diff options
Diffstat (limited to 'app/assets/javascripts/super_sidebar/components')
7 files changed, 364 insertions, 0 deletions
diff --git a/app/assets/javascripts/super_sidebar/components/bottom_bar.vue b/app/assets/javascripts/super_sidebar/components/bottom_bar.vue new file mode 100644 index 00000000000..fea29458f45 --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/bottom_bar.vue @@ -0,0 +1,24 @@ +<script> +import { GlIcon } from '@gitlab/ui'; +import { __ } from '~/locale'; + +export default { + components: { + GlIcon, + }, + i18n: { + help: __('Help'), + new: __('New'), + }, +}; +</script> + +<template> + <div class="bottom-links gl-p-3"> + <a href="#" class="gl-text-black-normal" + ><gl-icon name="question-o" class="gl-mr-3 gl-text-gray-300 gl-text-black-normal!" />{{ + $options.i18n.help + }}</a + > + </div> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/context_switcher.vue b/app/assets/javascripts/super_sidebar/components/context_switcher.vue new file mode 100644 index 00000000000..f1ddb8290a0 --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/context_switcher.vue @@ -0,0 +1,83 @@ +<script> +import { GlAvatar, GlSearchBoxByType } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { contextSwitcherItems } from '../mock_data'; +import NavItem from './nav_item.vue'; + +export default { + components: { + GlAvatar, + GlSearchBoxByType, + NavItem, + }, + i18n: { + contextNavigation: s__('Navigation|Context navigation'), + switchTo: s__('Navigation|Switch to...'), + recentProjects: s__('Navigation|Recent projects'), + recentGroups: s__('Navigation|Recent groups'), + }, + contextSwitcherItems, + viewAllProjectsItem: { + title: s__('Navigation|View all projects'), + link: '/projects', + icon: 'project', + }, + viewAllGroupsItem: { + title: s__('Navigation|View all groups'), + link: '/groups', + icon: 'group', + }, +}; +</script> + +<template> + <div> + <gl-search-box-by-type /> + <nav :aria-label="$options.i18n.contextNavigation"> + <ul class="gl-p-0 gl-list-style-none"> + <li> + <div aria-hidden="true" class="gl-font-weight-bold gl-px-3 gl-py-3"> + {{ $options.i18n.switchTo }} + </div> + <ul :aria-label="$options.i18n.switchTo" class="gl-p-0"> + <nav-item :item="$options.contextSwitcherItems.yourWork" /> + </ul> + </li> + <li> + <div aria-hidden="true" class="gl-font-weight-bold gl-px-3 gl-py-3"> + {{ $options.i18n.recentProjects }} + </div> + <ul :aria-label="$options.i18n.recentProjects" class="gl-p-0"> + <nav-item + v-for="project in $options.contextSwitcherItems.recentProjects" + :key="project.title" + :item="project" + > + <template #icon> + <gl-avatar shape="rect" :size="32" :src="project.avatar" /> + </template> + </nav-item> + <nav-item :item="$options.viewAllProjectsItem" /> + </ul> + </li> + <li> + <div aria-hidden="true" class="gl-font-weight-bold gl-px-3 gl-py-3"> + {{ $options.i18n.recentGroups }} + </div> + <ul :aria-label="$options.i18n.recentGroups" class="gl-p-0"> + <nav-item + v-for="project in $options.contextSwitcherItems.recentGroups" + :key="project.title" + :item="project" + > + <template #icon> + <gl-avatar shape="rect" :size="32" :src="project.avatar" /> + </template> + </nav-item> + <nav-item :item="$options.viewAllGroupsItem" /> + </ul> + </li> + </ul> + </nav> + </div> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue b/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue new file mode 100644 index 00000000000..b6f058f7aee --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue @@ -0,0 +1,45 @@ +<script> +import { GlTruncate, GlAvatar, GlCollapseToggleDirective, GlIcon } from '@gitlab/ui'; + +export default { + components: { + GlTruncate, + GlAvatar, + GlIcon, + }, + directives: { + CollapseToggle: GlCollapseToggleDirective, + }, + props: { + context: { + type: Object, + required: true, + }, + expanded: { + type: Boolean, + required: true, + }, + }, + computed: { + collapseIcon() { + return this.expanded ? 'chevron-up' : 'chevron-down'; + }, + }, +}; +</script> + +<template> + <button + v-collapse-toggle.context-switcher + type="button" + class="context-switcher-toggle gl-bg-transparent 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-pl-3 gl-pr-5 gl-h-8" + > + <gl-avatar :size="32" shape="rect" :src="context.avatar" class="gl-mr-3" /> + <div class="gl-overflow-auto"> + <gl-truncate :text="context.title" /> + </div> + <span class="gl-flex-grow-1 gl-text-right"> + <gl-icon :name="collapseIcon" /> + </span> + </button> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/counter.vue b/app/assets/javascripts/super_sidebar/components/counter.vue new file mode 100644 index 00000000000..d790e61ca31 --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/counter.vue @@ -0,0 +1,48 @@ +<script> +import { GlIcon } from '@gitlab/ui'; + +export default { + components: { + GlIcon, + }, + props: { + count: { + type: Number, + required: true, + }, + href: { + type: String, + required: false, + default: '', + }, + icon: { + type: String, + required: true, + }, + label: { + type: String, + required: true, + }, + }, + computed: { + ariaLabel() { + return `${this.label} ${this.count}`; + }, + component() { + return this.href ? 'a' : 'button'; + }, + }, +}; +</script> + +<template> + <component + :is="component" + :aria-label="ariaLabel" + :href="href" + class="counter gl-relative gl-display-inline-block gl-flex-grow-1 gl-text-center gl-py-3 gl-bg-gray-10 gl-rounded-base gl-text-black-normal gl-border gl-border-gray-a-08 gl-font-sm gl-font-weight-bold" + > + <gl-icon aria-hidden="true" :name="icon" /> + <span aria-hidden="true">{{ count }}</span> + </component> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/nav_item.vue b/app/assets/javascripts/super_sidebar/components/nav_item.vue new file mode 100644 index 00000000000..4fd6918fd6f --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/nav_item.vue @@ -0,0 +1,37 @@ +<script> +import { GlIcon } from '@gitlab/ui'; + +export default { + name: 'NavItem', + components: { + GlIcon, + }, + props: { + item: { + type: Object, + required: true, + }, + }, +}; +</script> + +<template> + <li> + <a + :href="item.link" + class="gl-display-flex gl-pl-3 gl-py-3 gl-line-height-normal gl-text-black-normal gl-hover-bg-t-gray-a-08" + > + <div class="gl-mr-3"> + <slot name="icon"> + <gl-icon v-if="item.icon" :name="item.icon" /> + </slot> + </div> + <div class="gl-pr-3"> + {{ item.title }} + <div v-if="item.subtitle" class="gl-font-sm gl-text-gray-500 gl-mt-1"> + {{ item.subtitle }} + </div> + </div> + </a> + </li> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue new file mode 100644 index 00000000000..e2eac64f5ad --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue @@ -0,0 +1,50 @@ +<script> +import { GlCollapse } from '@gitlab/ui'; +import { context } from '../mock_data'; +import UserBar from './user_bar.vue'; +import ContextSwitcherToggle from './context_switcher_toggle.vue'; +import ContextSwitcher from './context_switcher.vue'; +import BottomBar from './bottom_bar.vue'; + +export default { + context, + components: { + GlCollapse, + UserBar, + ContextSwitcherToggle, + ContextSwitcher, + BottomBar, + }, + props: { + sidebarData: { + type: Object, + required: true, + }, + }, + data() { + return { + contextSwitcherOpened: false, + }; + }, +}; +</script> + +<template> + <aside + class="super-sidebar gl-fixed gl-bottom-0 gl-left-0 gl-display-flex gl-flex-direction-column gl-bg-gray-10 gl-border-r gl-border-gray-a-08 gl-z-index-9999" + data-testid="super-sidebar" + > + <user-bar :sidebar-data="sidebarData" /> + <div class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-overflow-hidden"> + <div class="gl-flex-grow-1 gl-overflow-auto"> + <context-switcher-toggle :context="$options.context" :expanded="contextSwitcherOpened" /> + <gl-collapse id="context-switcher" v-model="contextSwitcherOpened"> + <context-switcher /> + </gl-collapse> + </div> + <div class="gl-px-3"> + <bottom-bar /> + </div> + </div> + </aside> +</template> diff --git a/app/assets/javascripts/super_sidebar/components/user_bar.vue b/app/assets/javascripts/super_sidebar/components/user_bar.vue new file mode 100644 index 00000000000..7ee1776bf07 --- /dev/null +++ b/app/assets/javascripts/super_sidebar/components/user_bar.vue @@ -0,0 +1,77 @@ +<script> +import { GlAvatar, GlDropdown, GlIcon } from '@gitlab/ui'; +import { __ } from '~/locale'; +import SafeHtml from '~/vue_shared/directives/safe_html'; +import NewNavToggle from '~/nav/components/new_nav_toggle.vue'; +import logo from '../../../../views/shared/_logo.svg'; +import Counter from './counter.vue'; + +export default { + logo, + components: { + GlAvatar, + GlDropdown, + GlIcon, + NewNavToggle, + Counter, + }, + i18n: { + issues: __('Issues'), + mergeRequests: __('Merge requests'), + todoList: __('To-Do list'), + }, + directives: { + SafeHtml, + }, + inject: ['rootPath', 'toggleNewNavEndpoint'], + props: { + sidebarData: { + type: Object, + required: true, + }, + }, +}; +</script> + +<template> + <div class="user-bar"> + <div class="gl-display-flex gl-align-items-center gl-px-3 gl-py-2 gl-gap-3"> + <div class="gl-flex-grow-1"> + <a v-safe-html="$options.logo" :href="rootPath"></a> + </div> + <gl-dropdown variant="link" no-caret> + <template #button-content> + <gl-icon name="plus" class="gl-vertical-align-middle gl-text-black-normal" /> + </template> + </gl-dropdown> + <button class="gl-border-none"> + <gl-icon name="search" class="gl-vertical-align-middle" /> + </button> + <gl-dropdown data-testid="user-dropdown" variant="link" no-caret> + <template #button-content> + <gl-avatar :entity-name="sidebarData.name" :src="sidebarData.avatar_url" :size="32" /> + </template> + <new-nav-toggle :endpoint="toggleNewNavEndpoint" enabled /> + </gl-dropdown> + </div> + <div class="gl-display-flex gl-justify-content-space-between gl-px-3 gl-py-2 gl-gap-2"> + <counter + icon="issues" + :count="sidebarData.assigned_open_issues_count" + :href="sidebarData.issues_dashboard_path" + :label="$options.i18n.issues" + /> + <counter + icon="merge-request-open" + :count="sidebarData.assigned_open_merge_requests_count" + :label="$options.i18n.mergeRequests" + /> + <counter + icon="todo-done" + :count="sidebarData.todos_pending_count" + href="/dashboard/todos" + :label="$options.i18n.todoList" + /> + </div> + </div> +</template> |