diff --git a/packages/stage-ui/stories/setup.ts b/packages/stage-ui/stories/setup.ts index da93d4a10e..2ca2be0b3d 100644 --- a/packages/stage-ui/stories/setup.ts +++ b/packages/stage-ui/stories/setup.ts @@ -2,6 +2,7 @@ import type { Plugin } from 'vue' import { autoAnimatePlugin } from '@formkit/auto-animate/vue' import { defineSetupVue3 } from '@histoire/plugin-vue' +import { useMutationObserver } from '@vueuse/core' import { MotionPlugin } from '@vueuse/motion' import { createPinia } from 'pinia' @@ -28,6 +29,22 @@ import '@fontsource/m-plus-rounded-1c/index.css' import '@fontsource/maple-mono/index.css' import '@fontsource-variable/nunito/index.css' +// NOTICE: +// `useTheme` re-applies its stored scheme and removes the Histoire `dark` class. +// Mirror the Histoire `htw-dark` state (@histoire/app/dist/bundled/util/dark.js) to `dark`. +// Do not write `useTheme`: stories share an origin with stage-web and would change its saved theme. +// Remove when Histoire can drive an app-owned theme store. +function syncHistoireDark() { + const root = document.documentElement + root.classList.toggle('dark', root.classList.contains('htw-dark')) +} + +// `setup.server.ts` re-exports this module for story collection in Node, where `document` does not exist. +if (typeof document !== 'undefined') { + syncHistoireDark() + useMutationObserver(document.documentElement, syncHistoireDark, { attributeFilter: ['class'] }) +} + export const setupVue3 = defineSetupVue3(({ app }) => { // Each story app gets its own Pinia, because components such as the chat history items read stores in setup. app.use(createPinia())