useOmarchyTheme
hookReads and writes the active Omarchy theme, mirroring it onto the document element and localStorage.
bunx --bun shadcn@latest add yamz8/omarchy-shadcn-registry/use-omarchy-themeDependencies
- registry
- yamz8/omarchy-shadcn-registry/omarchy-palette
Source
registry/hooks/use-omarchy-theme.ts
"use client"
import * as React from "react"
import {
DEFAULT_OMARCHY_THEME,
getOmarchyCssVariables,
getOmarchyTheme,
isOmarchyThemeName,
type OmarchyThemeName,
} from "@/lib/omarchy-palette"
const STORAGE_KEY = "omarchy-theme"
const listeners = new Set<() => void>()
let currentTheme: OmarchyThemeName = DEFAULT_OMARCHY_THEME
function subscribe(onStoreChange: () => void) {
listeners.add(onStoreChange)
window.addEventListener("storage", onStoreChange)
return () => {
listeners.delete(onStoreChange)
window.removeEventListener("storage", onStoreChange)
}
}
function getSnapshot(): OmarchyThemeName {
try {
const stored = window.localStorage.getItem(STORAGE_KEY)
if (stored && isOmarchyThemeName(stored)) {
currentTheme = stored
}
} catch {
// Storage can be unavailable (private mode, blocked site data).
}
return currentTheme
}
function getServerSnapshot(): OmarchyThemeName {
return DEFAULT_OMARCHY_THEME
}
export function applyOmarchyTheme(
name: OmarchyThemeName,
root: HTMLElement = document.documentElement
) {
const theme = getOmarchyTheme(name)
if (!theme) {
return
}
root.dataset.omarchyTheme = theme.name
root.style.colorScheme = theme.mode
for (const [property, value] of Object.entries(
getOmarchyCssVariables(theme)
)) {
root.style.setProperty(property, value)
}
}
/**
* Reads and writes the active Omarchy theme, mirroring it onto
* `document.documentElement[data-omarchy-theme]` and localStorage.
*/
export function useOmarchyTheme() {
const theme = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot
)
React.useEffect(() => {
applyOmarchyTheme(theme)
}, [theme])
const setTheme = React.useCallback((next: OmarchyThemeName) => {
currentTheme = next
try {
window.localStorage.setItem(STORAGE_KEY, next)
} catch {
// Ignore write failures and keep the in-memory selection.
}
applyOmarchyTheme(next)
for (const listener of listeners) {
listener()
}
}, [])
return { theme, setTheme }
}