diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-11-22 00:14:46 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-11-22 00:14:46 +0300 |
commit | a3e6d34643e760d1a8b8bd1e7e32d8d74c1ea678 (patch) | |
tree | 1228f600e98bfe626c313ffa61a60a4b7d162426 /app/assets/javascripts/super_sidebar/components | |
parent | d5ff0674315196e88f48dc0838486b44cd005628 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/super_sidebar/components')
4 files changed, 109 insertions, 22 deletions
diff --git a/app/assets/javascripts/super_sidebar/components/scroll_scrim.vue b/app/assets/javascripts/super_sidebar/components/scroll_scrim.vue new file mode 100644 index 00000000000..0e849b08a39 --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/scroll_scrim.vue @@ -0,0 +1,72 @@ +<script> +export default { + name: 'ScrollScrim', + data() { + return { + topBoundaryVisible: true, + bottomBoundaryVisible: true, + }; + }, + computed: { + scrimClasses() { + return { + 'top-scrim-visible': !this.topBoundaryVisible, + 'bottom-scrim-visible gl-border-b': !this.bottomBoundaryVisible, + }; + }, + }, + mounted() { + this.observeScroll(); + }, + beforeDestroy() { + this.scrollObserver?.disconnect(); + }, + + methods: { + observeScroll() { + const root = this.$el; + + const options = { + rootMargin: '8px', + root, + threshold: 1.0, + }; + + this.scrollObserver?.disconnect(); + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + this[entry.target?.$__visibilityProp] = entry.isIntersecting; + }); + }, options); + + const topBoundary = this.$refs['top-boundary']; + const bottomBoundary = this.$refs['bottom-boundary']; + + topBoundary.$__visibilityProp = 'topBoundaryVisible'; + observer.observe(topBoundary); + + bottomBoundary.$__visibilityProp = 'bottomBoundaryVisible'; + observer.observe(bottomBoundary); + + this.scrollObserver = observer; + }, + }, +}; +</script> + +<template> + <div class="gl-scroll-scrim gl-overflow-auto" :class="scrimClasses"> + <div class="top-scrim-wrapper"> + <div class="top-scrim"></div> + </div> + <div ref="top-boundary"></div> + + <slot></slot> + + <div ref="bottom-boundary"></div> + <div class="bottom-scrim-wrapper"> + <div class="bottom-scrim"></div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue b/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue index c04addf5262..5f067621814 100644 --- a/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue +++ b/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue @@ -194,7 +194,7 @@ export default { /> <ul aria-labelledby="super-sidebar-context-header" - class="gl-p-0 gl-list-style-none" + class="gl-p-0 gl-mb-0 gl-list-style-none" data-testid="non-static-items-section" > <template v-for="item in nonStaticItems"> diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue index 8f95dd1dcec..ebdc0026539 100644 --- a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue +++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue @@ -20,6 +20,7 @@ import HelpCenter from './help_center.vue'; import SidebarMenu from './sidebar_menu.vue'; import SidebarPeekBehavior from './sidebar_peek_behavior.vue'; import SidebarHoverPeekBehavior from './sidebar_hover_peek_behavior.vue'; +import ScrollScrim from './scroll_scrim.vue'; export default { components: { @@ -30,6 +31,7 @@ export default { SidebarPeekBehavior, SidebarHoverPeekBehavior, SidebarPortalTarget, + ScrollScrim, TrialStatusWidget: () => import('ee_component/contextual_sidebar/components/trial_status_widget.vue'), TrialStatusPopover: () => @@ -202,7 +204,7 @@ export default { <div class="contextual-nav gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-overflow-hidden" > - <div class="gl-flex-grow-1 gl-overflow-auto" data-testid="nav-container"> + <scroll-scrim class="gl-flex-grow-1" data-testid="nav-container"> <div id="super-sidebar-context-header" class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header" @@ -218,8 +220,8 @@ export default { :update-pins-url="sidebarData.update_pins_url" /> <sidebar-portal-target /> - </div> - <div class="gl-p-3"> + </scroll-scrim> + <div class="gl-p-2"> <help-center ref="helpCenter" :sidebar-data="sidebarData" /> <gl-button v-if="sidebarData.is_admin" diff --git a/app/assets/javascripts/super_sidebar/components/user_menu.vue b/app/assets/javascripts/super_sidebar/components/user_menu.vue index ef4ba8d9056..2823aeaee7b 100644 --- a/app/assets/javascripts/super_sidebar/components/user_menu.vue +++ b/app/assets/javascripts/super_sidebar/components/user_menu.vue @@ -5,11 +5,13 @@ import { GlDisclosureDropdownGroup, GlDisclosureDropdownItem, GlButton, + GlModalDirective, } from '@gitlab/ui'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { s__, __, sprintf } from '~/locale'; import Tracking from '~/tracking'; import PersistentUserCallout from '~/persistent_user_callout'; +import { SET_STATUS_MODAL_ID } from '~/set_status_modal/constants'; import { USER_MENU_TRACKING_DEFAULTS, DROPDOWN_Y_OFFSET, IMPERSONATING_OFFSET } from '../constants'; import UserMenuProfileItem from './user_menu_profile_item.vue'; @@ -18,6 +20,7 @@ const DROPDOWN_X_OFFSET_BASE = -211; const DROPDOWN_X_OFFSET_IMPERSONATING = DROPDOWN_X_OFFSET_BASE + IMPERSONATING_OFFSET; export default { + SET_STATUS_MODAL_ID, i18n: { setStatus: s__('SetStatusModal|Set status'), editStatus: s__('SetStatusModal|Edit status'), @@ -36,9 +39,14 @@ export default { GlDisclosureDropdownItem, GlButton, UserMenuProfileItem, + SetStatusModal: () => + import( + /* webpackChunkName: 'statusModalBundle' */ '~/set_status_modal/set_status_modal_wrapper.vue' + ), }, directives: { SafeHtml, + GlModal: GlModalDirective, }, mixins: [Tracking.mixin()], inject: ['isImpersonating'], @@ -48,6 +56,11 @@ export default { type: Object, }, }, + data() { + return { + setStatusModalReady: false, + }; + }, computed: { toggleText() { return sprintf(__('%{user} user’s menu'), { user: this.data.name }); @@ -61,7 +74,8 @@ export default { return { text: statusLabel, extraAttrs: { - class: 'js-set-status-modal-trigger', + ...USER_MENU_TRACKING_DEFAULTS, + 'data-track-label': 'user_edit_status', }, }; }, @@ -140,24 +154,22 @@ export default { }; }, statusModalData() { - const defaultData = { - 'data-current-emoji': '', - 'data-current-message': '', - 'data-default-emoji': 'speech_balloon', - }; + if (!this.data?.status?.can_update) { + return null; + } const { busy, customized } = this.data.status; if (!busy && !customized) { - return defaultData; + return {}; } + const { emoji, message, availability, clear_after: clearAfter } = this.data.status; return { - ...defaultData, - 'data-current-emoji': this.data.status.emoji, - 'data-current-message': this.data.status.message, - 'data-current-availability': this.data.status.availability, - 'data-current-clear-status-after': this.data.status.clear_after, + 'current-emoji': emoji || '', + 'current-message': message || '', + 'current-availability': availability || '', + 'current-clear-status-after': clearAfter || '', }; }, buyPipelineMinutesCalloutData() { @@ -248,7 +260,8 @@ export default { <gl-disclosure-dropdown-group bordered> <gl-disclosure-dropdown-item - v-if="data.status.can_update" + v-if="setStatusModalReady && statusModalData" + v-gl-modal="$options.SET_STATUS_MODAL_ID" :item="statusItem" data-testid="status-item" @action="closeDropdown" @@ -304,11 +317,11 @@ export default { @action="trackSignOut" /> </gl-disclosure-dropdown> - - <div - v-if="data.status.can_update" - class="js-set-status-modal-wrapper" + <set-status-modal + v-if="statusModalData" + default-emoji="speech_balloon" v-bind="statusModalData" - ></div> + @mounted="setStatusModalReady = true" + /> </div> </template> |