Theme switcher

The theme is data-theme on html

<html data-theme="dark"> or "light" means a theme is chosen. Without the attribute, the system theme (prefers-color-scheme) applies. data-theme-toggle buttons change this value and save it in localStorage under the key tsunami-theme. Every colour variable has a second value for dark.

Toggle

data-theme-toggle with no value switches between light and dark, based on the current theme.

No flash on load

The script applies the saved theme as soon as it runs, so load it as a plain script in <head>. With type="module" or defer it runs after the first paint, and people who chose dark see a white flash. If localStorage is blocked, the theme still changes but is only kept for that page.

<script src="https://cdn.jsdelivr.net/gh/Djirasak/tsunami-framework@v0.1.3/dist/tsunami.min.js"></script>

Icon and label follow the theme

data-theme-show="dark" shows only in dark and "light" only in light. It is pure CSS (it reads html[data-theme] or prefers-color-scheme), so it is correct before JS loads.

set() picks a theme by name

window.tsunami.theme.set(name) takes "light", "dark" or "system". Use it to change the theme from code, for example after a user saves their account settings.

Read with get(), listen for a change

get() returns "dark" or "light", whichever is showing. The event fires on document on every set() / toggle() / button click, and when the system theme changes while system is chosen.

Components redraw on a change

CSS updates colours on its own. A canvas or iframe that the page draws itself must listen for tsunami:themechange, read the new colour variables and redraw.

Attributes

Attribute / element Values Description
html[data-theme] (none = system, default), light, dark The chosen theme, set by JS and the head script. Without it, prefers-color-scheme applies.
.theme-switcher div + role="group", aria-label Segmented frame for theme buttons. Children are <button>s with icons.
data-theme-toggle (empty), light, dark, system Works on any button. Empty = toggle light / dark, any other value = set(value); system clears the saved choice.
aria-pressed true, false JS sets it on the data-theme-toggle button whose value matches the current choice (system when there is no data-theme).
aria-label text Required on icon-only buttons.
data-theme-show light, dark Shows the element only in that theme. Pure CSS.
tsunami-theme light, dark localStorage key that holds the choice. Removed when system is chosen.

API

Functions live on window.tsunami.theme.

Function / event Arguments / detail Description
theme.get() - Returns "dark" or "light" for the theme on screen (including when it follows the system).
theme.set(name) name: "light", "dark", "system" Sets and saves the theme. Any value other than light / dark counts as system.
theme.toggle() - Switches to the other theme from the one on screen.
tsunami:themechange { theme, choice } Fires on document after every set() / toggle() / button click (even if the value is unchanged), and when the system theme changes while system is chosen. theme = "dark" | "light", choice = "light" | "dark" | "system"