Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-20 13:43:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-20 13:43:29 +0300
commit3b1af5cc7ed2666ff18b718ce5d30fa5a2756674 (patch)
tree3bc4a40e0ee51ec27eabf917c537033c0c5b14d4 /app/assets/javascripts/super_sidebar
parent9bba14be3f2c211bf79e15769cd9b77bc73a13bc (diff)
Add latest changes from gitlab-org/gitlab@16-1-stable-eev16.1.0-rc42
Diffstat (limited to 'app/assets/javascripts/super_sidebar')
-rw-r--r--app/assets/javascripts/super_sidebar/components/brand_logo.vue45
-rw-r--r--app/assets/javascripts/super_sidebar/components/context_switcher.vue6
-rw-r--r--app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue2
-rw-r--r--app/assets/javascripts/super_sidebar/components/create_menu.vue18
-rw-r--r--app/assets/javascripts/super_sidebar/components/frequent_items_list.vue24
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/command_palette/command_palette_items.vue191
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/command_palette/constants.js45
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/command_palette/fake_search_input.vue42
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/command_palette/search_item.vue57
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/command_palette/utils.js47
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue56
-rw-r--r--app/assets/javascripts/super_sidebar/components/groups_list.vue4
-rw-r--r--app/assets/javascripts/super_sidebar/components/help_center.vue39
-rw-r--r--app/assets/javascripts/super_sidebar/components/items_list.vue19
-rw-r--r--app/assets/javascripts/super_sidebar/components/menu_section.vue2
-rw-r--r--app/assets/javascripts/super_sidebar/components/nav_item.vue15
-rw-r--r--app/assets/javascripts/super_sidebar/components/projects_list.vue4
-rw-r--r--app/assets/javascripts/super_sidebar/components/sidebar_menu.vue11
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_bar.vue27
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_menu.vue14
-rw-r--r--app/assets/javascripts/super_sidebar/popper_max_size_modifier.js43
-rw-r--r--app/assets/javascripts/super_sidebar/super_sidebar_bundle.js6
-rw-r--r--app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js2
23 files changed, 558 insertions, 161 deletions
diff --git a/app/assets/javascripts/super_sidebar/components/brand_logo.vue b/app/assets/javascripts/super_sidebar/components/brand_logo.vue
new file mode 100644
index 00000000000..c017fa8afa2
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/brand_logo.vue
@@ -0,0 +1,45 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+import logo from '../../../../views/shared/_logo.svg?raw';
+
+export default {
+ logo,
+ i18n: {
+ homepage: __('Homepage'),
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ inject: ['rootPath'],
+ props: {
+ logoUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+};
+</script>
+
+<template>
+ <a
+ v-gl-tooltip:super-sidebar.hover.bottom="$options.i18n.homepage"
+ class="tanuki-logo-container"
+ :href="rootPath"
+ :title="$options.i18n.homepage"
+ data-track-action="click_link"
+ data-track-label="gitlab_logo_link"
+ data-track-property="nav_core_menu"
+ >
+ <img
+ v-if="logoUrl"
+ data-testid="brand-header-custom-logo"
+ :src="logoUrl"
+ class="gl-h-6 gl-max-w-full"
+ />
+ <span v-else v-safe-html="$options.logo" data-testid="brand-header-default-logo"></span>
+ </a>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/components/context_switcher.vue b/app/assets/javascripts/super_sidebar/components/context_switcher.vue
index ad2111140a1..c5f3410a68f 100644
--- a/app/assets/javascripts/super_sidebar/components/context_switcher.vue
+++ b/app/assets/javascripts/super_sidebar/components/context_switcher.vue
@@ -5,7 +5,6 @@ import { s__ } from '~/locale';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import searchUserProjectsAndGroups from '../graphql/queries/search_user_groups_and_projects.query.graphql';
import { trackContextAccess, formatContextSwitcherItems } from '../utils';
-import { maxSize, applyMaxSize } from '../popper_max_size_modifier';
import NavItem from './nav_item.vue';
import ProjectsList from './projects_list.vue';
import GroupsList from './groups_list.vue';
@@ -142,9 +141,6 @@ export default {
},
},
DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
- popperOptions: {
- modifiers: [maxSize, applyMaxSize],
- },
};
</script>
@@ -153,7 +149,6 @@ export default {
ref="disclosure-dropdown"
class="context-switcher gl-w-full"
placement="center"
- :popper-options="$options.popperOptions"
@shown="onDisclosureDropdownShown"
@hidden="onDisclosureDropdownHidden"
>
@@ -194,6 +189,7 @@ export default {
:key="item.link"
:item="item"
:link-classes="{ [item.link_classes]: item.link_classes }"
+ is-subitem
/>
</ul>
</li>
diff --git a/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue b/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue
index cfb7e7732e9..17227a2b123 100644
--- a/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue
+++ b/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue
@@ -34,7 +34,7 @@ export default {
<template>
<button
type="button"
- class="context-switcher-toggle gl-p-0 gl-bg-transparent gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-border-0 border-top border-bottom gl-border-gray-a-08 gl-box-shadow-none gl-display-flex gl-align-items-center gl-font-weight-bold gl-w-full gl-h-8 gl-flex-shrink-0"
+ class="context-switcher-toggle gl-p-0 gl-bg-transparent gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-border-0 border-top border-bottom gl-border-gray-a-08! gl-box-shadow-none gl-display-flex gl-align-items-center gl-font-weight-bold gl-w-full gl-h-8 gl-flex-shrink-0"
data-qa-selector="context_switcher"
>
<span
diff --git a/app/assets/javascripts/super_sidebar/components/create_menu.vue b/app/assets/javascripts/super_sidebar/components/create_menu.vue
index fa6056aff5e..0ce856c9af8 100644
--- a/app/assets/javascripts/super_sidebar/components/create_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/create_menu.vue
@@ -42,21 +42,9 @@ export default {
isInvitedMembers(groupItem) {
return groupItem.component === TOP_NAV_INVITE_MEMBERS_COMPONENT;
},
- closeAndFocus() {
- this.$refs.dropdown.closeAndFocus();
- },
},
toggleId: 'create-menu-toggle',
- popperOptions: {
- modifiers: [
- {
- name: 'offset',
- options: {
- offset: [DROPDOWN_X_OFFSET, DROPDOWN_Y_OFFSET],
- },
- },
- ],
- },
+ dropdownOffset: { mainAxis: DROPDOWN_Y_OFFSET, crossAxis: DROPDOWN_X_OFFSET },
TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN,
};
</script>
@@ -64,14 +52,13 @@ export default {
<template>
<div>
<gl-disclosure-dropdown
- ref="dropdown"
category="tertiary"
icon="plus"
no-caret
text-sr-only
:toggle-text="$options.i18n.createNew"
:toggle-id="$options.toggleId"
- :popper-options="$options.popperOptions"
+ :dropdown-offset="$options.dropdownOffset"
data-qa-selector="new_menu_toggle"
data-testid="new-menu-toggle"
@shown="dropdownOpen = true"
@@ -89,7 +76,6 @@ export default {
:key="`${groupItem.text}-trigger`"
trigger-source="top-nav"
:trigger-element="$options.TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN"
- @modal-opened="closeAndFocus"
/>
<gl-disclosure-dropdown-item v-else :key="groupItem.text" :item="groupItem" />
</template>
diff --git a/app/assets/javascripts/super_sidebar/components/frequent_items_list.vue b/app/assets/javascripts/super_sidebar/components/frequent_items_list.vue
index 11bf2ddbd30..02adebc50af 100644
--- a/app/assets/javascripts/super_sidebar/components/frequent_items_list.vue
+++ b/app/assets/javascripts/super_sidebar/components/frequent_items_list.vue
@@ -1,13 +1,19 @@
<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import AccessorUtilities from '~/lib/utils/accessor';
+import { __ } from '~/locale';
import { getTopFrequentItems, formatContextSwitcherItems } from '../utils';
import ItemsList from './items_list.vue';
export default {
components: {
+ GlButton,
ItemsList,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
title: {
type: String,
@@ -68,6 +74,9 @@ export default {
}
},
},
+ i18n: {
+ removeItem: __('Remove'),
+ },
};
</script>
@@ -87,7 +96,20 @@ export default {
>
{{ pristineText }}
</div>
- <items-list :aria-label="title" :items="cachedFrequentItems" @remove-item="handleItemRemove">
+ <items-list :aria-label="title" :items="cachedFrequentItems">
+ <template #actions="{ item }">
+ <gl-button
+ v-gl-tooltip.right.viewport
+ size="small"
+ category="tertiary"
+ icon="dash"
+ :aria-label="$options.i18n.removeItem"
+ :title="$options.i18n.removeItem"
+ class="gl-align-self-center gl-mr-2"
+ data-testid="item-remove"
+ @click.stop.prevent="handleItemRemove(item)"
+ />
+ </template>
<template #view-all-items>
<slot name="view-all-items"></slot>
</template>
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/command_palette/command_palette_items.vue b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/command_palette_items.vue
new file mode 100644
index 00000000000..96e6c9bab9e
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/command_palette_items.vue
@@ -0,0 +1,191 @@
+<script>
+import { debounce } from 'lodash';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { GlDisclosureDropdownGroup, GlLoadingIcon } from '@gitlab/ui';
+import axios from '~/lib/utils/axios_utils';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import { getFormattedItem } from '../utils';
+import {
+ COMMON_HANDLES,
+ COMMAND_HANDLE,
+ USER_HANDLE,
+ PROJECT_HANDLE,
+ ISSUE_HANDLE,
+ GLOBAL_COMMANDS_GROUP_TITLE,
+ PAGES_GROUP_TITLE,
+ GROUP_TITLES,
+} from './constants';
+import SearchItem from './search_item.vue';
+import { commandMapper, linksReducer, autocompleteQuery } from './utils';
+
+export default {
+ name: 'CommandPaletteItems',
+ components: {
+ GlDisclosureDropdownGroup,
+ GlLoadingIcon,
+ SearchItem,
+ },
+ inject: ['commandPaletteCommands', 'commandPaletteLinks', 'autocompletePath', 'searchContext'],
+ props: {
+ searchQuery: {
+ type: String,
+ required: true,
+ },
+ handle: {
+ type: String,
+ required: true,
+ validator: (value) => {
+ return COMMON_HANDLES.includes(value);
+ },
+ },
+ },
+ data: () => ({
+ groups: [],
+ error: null,
+ loading: false,
+ }),
+ computed: {
+ isCommandMode() {
+ return this.handle === COMMAND_HANDLE;
+ },
+ isUserMode() {
+ return this.handle === USER_HANDLE;
+ },
+ commands() {
+ return this.commandPaletteCommands.map(commandMapper);
+ },
+ links() {
+ return this.commandPaletteLinks.reduce(linksReducer, []);
+ },
+ filteredCommands() {
+ return this.searchQuery
+ ? this.commands
+ .map(({ name, items }) => {
+ return {
+ name: name || GLOBAL_COMMANDS_GROUP_TITLE,
+ items: this.filterBySearchQuery(items, 'text'),
+ };
+ })
+ .filter(({ items }) => items.length)
+ : this.commands;
+ },
+ hasResults() {
+ return this.groups?.length && this.groups.some((group) => group.items?.length);
+ },
+ hasSearchQuery() {
+ if (this.isCommandMode) {
+ return this.searchQuery?.length > 0;
+ }
+ return this.searchQuery?.length > 2;
+ },
+ searchTerm() {
+ if (this.handle === ISSUE_HANDLE) {
+ return `${ISSUE_HANDLE}${this.searchQuery}`;
+ }
+ return this.searchQuery;
+ },
+ },
+ watch: {
+ searchQuery: {
+ handler() {
+ switch (this.handle) {
+ case COMMAND_HANDLE:
+ this.getCommandsAndPages();
+ break;
+ case USER_HANDLE:
+ case PROJECT_HANDLE:
+ case ISSUE_HANDLE:
+ this.getScopedItems();
+ break;
+ default:
+ break;
+ }
+ },
+ immediate: true,
+ },
+ },
+ methods: {
+ filterBySearchQuery(items, key = 'keywords') {
+ return fuzzaldrinPlus.filter(items, this.searchQuery, { key });
+ },
+ getCommandsAndPages() {
+ if (!this.searchQuery) {
+ this.groups = [...this.commands];
+ return;
+ }
+ const matchedLinks = this.filterBySearchQuery(this.links);
+
+ if (this.filteredCommands.length || matchedLinks.length) {
+ this.groups = [];
+ }
+
+ if (this.filteredCommands.length) {
+ this.groups = [...this.filteredCommands];
+ }
+
+ if (matchedLinks.length) {
+ this.groups.push({
+ name: PAGES_GROUP_TITLE,
+ items: matchedLinks,
+ });
+ }
+ },
+ getScopedItems: debounce(function debouncedSearch() {
+ if (this.searchQuery && this.searchQuery.length < 3) return null;
+
+ this.loading = true;
+
+ return axios
+ .get(
+ autocompleteQuery({
+ path: this.autocompletePath,
+ searchTerm: this.searchTerm,
+ handle: this.handle,
+ projectId: this.searchContext.project?.id,
+ }),
+ )
+ .then(({ data }) => {
+ this.groups = this.getGroups(data);
+ })
+ .catch((error) => {
+ this.error = error;
+ })
+ .finally(() => {
+ this.loading = false;
+ });
+ }, DEFAULT_DEBOUNCE_AND_THROTTLE_MS),
+ getGroups(data) {
+ return [
+ {
+ name: GROUP_TITLES[this.handle],
+ items: data.map(getFormattedItem),
+ },
+ ];
+ },
+ },
+};
+</script>
+
+<template>
+ <ul class="gl-p-0 gl-m-0 gl-list-style-none">
+ <gl-loading-icon v-if="loading" size="lg" class="gl-my-5" />
+
+ <template v-else-if="hasResults">
+ <gl-disclosure-dropdown-group
+ v-for="(group, index) in groups"
+ :key="index"
+ :group="group"
+ bordered
+ class="{'gl-mt-0!': index===0}"
+ >
+ <template #list-item="{ item }">
+ <search-item :item="item" :search-query="searchQuery" />
+ </template>
+ </gl-disclosure-dropdown-group>
+ </template>
+
+ <div v-else-if="hasSearchQuery && !hasResults" class="gl-text-gray-700 gl-pl-5 gl-py-3">
+ {{ __('No results found') }}
+ </div>
+ </ul>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/command_palette/constants.js b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/constants.js
new file mode 100644
index 00000000000..9dab16984f5
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/constants.js
@@ -0,0 +1,45 @@
+import { s__, sprintf } from '~/locale';
+
+export const COMMAND_HANDLE = '>';
+export const USER_HANDLE = '@';
+export const PROJECT_HANDLE = '&';
+export const ISSUE_HANDLE = '#';
+
+export const COMMON_HANDLES = [COMMAND_HANDLE, USER_HANDLE, PROJECT_HANDLE, ISSUE_HANDLE];
+export const SEARCH_OR_COMMAND_MODE_PLACEHOLDER = sprintf(
+ s__(
+ 'CommandPalette|Type %{commandHandle} for command, %{userHandle} for user, %{projectHandle} for project, %{issueHandle} for issue or perform generic search...',
+ ),
+ {
+ commandHandle: COMMAND_HANDLE,
+ userHandle: USER_HANDLE,
+ issueHandle: ISSUE_HANDLE,
+ projectHandle: PROJECT_HANDLE,
+ },
+ false,
+);
+
+export const SEARCH_SCOPE_PLACEHOLDER = {
+ [COMMAND_HANDLE]: s__('CommandPalette|command'),
+ [USER_HANDLE]: s__('CommandPalette|user (enter at least 3 chars)'),
+ [PROJECT_HANDLE]: s__('CommandPalette|project (enter at least 3 chars)'),
+ [ISSUE_HANDLE]: s__('CommandPalette|issue (enter at least 3 chars)'),
+};
+
+export const SEARCH_SCOPE = {
+ [USER_HANDLE]: 'user',
+ [PROJECT_HANDLE]: 'project',
+ [ISSUE_HANDLE]: 'issue',
+};
+
+export const GLOBAL_COMMANDS_GROUP_TITLE = s__('CommandPalette|Global Commands');
+export const USERS_GROUP_TITLE = s__('GlobalSearch|Users');
+export const PAGES_GROUP_TITLE = s__('CommandPalette|Pages');
+export const PROJECTS_GROUP_TITLE = s__('GlobalSearch|Projects');
+export const ISSUE_GROUP_TITLE = s__('GlobalSearch|Recent issues');
+
+export const GROUP_TITLES = {
+ [USER_HANDLE]: USERS_GROUP_TITLE,
+ [PROJECT_HANDLE]: PROJECTS_GROUP_TITLE,
+ [ISSUE_HANDLE]: ISSUE_GROUP_TITLE,
+};
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/command_palette/fake_search_input.vue b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/fake_search_input.vue
new file mode 100644
index 00000000000..dce2b24f551
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/fake_search_input.vue
@@ -0,0 +1,42 @@
+<script>
+import { COMMON_HANDLES, SEARCH_SCOPE_PLACEHOLDER } from './constants';
+
+export default {
+ name: 'FakeSearchInput',
+ props: {
+ userInput: {
+ type: String,
+ required: true,
+ },
+ scope: {
+ type: String,
+ required: true,
+ validator: (value) => COMMON_HANDLES.includes(value),
+ },
+ },
+ computed: {
+ placeholder() {
+ return SEARCH_SCOPE_PLACEHOLDER[this.scope];
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-pointer-events-none fake-input">
+ <span class="gl-opacity-0" data-testid="search-scope">{{ scope }}&nbsp;</span>
+ <span
+ v-if="!userInput"
+ data-testid="search-scope-placeholder"
+ class="gl-text-gray-500 gl-pointer-events-none"
+ >{{ placeholder }}</span
+ >
+ </div>
+</template>
+
+<style scoped>
+.fake-input {
+ top: 12px;
+ left: 33px;
+}
+</style>
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/command_palette/search_item.vue b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/search_item.vue
new file mode 100644
index 00000000000..b940c7c24c6
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/search_item.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlAvatar, GlIcon } from '@gitlab/ui';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+import highlight from '~/lib/utils/highlight';
+import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
+
+export default {
+ name: 'CommandPaletteSearchItem',
+ components: {
+ GlAvatar,
+ GlIcon,
+ },
+ directives: {
+ SafeHtml,
+ },
+ props: {
+ item: {
+ type: Object,
+ required: true,
+ },
+ searchQuery: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ highlightedName() {
+ return highlight(this.item.text, this.searchQuery);
+ },
+ },
+ AVATAR_SHAPE_OPTION_RECT,
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-avatar
+ v-if="item.avatar_url !== undefined"
+ class="gl-mr-3"
+ :src="item.avatar_url"
+ :entity-id="item.entity_id"
+ :entity-name="item.entity_name"
+ :size="item.avatar_size"
+ :shape="$options.AVATAR_SHAPE_OPTION_RECT"
+ aria-hidden="true"
+ />
+ <gl-icon v-if="item.icon" class="gl-mr-3" :name="item.icon" />
+ <span class="gl-display-flex gl-flex-direction-column">
+ <span v-safe-html="highlightedName" class="gl-text-gray-900"></span>
+ <span
+ v-if="item.namespace"
+ v-safe-html="item.namespace"
+ class="gl-font-sm gl-text-gray-500"
+ ></span>
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/command_palette/utils.js b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/utils.js
new file mode 100644
index 00000000000..5c8c0e59eaf
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/global_search/command_palette/utils.js
@@ -0,0 +1,47 @@
+import { isNil, omitBy } from 'lodash';
+import { objectToQuery } from '~/lib/utils/url_utility';
+import { SEARCH_SCOPE } from './constants';
+
+export const commandMapper = ({ name, items }) => {
+ // TODO: we filter out invite_members for now, because it is complicated to add the invite members modal here
+ // and is out of scope for the basic command palette items. If it proves to be useful, we can add it later.
+ return {
+ name,
+ items: items.filter(({ component }) => component !== 'invite_members'),
+ };
+};
+
+export const linksReducer = (acc, menuItem) => {
+ acc.push({
+ text: menuItem.title,
+ keywords: menuItem.title,
+ icon: menuItem.icon,
+ href: menuItem.link,
+ });
+ if (menuItem.items?.length) {
+ const items = menuItem.items.map(({ title, link }) => ({
+ keywords: title,
+ text: [menuItem.title, title].join(' > '),
+ href: link,
+ icon: menuItem.icon,
+ }));
+
+ /* eslint-disable-next-line no-param-reassign */
+ acc = [...acc, ...items];
+ }
+ return acc;
+};
+
+export const autocompleteQuery = ({ path, searchTerm, handle, projectId }) => {
+ const query = omitBy(
+ {
+ term: searchTerm,
+ project_id: projectId,
+ filter: 'search',
+ scope: SEARCH_SCOPE[handle],
+ },
+ isNil,
+ );
+
+ return `${path}?${objectToQuery(query)}`;
+};
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue b/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue
index 55c28661440..cb34f2b8c26 100644
--- a/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue
+++ b/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue
@@ -24,6 +24,7 @@ import {
SEARCH_RESULTS_LOADING,
SEARCH_RESULTS_SCOPE,
} from '~/vue_shared/global_search/constants';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
SEARCH_INPUT_DESCRIPTION,
SEARCH_RESULTS_DESCRIPTION,
@@ -35,6 +36,9 @@ import {
SEARCH_INPUT_SELECTOR,
SEARCH_RESULTS_ITEM_SELECTOR,
} from '../constants';
+import CommandPaletteItems from '../command_palette/command_palette_items.vue';
+import FakeSearchInput from '../command_palette/fake_search_input.vue';
+import { COMMON_HANDLES, SEARCH_OR_COMMAND_MODE_PLACEHOLDER } from '../command_palette/constants';
import GlobalSearchAutocompleteItems from './global_search_autocomplete_items.vue';
import GlobalSearchDefaultItems from './global_search_default_items.vue';
import GlobalSearchScopedItems from './global_search_scoped_items.vue';
@@ -60,7 +64,10 @@ export default {
GlIcon,
GlToken,
GlModal,
+ CommandPaletteItems,
+ FakeSearchInput,
},
+ mixins: [glFeatureFlagMixin()],
computed: {
...mapState(['search', 'loading', 'searchContext']),
...mapGetters(['searchQuery', 'searchOptions', 'scopedSearchOptions']),
@@ -72,6 +79,9 @@ export default {
this.setSearch(value);
},
},
+ searchPlaceholder() {
+ return this.glFeatures?.commandPalette ? SEARCH_OR_COMMAND_MODE_PLACEHOLDER : SEARCH_GITLAB;
+ },
showDefaultItems() {
return !this.searchText;
},
@@ -104,7 +114,7 @@ export default {
};
},
showScopeHelp() {
- return this.searchTermOverMin;
+ return this.searchTermOverMin && !this.isCommandMode;
},
searchBarItem() {
return this.searchOptions?.[0];
@@ -120,10 +130,26 @@ export default {
scope: this.infieldHelpContent,
});
},
+
+ searchTextFirstChar() {
+ return this.searchText?.trim().charAt(0);
+ },
+ isCommandMode() {
+ return this.glFeatures?.commandPalette && COMMON_HANDLES.includes(this.searchTextFirstChar);
+ },
+ commandPaletteQuery() {
+ if (this.isCommandMode) {
+ return this.searchText?.trim().substring(1);
+ }
+ return '';
+ },
},
methods: {
...mapActions(['setSearch', 'fetchAutocompleteOptions', 'clearAutocomplete']),
getAutocompleteOptions: debounce(function debouncedSearch(searchTerm) {
+ if (this.isCommandMode) {
+ return;
+ }
if (!searchTerm) {
this.clearAutocomplete();
} else {
@@ -222,12 +248,12 @@ export default {
>
<form
role="search"
- :aria-label="$options.i18n.SEARCH_GITLAB"
+ :aria-label="searchPlaceholder"
class="gl-relative gl-rounded-base gl-w-full"
:class="searchBarClasses"
data-testid="global-search-form"
>
- <div class="gl-p-1">
+ <div class="gl-p-1 gl-relative">
<gl-search-box-by-type
id="search"
ref="searchInputBox"
@@ -236,7 +262,7 @@ export default {
data-testid="global-search-input"
data-qa-selector="global_search_input"
autocomplete="off"
- :placeholder="$options.i18n.SEARCH_GITLAB"
+ :placeholder="searchPlaceholder"
:aria-describedby="$options.SEARCH_INPUT_DESCRIPTION"
borderless
@input="getAutocompleteOptions"
@@ -266,6 +292,13 @@ export default {
<span :id="$options.SEARCH_INPUT_DESCRIPTION" role="region" class="gl-sr-only">
{{ $options.i18n.SEARCH_DESCRIBED_BY_WITH_RESULTS }}
</span>
+
+ <fake-search-input
+ v-if="isCommandMode"
+ :user-input="commandPaletteQuery"
+ :scope="searchTextFirstChar"
+ class="gl-absolute"
+ />
</div>
<span
role="region"
@@ -282,13 +315,20 @@ export default {
class="global-search-results gl-overflow-y-auto gl-w-full gl-pb-2"
@keydown="onKeydown"
>
- <global-search-default-items v-if="showDefaultItems" />
+ <command-palette-items
+ v-if="isCommandMode"
+ :search-query="commandPaletteQuery"
+ :handle="searchTextFirstChar"
+ />
+
<template v-else>
- <global-search-scoped-items v-if="showScopedSearchItems" />
- <global-search-autocomplete-items />
+ <global-search-default-items v-if="showDefaultItems" />
+ <template v-else>
+ <global-search-scoped-items v-if="showScopedSearchItems" />
+ <global-search-autocomplete-items />
+ </template>
</template>
</div>
-
<template v-if="searchContext">
<input
v-if="searchContext.group"
diff --git a/app/assets/javascripts/super_sidebar/components/groups_list.vue b/app/assets/javascripts/super_sidebar/components/groups_list.vue
index 4fa15f1cd76..48becacebb7 100644
--- a/app/assets/javascripts/super_sidebar/components/groups_list.vue
+++ b/app/assets/javascripts/super_sidebar/components/groups_list.vue
@@ -64,7 +64,7 @@ export default {
:search-results="searchResults"
>
<template #view-all-items>
- <nav-item v-bind="viewAllProps" />
+ <nav-item v-bind="viewAllProps" is-subitem />
</template>
</search-results>
<frequent-items-list
@@ -75,7 +75,7 @@ export default {
:pristine-text="$options.i18n.pristineText"
>
<template #view-all-items>
- <nav-item v-bind="viewAllProps" />
+ <nav-item v-bind="viewAllProps" is-subitem />
</template>
</frequent-items-list>
</template>
diff --git a/app/assets/javascripts/super_sidebar/components/help_center.vue b/app/assets/javascripts/super_sidebar/components/help_center.vue
index 1fffbb05d03..1d4c24c6853 100644
--- a/app/assets/javascripts/super_sidebar/components/help_center.vue
+++ b/app/assets/javascripts/super_sidebar/components/help_center.vue
@@ -8,7 +8,7 @@ import {
} from '@gitlab/ui';
import GitlabVersionCheckBadge from '~/gitlab_version_check/components/gitlab_version_check_badge.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { DOMAIN, PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
+import { FORUM_URL, DOCS_URL, PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import { STORAGE_KEY } from '~/whats_new/utils/notification';
import Tracking from '~/tracking';
@@ -70,7 +70,7 @@ export default {
helpLinks: {
items: [
this.sidebarData.show_tanuki_bot && {
- icon: 'tanuki',
+ icon: 'tanuki-ai',
text: this.$options.i18n.chat,
action: this.showTanukiBotChat,
extraAttrs: {
@@ -93,7 +93,7 @@ export default {
},
{
text: this.$options.i18n.docs,
- href: `https://docs.${DOMAIN}`,
+ href: DOCS_URL,
extraAttrs: {
...this.trackingAttrs('gitlab_documentation'),
},
@@ -107,7 +107,7 @@ export default {
},
{
text: this.$options.i18n.forum,
- href: `https://forum.${DOMAIN}/`,
+ href: FORUM_URL,
extraAttrs: {
...this.trackingAttrs('community_forum'),
},
@@ -132,7 +132,7 @@ export default {
items: [
{
text: this.$options.i18n.shortcuts,
- action: this.showKeyboardShortcuts,
+ action: () => {},
extraAttrs: {
class: 'js-shortcuts-modal-trigger',
'data-track-action': 'click_button',
@@ -172,18 +172,11 @@ export default {
return true;
},
- showKeyboardShortcuts() {
- this.$refs.dropdown.close();
- },
-
showTanukiBotChat() {
- this.$refs.dropdown.close();
-
this.helpCenterState.showTanukiBotChatDrawer = true;
},
async showWhatsNew() {
- this.$refs.dropdown.close();
this.showWhatsNewNotification = false;
if (!this.toggleWhatsNewDrawer) {
@@ -211,29 +204,23 @@ export default {
});
},
},
- popperOptions: {
- modifiers: [
- {
- name: 'offset',
- options: {
- offset: [DROPDOWN_X_OFFSET, DROPDOWN_Y_OFFSET],
- },
- },
- ],
- },
+ dropdownOffset: { mainAxis: DROPDOWN_Y_OFFSET, crossAxis: DROPDOWN_X_OFFSET },
};
</script>
<template>
<gl-disclosure-dropdown
- ref="dropdown"
- :popper-options="$options.popperOptions"
+ :dropdown-offset="$options.dropdownOffset"
@shown="trackDropdownToggle(true)"
@hidden="trackDropdownToggle(false)"
>
<template #toggle>
<gl-button category="tertiary" icon="question-o" class="btn-with-notification">
- <span v-if="showWhatsNewNotification" class="notification-dot-info"></span>
+ <span
+ v-if="showWhatsNewNotification"
+ data-testid="notification-dot"
+ class="notification-dot-info"
+ ></span>
{{ $options.i18n.help }}
</gl-button>
</template>
@@ -263,7 +250,7 @@ export default {
<template #list-item="{ item }">
<span class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
{{ item.text }}
- <gl-icon v-if="item.icon" :name="item.icon" class="gl-text-orange-500" />
+ <gl-icon v-if="item.icon" :name="item.icon" class="gl-text-purple-600" />
</span>
</template>
</gl-disclosure-dropdown-group>
diff --git a/app/assets/javascripts/super_sidebar/components/items_list.vue b/app/assets/javascripts/super_sidebar/components/items_list.vue
index ef27251dc6c..7d5af883651 100644
--- a/app/assets/javascripts/super_sidebar/components/items_list.vue
+++ b/app/assets/javascripts/super_sidebar/components/items_list.vue
@@ -1,17 +1,12 @@
<script>
-import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
import NavItem from './nav_item.vue';
export default {
components: {
- GlButton,
ProjectAvatar,
NavItem,
},
- directives: {
- GlTooltip: GlTooltipDirective,
- },
props: {
items: {
type: Array,
@@ -29,6 +24,7 @@ export default {
:key="item.id"
:item="item"
:link-classes="{ 'gl-py-2!': true }"
+ is-subitem
>
<template #icon>
<project-avatar
@@ -37,20 +33,11 @@ export default {
:project-avatar-url="item.avatar"
:size="24"
aria-hidden="true"
+ class="gl-mr-n2"
/>
</template>
<template #actions>
- <gl-button
- v-gl-tooltip.right.viewport
- size="small"
- category="tertiary"
- icon="dash"
- :aria-label="__('Remove')"
- :title="__('Remove')"
- class="gl-align-self-center gl-p-1! gl-absolute gl-right-4"
- data-testid="item-remove"
- @click.stop.prevent="$emit('remove-item', item)"
- />
+ <slot name="actions" :item="item"></slot>
</template>
</nav-item>
<slot name="view-all-items"></slot>
diff --git a/app/assets/javascripts/super_sidebar/components/menu_section.vue b/app/assets/javascripts/super_sidebar/components/menu_section.vue
index 93c249dffeb..b5a8241a286 100644
--- a/app/assets/javascripts/super_sidebar/components/menu_section.vue
+++ b/app/assets/javascripts/super_sidebar/components/menu_section.vue
@@ -71,7 +71,7 @@ export default {
<component :is="tag">
<hr v-if="separated" aria-hidden="true" class="gl-mx-4 gl-my-2" />
<button
- class="gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-mb-1 gl-py-3 gl-px-0 gl-line-height-normal gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-appearance-none gl-border-0 gl-bg-transparent gl-text-left gl-w-full gl-focus--focus"
+ class="gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-line-height-normal gl-mb-2 gl-py-3 gl-px-0 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-appearance-none gl-border-0 gl-bg-transparent gl-text-left gl-w-full gl-focus--focus"
:class="computedLinkClasses"
data-qa-selector="menu_section_button"
:data-qa-section-name="item.title"
diff --git a/app/assets/javascripts/super_sidebar/components/nav_item.vue b/app/assets/javascripts/super_sidebar/components/nav_item.vue
index ec1c4069b1a..0ee9db10ee2 100644
--- a/app/assets/javascripts/super_sidebar/components/nav_item.vue
+++ b/app/assets/javascripts/super_sidebar/components/nav_item.vue
@@ -51,6 +51,11 @@ export default {
required: false,
default: () => ({}),
},
+ isSubitem: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
pillData() {
@@ -99,6 +104,7 @@ export default {
return {
'gl-py-2': this.isPinnable,
'gl-py-3': !this.isPinnable,
+ 'gl-mx-2': this.isSubitem,
[this.item.link_classes]: this.item.link_classes,
...this.linkClasses,
};
@@ -106,6 +112,9 @@ export default {
navItemLinkComponent() {
return this.item.to ? NavItemRouterLink : NavItemLink;
},
+ iconClasses() {
+ return this.isSubitem === true ? 'gl-ml-2 gl-mr-4' : 'gl-w-6 gl-mx-3';
+ },
},
};
</script>
@@ -128,7 +137,7 @@ export default {
style="width: 3px; border-radius: 3px; margin-right: 1px"
data-testid="active-indicator"
></div>
- <div class="gl-flex-shrink-0 gl-w-6 gl-mx-3">
+ <div :class="iconClasses" class="gl-flex-shrink-0">
<slot name="icon">
<gl-icon v-if="item.icon" :name="item.icon" class="gl-ml-2 item-icon" />
<gl-icon
@@ -138,14 +147,14 @@ export default {
/>
</slot>
</div>
- <div class="gl-pr-8 gl-text-gray-900 gl-truncate-end">
+ <div class="gl-flex-grow-1 gl-text-gray-900 gl-truncate-end">
{{ item.title }}
<div v-if="item.subtitle" class="gl-font-sm gl-text-gray-500 gl-truncate-end">
{{ item.subtitle }}
</div>
</div>
<slot name="actions"></slot>
- <span v-if="hasPill || isPinnable" class="gl-flex-grow-1 gl-text-right gl-mr-3 gl-relative">
+ <span v-if="hasPill || isPinnable" class="gl-text-right gl-mr-3 gl-relative">
<gl-badge
v-if="hasPill"
size="sm"
diff --git a/app/assets/javascripts/super_sidebar/components/projects_list.vue b/app/assets/javascripts/super_sidebar/components/projects_list.vue
index 78860e35eb1..8d1a5c825b5 100644
--- a/app/assets/javascripts/super_sidebar/components/projects_list.vue
+++ b/app/assets/javascripts/super_sidebar/components/projects_list.vue
@@ -65,7 +65,7 @@ export default {
:search-results="searchResults"
>
<template #view-all-items>
- <nav-item v-bind="viewAllProps" />
+ <nav-item v-bind="viewAllProps" is-subitem />
</template>
</search-results>
<frequent-items-list
@@ -76,7 +76,7 @@ export default {
:pristine-text="$options.i18n.pristineText"
>
<template #view-all-items>
- <nav-item v-bind="viewAllProps" />
+ <nav-item v-bind="viewAllProps" is-subitem />
</template>
</frequent-items-list>
</template>
diff --git a/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue b/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue
index 08af9232107..287e4f57d01 100644
--- a/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/sidebar_menu.vue
@@ -1,6 +1,7 @@
<script>
import * as Sentry from '@sentry/browser';
import axios from '~/lib/utils/axios_utils';
+import { s__ } from '~/locale';
import { PANELS_WITH_PINS } from '../constants';
import NavItem from './nav_item.vue';
import PinnedSection from './pinned_section.vue';
@@ -42,6 +43,10 @@ export default {
},
},
+ i18n: {
+ mainNavigation: s__('Navigation|Main navigation'),
+ },
+
data() {
return {
// This is used as a provide and injected into the nav items.
@@ -137,8 +142,8 @@ export default {
</script>
<template>
- <nav class="gl-p-2 gl-relative">
- <ul v-if="hasStaticItems" class="gl-p-0 gl-m-0">
+ <nav :aria-label="$options.i18n.mainNavigation" class="gl-p-2 gl-relative">
+ <ul v-if="hasStaticItems" class="gl-p-0 gl-m-0" data-testid="static-items-section">
<nav-item v-for="item in staticItems" :key="item.id" :item="item" is-static />
</ul>
<pinned-section
@@ -154,7 +159,7 @@ export default {
class="gl-my-2 gl-mx-4"
data-testid="main-menu-separator"
/>
- <ul class="gl-p-0 gl-list-style-none">
+ <ul class="gl-p-0 gl-list-style-none" data-testid="non-static-items-section">
<template v-for="item in nonStaticItems">
<menu-section
v-if="isSection(item)"
diff --git a/app/assets/javascripts/super_sidebar/components/user_bar.vue b/app/assets/javascripts/super_sidebar/components/user_bar.vue
index 768914584e8..d3b2143aaa7 100644
--- a/app/assets/javascripts/super_sidebar/components/user_bar.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_bar.vue
@@ -1,13 +1,12 @@
<script>
import { GlBadge, GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
-import SafeHtml from '~/vue_shared/directives/safe_html';
import {
destroyUserCountsManager,
createUserCountsManager,
userCounts,
} from '~/super_sidebar/user_counts_manager';
-import logo from '../../../../views/shared/_logo.svg';
+import BrandLogo from 'jh_else_ce/super_sidebar/components/brand_logo.vue';
import { JS_TOGGLE_COLLAPSE_CLASS } from '../constants';
import CreateMenu from './create_menu.vue';
import Counter from './counter.vue';
@@ -20,7 +19,6 @@ export default {
// "GitLab Next" is a proper noun, so don't translate "Next"
/* eslint-disable-next-line @gitlab/require-i18n-strings */
NEXT_LABEL: 'Next',
- logo,
JS_TOGGLE_COLLAPSE_CLASS,
SEARCH_MODAL_ID,
components: {
@@ -35,6 +33,7 @@ export default {
/* webpackChunkName: 'global_search_modal' */ './global_search/components/global_search.vue'
),
SuperSidebarToggle,
+ BrandLogo,
},
i18n: {
createNew: __('Create new...'),
@@ -53,9 +52,8 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective,
- SafeHtml,
},
- inject: ['rootPath', 'isImpersonating'],
+ inject: ['isImpersonating'],
props: {
hasCollapseButton: {
default: true,
@@ -107,23 +105,7 @@ export default {
<template>
<div class="user-bar">
<div class="gl-display-flex gl-align-items-center gl-px-3 gl-py-2">
- <a
- v-gl-tooltip:super-sidebar.hover.bottom="$options.i18n.homepage"
- class="tanuki-logo-container"
- :href="rootPath"
- :title="$options.i18n.homepage"
- data-track-action="click_link"
- data-track-label="gitlab_logo_link"
- data-track-property="nav_core_menu"
- >
- <img
- v-if="sidebarData.logo_url"
- data-testid="brand-header-custom-logo"
- :src="sidebarData.logo_url"
- class="gl-h-6"
- />
- <span v-else v-safe-html="$options.logo"></span>
- </a>
+ <brand-logo :logo-url="sidebarData.logo_url" />
<gl-badge
v-if="sidebarData.gitlab_com_and_canary"
variant="success"
@@ -168,6 +150,7 @@ export default {
category="tertiary"
data-method="delete"
data-testid="stop-impersonation-btn"
+ data-qa-selector="stop_impersonation_link"
/>
</div>
<div class="gl-display-flex gl-justify-content-space-between gl-px-3 gl-py-2 gl-gap-2">
diff --git a/app/assets/javascripts/super_sidebar/components/user_menu.vue b/app/assets/javascripts/super_sidebar/components/user_menu.vue
index cd5a83c86cc..7d4991fbe96 100644
--- a/app/assets/javascripts/super_sidebar/components/user_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_menu.vue
@@ -221,16 +221,7 @@ export default {
});
},
},
- popperOptions: {
- modifiers: [
- {
- name: 'offset',
- options: {
- offset: [DROPDOWN_X_OFFSET, DROPDOWN_Y_OFFSET],
- },
- },
- ],
- },
+ dropdownOffset: { mainAxis: DROPDOWN_Y_OFFSET, crossAxis: DROPDOWN_X_OFFSET },
};
</script>
@@ -238,9 +229,10 @@ export default {
<div>
<gl-disclosure-dropdown
ref="userDropdown"
- :popper-options="$options.popperOptions"
+ :dropdown-offset="$options.dropdownOffset"
data-testid="user-dropdown"
data-qa-selector="user_menu"
+ :auto-close="false"
@shown="onShow"
>
<template #toggle>
diff --git a/app/assets/javascripts/super_sidebar/popper_max_size_modifier.js b/app/assets/javascripts/super_sidebar/popper_max_size_modifier.js
deleted file mode 100644
index 6581d521107..00000000000
--- a/app/assets/javascripts/super_sidebar/popper_max_size_modifier.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { detectOverflow } from '@popperjs/core';
-
-/**
- * These modifiers were copied from the community modifier popper-max-size-modifier
- * https://www.npmjs.com/package/popper-max-size-modifier.
- * We are considering upgrading Popper.js to Floating UI, at which point the behavior this
- * introduces will be available out of the box.
- * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/2213
- */
-
-export const maxSize = {
- name: 'maxSize',
- enabled: true,
- phase: 'main',
- requiresIfExists: ['offset', 'preventOverflow', 'flip'],
- fn({ state, name }) {
- const overflow = detectOverflow(state);
- const { x, y } = state.modifiersData.preventOverflow || { x: 0, y: 0 };
- const { width, height } = state.rects.popper;
- const [basePlacement] = state.placement.split('-');
-
- const widthProp = basePlacement === 'left' ? 'left' : 'right';
- const heightProp = basePlacement === 'top' ? 'top' : 'bottom';
-
- state.modifiersData[name] = {
- width: width - overflow[widthProp] - x,
- height: height - overflow[heightProp] - y,
- };
- },
-};
-
-export const applyMaxSize = {
- name: 'applyMaxSize',
- enabled: true,
- phase: 'write',
- requires: ['maxSize'],
- fn({ state }) {
- // The `maxSize` modifier provides this data
- const { width, height } = state.modifiersData.maxSize;
- state.elements.popper.style.maxWidth = `${width}px`;
- state.elements.popper.style.maxHeight = `${height}px`;
- },
-};
diff --git a/app/assets/javascripts/super_sidebar/super_sidebar_bundle.js b/app/assets/javascripts/super_sidebar/super_sidebar_bundle.js
index 63424277ffc..f6afde02fa5 100644
--- a/app/assets/javascripts/super_sidebar/super_sidebar_bundle.js
+++ b/app/assets/javascripts/super_sidebar/super_sidebar_bundle.js
@@ -72,6 +72,8 @@ export const initSuperSidebar = () => {
const sidebarData = JSON.parse(sidebar);
const searchData = convertObjectPropsToCamelCase(sidebarData.search);
+ const commandPaletteCommands = sidebarData.create_new_menu_groups || [];
+ const commandPaletteLinks = convertObjectPropsToCamelCase(sidebarData.current_menu_items || []);
const { searchPath, issuesPath, mrPath, autocompletePath, searchContext } = searchData;
const isImpersonating = parseBoolean(sidebarData.is_impersonating);
@@ -85,6 +87,10 @@ export const initSuperSidebar = () => {
toggleNewNavEndpoint,
isImpersonating,
...getTrialStatusWidgetData(sidebarData),
+ commandPaletteCommands,
+ commandPaletteLinks,
+ autocompletePath,
+ searchContext,
},
store: createStore({
searchPath,
diff --git a/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js b/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js
index 1a359533435..2687ea5ccf8 100644
--- a/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js
+++ b/app/assets/javascripts/super_sidebar/super_sidebar_collapsed_state_manager.js
@@ -24,7 +24,7 @@ export const toggleSuperSidebarCollapsed = (collapsed, saveCookie) => {
findPage().classList.toggle(SIDEBAR_COLLAPSED_CLASS, collapsed);
sidebarState.isPeek = false;
- sidebarState.isPeekable = Boolean(gon.features?.superSidebarPeek) && collapsed;
+ sidebarState.isPeekable = collapsed;
sidebarState.isCollapsed = collapsed;
if (saveCookie && isDesktopBreakpoint()) {