Theme
Ooko follows the browser or operating-system color preference by default and exposes useOokoTheme for persistent light and dark overrides.
Automatic theme
When data-ooko-theme is absent, Ooko uses prefers-color-scheme:
<html>
<!-- The Ooko theme follows the system preference. -->
</html>This behavior is implemented in CSS, so the automatic light or dark palette does not depend on Vue or JavaScript. Ooko also sets color-scheme so compatible native controls follow the same theme.
Explicit theme containers remain supported:
<section data-ooko-theme="dark">
<!-- This section is always dark. -->
</section>Use data-ooko-theme="light" for an explicit light scope. Removing the attribute returns that scope to its inherited or system theme.
Vue composable
Import the composable from the dedicated package entry:
<script setup lang="ts">
import { useOokoTheme } from "ooko-ui/theme";
const { mode, resolvedTheme, setMode } = useOokoTheme();
</script>
<template>
<button type="button" @click="setMode('light')">Light</button>
<button type="button" @click="setMode('dark')">Dark</button>
<button type="button" @click="setMode('system')">System</button>
<p>Preference: {{ mode }}</p>
<p>Applied theme: {{ resolvedTheme ?? "Waiting for the browser" }}</p>
</template>Call useOokoTheme from a long-lived component such as the application root. Calls share the same document-level state, while listener ownership follows mounted consumers.
API reference
Manages the document-level light, dark, or system theme preference.
function useOokoTheme(): UseOokoThemeReturnParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| none | none | none | none | none |
Returns
| Member | Type | Description |
|---|---|---|
mode | Readonly<Ref<OokoThemeMode, OokoThemeMode>> | Readonly user preference. |
resolvedTheme | ComputedRef<OokoTheme | undefined> | Effective client theme, unresolved before mounting. |
setMode | (mode: OokoThemeMode) => void | Applies and persists a theme preference. |
Related types
| Type | Definition |
|---|---|
OokoTheme | type OokoTheme = "light" | "dark"; |
OokoThemeMode | type OokoThemeMode = OokoTheme | "system"; |
UseOokoThemeReturn | interface UseOokoThemeReturn { /** Readonly user preference. */ mode: Readonly<Ref<OokoThemeMode>>; /** Effective client theme, unresolved before mounting. */ resolvedTheme: ComputedRef<OokoTheme | undefined>; /** Applies and persists a theme preference. */ setMode: (mode: OokoThemeMode) => void; } |
light and dark are stored under the ooko-theme local-storage key. system removes both the stored value and data-ooko-theme, allowing CSS to follow future system changes.
SSR and hydration
The composable does not access window, document, localStorage, or matchMedia while its module loads or while Vue renders on the server. Before the component mounts:
modeissystem;resolvedThemeisundefined;- no document attribute or browser listener is changed.
Do not use resolvedTheme to produce different server markup without an explicit stable fallback. Use CSS for theme-dependent presentation so server and client markup remain identical.
The system theme is correct before Vue mounts because CSS owns automatic selection. A persisted explicit override is applied when the composable mounts; applications that require a zero-flash stored override need a separate early bootstrap strategy compatible with their SSR and Content Security Policy setup.