Persist theme and style preferences to localStorage and sync with document classes.
The LSH (Local Storage Head) component provides an easy way to manage theme switching and style preferences. It stores selections in localStorage under the key __Z_THEME__ and applies them as classes to the <html> element. Multiple instances automatically stay in sync.
To implement LSH, you’ll need to make some modifications to your HTML code to allow users to change their preferences.
1. Start by setting a default theme and mode in the <head> tag of your HTML by checking the user’s preference:
<script>
const htmlElement = document.documentElement;
const __Z_THEME__ = JSON.parse(localStorage.getItem("__Z_THEME__") || "{}");
if (
__Z_THEME__.mode === "dark" ||
(!__Z_THEME__.mode &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
) {
htmlElement.classList.add("dark");
} else {
htmlElement.classList.remove("dark");
}
/* below is just an example, feel free to implement your own */
htmlElement.classList.add(__Z_THEME__.layout || "z-layout-small");
htmlElement.classList.add(__Z_THEME__.ff || "z-ff-a");
</script>This will first check if a user previously set the theme color preference manually using localStorage, and as a fallback, it will either set dark or light mode based on the browser’s color scheme preference.
Note You can replace z-[group]-[value] with anything you want as the default.
2. Ensure that your <body> tag includes the classes bg and color to apply the proper background and text colors that automatically adapt to the currently set theme.
<!doctype html>
<html lang="en">
<head>
<!-- ... -->
</head>
<body class="bg color" style="--bg: var(--z-bg); --color: var(--z-bg-f)">
<!-- ... -->
</body>
</html>3. You can now use any instance of <z-lsh> component anywhere in your HTML.
Enable toggle mode to create a button that switches between light and dark modes:
When toggle is enabled with group="mode", the button automatically switches between light and dark modes, ignoring the value attribute.
The component supports multiple configuration groups beyond just light/dark mode:
The mode group has special handling:
value="light" removes the dark class from <html>value="dark" adds the dark class to <html><z-lsh group="mode" value="light">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<z-lsh group="mode" value="dark">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>Other groups apply class names directly to the <html> element:
<!-- Color themes -->
<z-lsh group="color" value="z-theme-blue">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<z-lsh group="color" value="z-theme-red">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<z-lsh group="color" value="z-theme-green">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<!-- Font sizes -->
<z-lsh group="font" value="z-font-small">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<z-lsh group="font" value="z-font-medium">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<z-lsh group="font" value="z-font-large">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>When switching within a group, the component automatically removes the previous class with the same prefix.
By default, all instances sync when one changes. Use prevent-autoupdate to create standalone buttons:
<z-lsh group="mode" value="dark" prevent-autoupdate>
<template data-fn="template">
<!-- -->
</template>
</z-lsh>Listen to events to respond to theme changes:
<z-lsh id="theme-toggle" toggle group="mode">
<template data-fn="template">
<!-- -->
</template>
</z-lsh>
<script>
const toggle = document.getElementById("theme-toggle");
// Before change (cancelable)
toggle.addEventListener("z-lsh:before-change", (e) => {
console.log("About to change:", e.detail);
// e.preventDefault(); // Cancel the change
});
// After change
toggle.addEventListener("z-lsh:change", (e) => {
console.log("Changed:", e.detail);
// e.detail.group - The configuration group
// e.detail.value - The new value
// e.detail.previousValue - The old value
// e.detail.config - Complete configuration object
});
</script>The component stores configuration in localStorage under the key __Z_THEME__:
{
"mode": "dark",
"color": "z-theme-blue",
"font": "z-font-medium"
}The LSH component supports internationalization through multiple methods with the following priority order (highest to lowest):
i18n attribute or script tag)<script id="z-i18n">)<z-lsh
toggle
group="mode"
i18n='{"aria-label": "Cambiar tema", "switch-to-dark": "Cambiar a modo oscuro", "switch-to-light": "Cambiar a modo claro"}'
>
</z-lsh><z-lsh toggle group="mode">
<script type="application/json" data-fn="config">
{
"i18n": {
"aria-label": "Thème bascule",
"switch-to-dark": "Passer en mode sombre",
"switch-to-light": "Passer en mode clair"
}
}
</script>
<template data-fn="template">🌓</template>
</z-lsh>| Key | Default | Description |
|---|---|---|
aria-label | Toggle theme | ARIA label for the button |
active-label | Active | Label appended to ARIA when button is active |
switch-to-dark | Switch to dark mode | ARIA description when switching to dark (toggle mode) |
switch-to-light | Switch to light mode | ARIA description when switching to light (toggle mode) |
The LSH component supports custom CSS classes through the cls attribute.
<z-lsh cls="my-theme-button" toggle group="mode">
<template data-fn="template">
<!-- -->
</template>
</z-lsh><z-lsh
cls='{"button": "z-button z-button-primary z-lsh"}'
toggle
group="mode"
>
<template data-fn="template">
<!-- -->
</template>
</z-lsh>| Target | Description |
|---|---|
button | The button element |
The LSH component supports custom inline styles through the stl attribute.
<z-lsh
stl='{"button": "padding: 0.5rem 1rem; border-radius: 8px;"}'
toggle
group="mode"
>
<template data-fn="template">
<!-- -->
</template>
</z-lsh>| Name | Type | Default | Description |
|---|---|---|---|
value | String | The specific theme value to apply (e.g., “dark”, “z-theme-blue”) | |
group | String | Configuration group (e.g., “mode”, “color”, “font”) | |
toggle | Boolean | false | Enables toggle behavior for mode switching (ignores value attribute) |
prevent-autoupdate | Boolean | false | Prevents this instance from syncing with other instances |
cls | String | Custom CSS classes for the button | |
stl | String | Custom inline styles for the button | |
i18n | String | Internationalization strings as JSON object or via configuration script | |
force-prevent-rerender | Boolean | false | Prevents component rerendering (useful for HTMX or SPA scenarios) |
| Name | Description |
|---|---|
z-lsh:before-change | Fired before theme change (cancelable). Event detail contains {group, value, previousValue, config}. |
z-lsh:change | Fired after theme change. Event detail contains {group, value, previousValue, config}. |