refactor: migrate useSidebar into useLayout and useSidebarControl

pull/4673/head
Yuxuan Zhang 6 months ago
parent 9477d8169e
commit 0958b6aff4
No known key found for this signature in database
GPG Key ID: 6910B04F3351EF7D

@ -9,13 +9,13 @@ import VPNav from './components/VPNav.vue'
import VPSidebar from './components/VPSidebar.vue' import VPSidebar from './components/VPSidebar.vue'
import VPSkipLink from './components/VPSkipLink.vue' import VPSkipLink from './components/VPSkipLink.vue'
import { useData } from './composables/data' import { useData } from './composables/data'
import { useCloseSidebarOnEscape, useSidebar } from './composables/sidebar' import { useCloseSidebarOnEscape, useSidebarControl } from './composables/sidebar'
const { const {
isOpen: isSidebarOpen, isOpen: isSidebarOpen,
open: openSidebar, open: openSidebar,
close: closeSidebar close: closeSidebar
} = useSidebar() } = useSidebarControl()
const route = useRoute() const route = useRoute()
watch(() => route.path, closeSidebar) watch(() => route.path, closeSidebar)

@ -2,14 +2,12 @@
import NotFound from '../NotFound.vue' import NotFound from '../NotFound.vue'
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { useLayout } from '../composables/layout' import { useLayout } from '../composables/layout'
import { useSidebar } from '../composables/sidebar'
import VPDoc from './VPDoc.vue' import VPDoc from './VPDoc.vue'
import VPHome from './VPHome.vue' import VPHome from './VPHome.vue'
import VPPage from './VPPage.vue' import VPPage from './VPPage.vue'
const { page, frontmatter } = useData() const { page, frontmatter } = useData()
const { isHome } = useLayout() const { isHome, hasSidebar } = useLayout()
const { hasSidebar } = useSidebar()
</script> </script>
<template> <template>

