Skip to content

Commit

Permalink
perf(a11y): make menu traversable only when it is open (#1491)
Browse files Browse the repository at this point in the history
Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com>
  • Loading branch information
7nohe and brc-dd committed Dec 26, 2022
1 parent 7a73784 commit 257f9e6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/client/theme-default/Layout.vue
Expand Up @@ -22,6 +22,7 @@ watch(() => route.path, closeSidebar)
useCloseSidebarOnEscape(isSidebarOpen, closeSidebar)
provide('close-sidebar', closeSidebar)
provide('is-sidebar-open', isSidebarOpen)
const { frontmatter } = useData()
</script>
Expand Down
23 changes: 20 additions & 3 deletions src/client/theme-default/components/VPSidebarLink.vue
@@ -1,11 +1,12 @@
<script lang="ts" setup>
import type { DefaultTheme } from 'vitepress/theme'
import { computed, inject } from 'vue'
import { Ref, computed, inject, ref, watchEffect } from 'vue'
import { useData } from 'vitepress'
import { useSidebar } from '../composables/sidebar.js'
import { isActive } from '../support/utils.js'
import VPLink from './VPLink.vue'
withDefaults(
const props = withDefaults(
defineProps<{ item: DefaultTheme.SidebarItem; depth?: number }>(),
{ depth: 1 }
)
Expand All @@ -14,16 +15,32 @@ const { page, frontmatter } = useData()
const maxDepth = computed<number>(
() => frontmatter.value.sidebarDepth || Infinity
)
const active = computed(() =>
isActive(page.value.relativePath, props.item.link)
)
const { isSidebarEnabled } = useSidebar()
const closeSideBar = inject('close-sidebar') as () => void
const isSidebarOpen = inject('is-sidebar-open') as Ref<boolean>
const link = ref<InstanceType<typeof VPLink> | null>(null)
watchEffect(() => {
if (isSidebarOpen.value && active.value) {
link.value?.$el?.focus()
}
})
</script>

<template>
<VPLink
class="link"
:class="{ active: isActive(page.relativePath, item.link) }"
:class="{ active }"
:style="{ paddingLeft: 16 * (depth - 1) + 'px' }"
:href="item.link"
:tabindex="isSidebarEnabled || isSidebarOpen ? 0 : -1"
@click="closeSideBar"
ref="link"
>
<span v-html="item.text" class="link-text" :class="{ light: depth > 1 }"></span>
</VPLink>
Expand Down
5 changes: 5 additions & 0 deletions src/client/theme-default/composables/sidebar.ts
@@ -1,10 +1,12 @@
import { computed, onMounted, onUnmounted, Ref, ref, watchEffect } from 'vue'
import { useData, useRoute } from 'vitepress'
import { useMediaQuery } from '@vueuse/core'
import { getSidebar } from '../support/sidebar.js'

export function useSidebar() {
const route = useRoute()
const { theme, frontmatter } = useData()
const is960 = useMediaQuery('(min-width: 960px)')

const isOpen = ref(false)

Expand All @@ -28,6 +30,8 @@ export function useSidebar() {
)
})

const isSidebarEnabled = computed(() => hasSidebar.value && is960.value)

function open() {
isOpen.value = true
}
Expand All @@ -45,6 +49,7 @@ export function useSidebar() {
sidebar,
hasSidebar,
hasAside,
isSidebarEnabled,
open,
close,
toggle
Expand Down

0 comments on commit 257f9e6

Please sign in to comment.