summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/super_sidebar
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/super_sidebar')
-rw-r--r--app/assets/javascripts/super_sidebar/components/nav_item.vue21
-rw-r--r--app/assets/javascripts/super_sidebar/components/nav_item_link.vue35
-rw-r--r--app/assets/javascripts/super_sidebar/components/nav_item_router_link.vue37
-rw-r--r--app/assets/javascripts/super_sidebar/constants.js2
-rw-r--r--app/assets/javascripts/super_sidebar/utils.js2
5 files changed, 89 insertions, 8 deletions
diff --git a/app/assets/javascripts/super_sidebar/components/nav_item.vue b/app/assets/javascripts/super_sidebar/components/nav_item.vue
index 9dc26ad10f5..8382ae8987b 100644
--- a/app/assets/javascripts/super_sidebar/components/nav_item.vue
+++ b/app/assets/javascripts/super_sidebar/components/nav_item.vue
@@ -7,6 +7,8 @@ import {
TRACKING_UNKNOWN_ID,
TRACKING_UNKNOWN_PANEL,
} from '~/super_sidebar/constants';
+import NavItemLink from './nav_item_link.vue';
+import NavItemRouterLink from './nav_item_router_link.vue';
export default {
i18n: {
@@ -18,6 +20,8 @@ export default {
GlButton,
GlIcon,
GlBadge,
+ NavItemLink,
+ NavItemRouterLink,
},
inject: {
pinnedItemIds: { default: { ids: [] } },
@@ -55,9 +59,6 @@ export default {
(typeof this.pillData === 'string' && this.pillData !== '')
);
},
- isActive() {
- return this.item.is_active;
- },
isPinnable() {
return this.panelSupportsPins && !this.isStatic;
},
@@ -86,27 +87,30 @@ export default {
return {
...this.$attrs,
...this.trackingProps,
- href: this.item.link,
- 'aria-current': this.isActive ? 'page' : null,
+ item: this.item,
'data-qa-submenu-item': this.item.title,
};
},
computedLinkClasses() {
return {
- 'gl-bg-t-gray-a-08': this.isActive,
'gl-py-2': this.isPinnable,
'gl-py-3': !this.isPinnable,
[this.item.link_classes]: this.item.link_classes,
...this.linkClasses,
};
},
+ navItemLinkComponent() {
+ return this.item.to ? NavItemRouterLink : NavItemLink;
+ },
},
};
</script>
<template>
<li>
- <a
+ <component
+ :is="navItemLinkComponent"
+ #default="{ isActive }"
v-bind="linkProps"
class="nav-item-link gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-mb-1 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-focus--focus"
:class="computedLinkClasses"
@@ -118,6 +122,7 @@ export default {
class="gl-absolute gl-left-2 gl-top-2 gl-bottom-2 gl-transition-slow"
aria-hidden="true"
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">
<slot name="icon">
@@ -162,6 +167,6 @@ export default {
@click.prevent="$emit('pin-remove', item.id)"
/>
</span>
- </a>
+ </component>
</li>
</template>
diff --git a/app/assets/javascripts/super_sidebar/components/nav_item_link.vue b/app/assets/javascripts/super_sidebar/components/nav_item_link.vue
new file mode 100644
index 00000000000..8358e96db94
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/nav_item_link.vue
@@ -0,0 +1,35 @@
+<script>
+import { NAV_ITEM_LINK_ACTIVE_CLASS } from '../constants';
+import { ariaCurrent } from '../utils';
+
+export default {
+ props: {
+ item: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ isActive() {
+ return this.item.is_active;
+ },
+ linkProps() {
+ return {
+ href: this.item.link,
+ 'aria-current': ariaCurrent(this.isActive),
+ };
+ },
+ computedLinkClasses() {
+ return {
+ [NAV_ITEM_LINK_ACTIVE_CLASS]: this.isActive,
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <a v-bind="linkProps" :class="computedLinkClasses">
+ <slot :is-active="isActive"></slot>
+ </a>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/components/nav_item_router_link.vue b/app/assets/javascripts/super_sidebar/components/nav_item_router_link.vue
new file mode 100644
index 00000000000..78aca24d9a6
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/nav_item_router_link.vue
@@ -0,0 +1,37 @@
+<script>
+import { NAV_ITEM_LINK_ACTIVE_CLASS } from '../constants';
+import { ariaCurrent } from '../utils';
+
+export default {
+ NAV_ITEM_LINK_ACTIVE_CLASS,
+ props: {
+ item: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ linkProps() {
+ return {
+ to: this.item.to,
+ };
+ },
+ },
+ methods: {
+ ariaCurrent,
+ },
+};
+</script>
+
+<template>
+ <router-link
+ #default="{ href, navigate, isActive }"
+ v-bind="linkProps"
+ :active-class="$options.NAV_ITEM_LINK_ACTIVE_CLASS"
+ custom
+ >
+ <a :href="href" :aria-current="ariaCurrent(isActive)" @click="navigate">
+ <slot :is-active="isActive"></slot>
+ </a>
+ </router-link>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/constants.js b/app/assets/javascripts/super_sidebar/constants.js
index 4a5d0bf637f..00ceaebe2cc 100644
--- a/app/assets/javascripts/super_sidebar/constants.js
+++ b/app/assets/javascripts/super_sidebar/constants.js
@@ -50,3 +50,5 @@ export const SIDEBAR_PINS_EXPANDED_COOKIE = 'sidebar_pinned_section_expanded';
export const SIDEBAR_COOKIE_EXPIRATION = 365 * 10;
export const DROPDOWN_Y_OFFSET = 4;
+
+export const NAV_ITEM_LINK_ACTIVE_CLASS = 'gl-bg-t-gray-a-08';
diff --git a/app/assets/javascripts/super_sidebar/utils.js b/app/assets/javascripts/super_sidebar/utils.js
index 4bbef67742c..3b17a35c5bc 100644
--- a/app/assets/javascripts/super_sidebar/utils.js
+++ b/app/assets/javascripts/super_sidebar/utils.js
@@ -83,3 +83,5 @@ export const formatContextSwitcherItems = (items) =>
avatar,
link,
}));
+
+export const ariaCurrent = (isActive) => (isActive ? 'page' : null);