@ -2,14 +2,14 @@
import { useRoute } from 'vitepress' import { useRoute } from 'vitepress'
import { computed } from 'vue' import { computed } from 'vue'
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { useSidebar } from '../composables/sidebar' import { useLayout } from '../composables/layout'
import VPDocAside from './VPDocAside.vue' import VPDocAside from './VPDocAside.vue'
import VPDocFooter from './VPDocFooter.vue' import VPDocFooter from './VPDocFooter.vue'
const { theme } = useData() const { theme } = useData()
const route = useRoute() const route = useRoute()
const { hasSidebar, hasAside, leftAside } = useSidebar() const { hasSidebar, hasAside, leftAside } = useLayout()
const pageName = computed(() => const pageName = computed(() =>
route.path.replace(/[./]+/g, '_').replace(/_html$/, '') route.path.replace(/[./]+/g, '_').replace(/_html$/, '')

@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { useSidebar } from '../composables/sidebar' import { useLayout } from '../composables/layout'
const { theme, frontmatter } = useData() const { theme, frontmatter } = useData()
const { hasSidebar } = useSidebar() const { hasSidebar } = useLayout()
</script> </script>
<template> <template>

@ -5,7 +5,7 @@ import { computed, onMounted, ref } from 'vue'
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { useLocalNav } from '../composables/local-nav' import { useLocalNav } from '../composables/local-nav'
import { getHeaders } from '../composables/outline' import { getHeaders } from '../composables/outline'
import { useSidebar } from '../composables/sidebar' import { useLayout } from '../composables/layout'
import VPLocalNavOutlineDropdown from './VPLocalNavOutlineDropdown.vue' import VPLocalNavOutlineDropdown from './VPLocalNavOutlineDropdown.vue'
defineProps<{ defineProps<{
@ -17,7 +17,7 @@ defineEmits<{
}>() }>()
const { theme, frontmatter } = useData() const { theme, frontmatter } = useData()
const { hasSidebar } = useSidebar() const { hasSidebar } = useLayout()
const { headers } = useLocalNav() const { headers } = useLocalNav()
const { y } = useWindowScroll() const { y } = useWindowScroll()

@ -2,7 +2,6 @@
import { useWindowScroll } from '@vueuse/core' import { useWindowScroll } from '@vueuse/core'
import { ref, watchPostEffect } from 'vue' import { ref, watchPostEffect } from 'vue'
import { useLayout } from '../composables/layout' import { useLayout } from '../composables/layout'
import { useSidebar } from '../composables/sidebar'
import VPNavBarAppearance from './VPNavBarAppearance.vue' import VPNavBarAppearance from './VPNavBarAppearance.vue'
import VPNavBarExtra from './VPNavBarExtra.vue' import VPNavBarExtra from './VPNavBarExtra.vue'
import VPNavBarHamburger from './VPNavBarHamburger.vue' import VPNavBarHamburger from './VPNavBarHamburger.vue'
@ -21,8 +20,7 @@ defineEmits<{
}>() }>()
const { y } = useWindowScroll() const { y } = useWindowScroll()
const { hasSidebar } = useSidebar() const { isHome, hasSidebar } = useLayout()
const { isHome } = useLayout()
const classes = ref<Record<string, boolean>>({}) const classes = ref<Record<string, boolean>>({})

@ -2,12 +2,12 @@
import { computed } from 'vue' import { computed } from 'vue'
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { useLangs } from '../composables/langs' import { useLangs } from '../composables/langs'
import { useSidebar } from '../composables/sidebar' import { useLayout } from '../composables/layout'
import { normalizeLink } from '../support/utils' import { normalizeLink } from '../support/utils'
import VPImage from './VPImage.vue' import VPImage from './VPImage.vue'
const { site, theme } = useData() const { site, theme } = useData()
const { hasSidebar } = useSidebar() const { hasSidebar } = useLayout()
const { currentLang } = useLangs() const { currentLang } = useLangs()
const link = computed(() => const link = computed(() =>

@ -2,10 +2,10 @@
import { useScrollLock } from '@vueuse/core' import { useScrollLock } from '@vueuse/core'
import { inBrowser } from 'vitepress' import { inBrowser } from 'vitepress'
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import { useSidebar } from '../composables/sidebar' import { useLayout } from '../composables/layout'
import VPSidebarGroup from './VPSidebarGroup.vue' import VPSidebarGroup from './VPSidebarGroup.vue'
const { sidebarGroups, hasSidebar } = useSidebar() const { sidebarGroups, hasSidebar } = useLayout()
const props = defineProps<{ const props = defineProps<{
open: boolean open: boolean

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme' import type { DefaultTheme } from 'vitepress/theme'
import { computed } from 'vue' import { computed } from 'vue'
import { useSidebarControl } from '../composables/sidebar' import { useSidebarItemControl } from '../composables/sidebar'
import VPLink from './VPLink.vue' import VPLink from './VPLink.vue'
const props = defineProps<{ const props = defineProps<{
@ -17,7 +17,7 @@ const {
hasActiveLink, hasActiveLink,
hasChildren, hasChildren,
toggle toggle
} = useSidebarControl(computed(() => props.item)) } = useSidebarItemControl(computed(() => props.item))
const sectionTag = computed(() => (hasChildren.value ? 'section' : `div`)) const sectionTag = computed(() => (hasChildren.value ? 'section' : `div`))

@ -1,9 +1,9 @@
import { useMediaQuery } from '@vueuse/core' import { useMediaQuery } from '@vueuse/core'
import { computed } from 'vue' import { computed } from 'vue'
import { useSidebar } from './sidebar' import { useLayout } from './layout'
export function useAside() { export function useAside() {
const { hasSidebar } = useSidebar() const { hasSidebar } = useLayout()
const is960 = useMediaQuery('(min-width: 960px)') const is960 = useMediaQuery('(min-width: 960px)')
const is1280 = useMediaQuery('(min-width: 1280px)') const is1280 = useMediaQuery('(min-width: 1280px)')

@ -1,8 +1,11 @@
import { computed } from 'vue' import { useMediaQuery } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { getSidebar, getSidebarGroups } from '../support/sidebar'
import { useData } from './data' import { useData } from './data'
export function useLayout() { export function useLayout() {
const { frontmatter } = useData() const { frontmatter, page, theme } = useData()
const is960 = useMediaQuery('(min-width: 960px)')
const isHome = computed(() => { const isHome = computed(() => {
if (frontmatter.value.isHome !== undefined) if (frontmatter.value.isHome !== undefined)
@ -10,5 +13,54 @@ export function useLayout() {
else return frontmatter.value.layout === 'home' else return frontmatter.value.layout === 'home'
}) })
return { isHome } const _sidebar = computed(() => {
const sidebarConfig = theme.value.sidebar
const relativePath = page.value.relativePath
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []
})
const sidebar = ref(_sidebar.value)
watch(_sidebar, (next, prev) => {
if (JSON.stringify(next) !== JSON.stringify(prev))
sidebar.value = _sidebar.value
})
const hasSidebar = computed(() => {
return (
frontmatter.value.sidebar !== false &&
sidebar.value.length > 0 &&
!isHome.value
)
})
const leftAside = computed(() => {
if (hasAside)
return frontmatter.value.aside == null
? theme.value.aside === 'left'
: frontmatter.value.aside === 'left'
return false
})
const hasAside = computed(() => {
if (isHome.value) return false
if (frontmatter.value.aside != null) return !!frontmatter.value.aside
return theme.value.aside !== false
})
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value)
const sidebarGroups = computed(() => {
return hasSidebar.value ? getSidebarGroups(sidebar.value) : []
})
return {
isHome,
sidebar,
sidebarGroups,
hasSidebar,
hasAside,
leftAside,
isSidebarEnabled
}
} }

@ -1,4 +1,3 @@
import { useMediaQuery } from '@vueuse/core'
import type { DefaultTheme } from 'vitepress/theme' import type { DefaultTheme } from 'vitepress/theme'
import { import {
computed, computed,
@ -12,13 +11,8 @@ import {
type Ref type Ref
} from 'vue' } from 'vue'
import { isActive } from '../../shared' import { isActive } from '../../shared'
import { import { hasActiveLink as containsActiveLink } from '../support/sidebar'
hasActiveLink as containsActiveLink,
getSidebar,
getSidebarGroups
} from '../support/sidebar'
import { useData } from './data' import { useData } from './data'
import { useLayout } from './layout'
export interface SidebarControl { export interface SidebarControl {
collapsed: Ref<boolean> collapsed: Ref<boolean>
@ -30,80 +24,6 @@ export interface SidebarControl {
toggle(): void toggle(): void
} }
export function useSidebar() {
const { frontmatter, page, theme } = useData()
const { isHome } = useLayout()
const is960 = useMediaQuery('(min-width: 960px)')
const isOpen = ref(false)
const _sidebar = computed(() => {
const sidebarConfig = theme.value.sidebar
const relativePath = page.value.relativePath
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []
})
const sidebar = ref(_sidebar.value)
watch(_sidebar, (next, prev) => {
if (JSON.stringify(next) !== JSON.stringify(prev))
sidebar.value = _sidebar.value
})
const hasSidebar = computed(() => {
return (
frontmatter.value.sidebar !== false &&
sidebar.value.length > 0 &&
!isHome.value
)
})
const leftAside = computed(() => {
if (hasAside)
return frontmatter.value.aside == null
? theme.value.aside === 'left'
: frontmatter.value.aside === 'left'
return false
})
const hasAside = computed(() => {
if (isHome.value) return false
if (frontmatter.value.aside != null) return !!frontmatter.value.aside
return theme.value.aside !== false
})
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value)
const sidebarGroups = computed(() => {
return hasSidebar.value ? getSidebarGroups(sidebar.value) : []
})
function open() {
isOpen.value = true
}
function close() {
isOpen.value = false
}
function toggle() {
isOpen.value ? close() : open()
}
return {
isOpen,
sidebar,
sidebarGroups,
hasSidebar,
hasAside,
leftAside,
isSidebarEnabled,
open,
close,
toggle
}
}
/** /**
* a11y: cache the element that opened the Sidebar (the menu button) then * a11y: cache the element that opened the Sidebar (the menu button) then
* focus that button again when Menu is closed with Escape key. * focus that button again when Menu is closed with Escape key.
@ -136,7 +56,30 @@ export function useCloseSidebarOnEscape(
} }
} }
export function useSidebarControl( export function useSidebarControl() {
const isOpen = ref(false)
function open() {
isOpen.value = true
}
function close() {
isOpen.value = false
}
function toggle() {
isOpen.value ? close() : open()
}
return {
isOpen,
open,
close,
toggle
}
}
export function useSidebarItemControl(
item: ComputedRef<DefaultTheme.SidebarItem> item: ComputedRef<DefaultTheme.SidebarItem>
): SidebarControl { ): SidebarControl {
const { page, hash } = useData() const { page, hash } = useData()

@ -32,7 +32,7 @@ export { default as VPTeamPageSection } from './components/VPTeamPageSection.vue
export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue' export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue'
export { useLocalNav } from './composables/local-nav' export { useLocalNav } from './composables/local-nav'
export { useSidebar } from './composables/sidebar' export { useLayout } from './composables/layout'
const theme: Theme = { const theme: Theme = {
Layout, Layout,

Loading…
Cancel
Save