From 727f84ee296711020eb6845efd28f7957ccf7818 Mon Sep 17 00:00:00 2001 From: MilkyWeighW <120256681+MilkyWeighW@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:35:55 +0800 Subject: [PATCH] chore(docs): polish theme toggle, search morph & page transitions (#2205) --------- Co-authored-by: Neko --- docs/.vitepress/components/DocCommunity.vue | 4 +- docs/.vitepress/components/DocTopbar.vue | 51 +---- docs/.vitepress/components/Home.vue | 12 +- docs/.vitepress/components/Navbar.vue | 13 +- docs/.vitepress/components/ParallaxCover.vue | 2 +- .../ParallaxCoverChristmas20251224.vue | 14 -- .../ParallaxCoverHalloween20251029.vue | 2 +- .../components/SearchCommandBox.vue | 15 +- docs/.vitepress/components/SearchTrigger.vue | 199 +++++++++++++++--- docs/.vitepress/components/ThemeToggle.vue | 28 ++- docs/.vitepress/composables/theme-color.ts | 16 +- docs/.vitepress/config.ts | 15 +- docs/.vitepress/custom/Docs.vue | 133 ++++++++---- docs/.vitepress/theme/theme-animations.css | 48 ++++- .../design-guidelines/resources.md | 2 +- .../design-guidelines/resources.md | 2 +- .../design-guidelines/resources.md | 2 +- docs/content/public/_redirects | 2 + .../design-guidelines/resources.md | 2 +- 19 files changed, 396 insertions(+), 166 deletions(-) diff --git a/docs/.vitepress/components/DocCommunity.vue b/docs/.vitepress/components/DocCommunity.vue index 7a987db58..af046fc51 100644 --- a/docs/.vitepress/components/DocCommunity.vue +++ b/docs/.vitepress/components/DocCommunity.vue @@ -34,12 +34,12 @@ const links = computed(() => [ transition-colors duration-200 ease-in-out > {{ link.label }} diff --git a/docs/.vitepress/components/DocTopbar.vue b/docs/.vitepress/components/DocTopbar.vue index 14ba8cb44..207b2339d 100644 --- a/docs/.vitepress/components/DocTopbar.vue +++ b/docs/.vitepress/components/DocTopbar.vue @@ -6,7 +6,6 @@ import { useScroll } from '@vueuse/core' import { DialogContent, DialogDescription, DialogOverlay, DialogPortal, DialogRoot, DialogTitle, DialogTrigger } from 'reka-ui' import { useData, useRoute, withBase } from 'vitepress' import { computed, ref, toRefs, watch } from 'vue' -import { useI18n } from 'vue-i18n' import DocSidebarItem from '../components/DocSidebarItem.vue' @@ -14,7 +13,6 @@ import { flatten } from '../utils/flatten' const { path } = toRefs(useRoute()) const { page, theme } = useData() -const { t } = useI18n() const isSidebarOpen = ref(false) const sidebar = computed(() => (theme.value.sidebar as (DefaultTheme.SidebarItem & { icon?: string })[])) @@ -24,17 +22,18 @@ const sectionTabs = computed(() => sidebar.value return { label: val.text, link: flatten(val.items ?? [], 'items').filter(i => !!i?.link)?.[0]?.link ?? val.link, + // Highlight by the section's own link; tab.link points at the first + // child page and would narrow the highlight to it. + highlight: val.link, icon: val.icon, } }) .filter(i => !!i?.link), ) -function isCharacterPage(link?: string) { - if (!link) - return false - - return link.includes('/characters') || link.includes('/characters/') +function isTabActive(tab: { link?: string, highlight?: string }): boolean { + const prefix = (tab.highlight ?? tab.link)?.split('/').slice(0, -1).join('/') ?? '' + return withBase(`/${page.value.relativePath}`).includes(prefix) } const { arrivedState } = useScroll(globalThis.window) @@ -55,28 +54,10 @@ watch(path, () => {
- - {{ tab.label }} - -
- - diff --git a/docs/.vitepress/components/Home.vue b/docs/.vitepress/components/Home.vue index 9b7596a80..a4e547dc2 100644 --- a/docs/.vitepress/components/Home.vue +++ b/docs/.vitepress/components/Home.vue @@ -192,8 +192,12 @@ const buttons = computed(() => theme.value.homepage?.buttons || []) diff --git a/docs/.vitepress/components/Navbar.vue b/docs/.vitepress/components/Navbar.vue index 49973944e..bb3f3f946 100644 --- a/docs/.vitepress/components/Navbar.vue +++ b/docs/.vitepress/components/Navbar.vue @@ -1,5 +1,6 @@ diff --git a/docs/.vitepress/components/ThemeToggle.vue b/docs/.vitepress/components/ThemeToggle.vue index 9bdf7c0f6..54cfa19af 100644 --- a/docs/.vitepress/components/ThemeToggle.vue +++ b/docs/.vitepress/components/ThemeToggle.vue @@ -4,6 +4,12 @@ import { SwitchRoot, SwitchThumb } from 'reka-ui' import { useData } from 'vitepress' import { ref, watchPostEffect } from 'vue' +defineOptions({ + // DropdownMenuItem as-child passes item attrs here; ClientOnly (fragment) + // can't inherit them, so bind $attrs onto SwitchRoot manually. + inheritAttrs: false, +}) + const { isDark } = useData() const switchTitle = ref('') @@ -13,15 +19,35 @@ watchPostEffect(() => { ? 'Switch to light theme' : 'Switch to dark theme' }) + +/** + * Wraps the theme switch in a View Transition so the browser cross-fades the + * whole page snapshots, keeping every element in sync. Falls back to an + * instant switch where `startViewTransition` is unsupported (e.g. Firefox). + */ +function onToggle(value: boolean) { + if (value === isDark.value) + return + if (typeof document !== 'undefined' && 'startViewTransition' in document) { + document.startViewTransition(() => { + isDark.value = value + }) + } + else { + isDark.value = value + } +}