Add light theme overrides and documentation

This commit is contained in:
thePR0M3TH3AN committed 2025-10-11 14:10:57 -04:00
1 parent 317463619c
commit b20895ec32
4 files changed
+110 -8

No files matched your search

+12
View File
@@ -2,6 +2,18 @@
bitvid's visual language is now powered by Tailwind utilities backed by our design tokens. This document lists the primitives available via `css/tailwind.source.css`, how they behave across states, and when to mix them with Tailwind utilities.
## Theme System
The default experience renders the production dark palette. Pages and embeds can opt into alternates by setting the `data-theme` attribute on the `<html>` (or any ancestor that wraps the component). `data-theme="light"` promotes the light tokens defined in `css/tokens.css`, swapping surface, panel, border, muted, and overlay colors while keeping semantic accents consistent. Omit the attribute or set it back to `default` to inherit the dark baseline. Reserve additional theme keys (for example, `data-theme="contrast"`) for upcoming accessibility palettes—the same hook will activate them once their tokens land.
### Per-page overrides
Add `<html data-theme="light">` to force a page into light mode. The attribute can also target specific islands—wrap your component tree in a container with `data-theme="light"` when you need to render light cards inside a dark shell.
### Embedding in third-party surfaces
Components consume design tokens via CSS custom properties, so they pick up the active theme from the closest ancestor. When embedding widgets into a host site, include the `css/tokens.css` bundle and set `data-theme` on the wrapper to control contrast. If the host already defines its own theme, namespace our tokens (e.g., nest them inside a dedicated `.bitvid-embed[data-theme="light"]`) to avoid collisions while still letting overlay, border, and panel tokens cascade.
## Focus Handling
All interactive primitives mix in the shared `.focus-ring` helper. It removes default outlines and applies a branded ring using `focus-visible` only. When building bespoke components, add `.focus-ring` to your root interactive element or replicate its rules:
+51 -2
View File
@@ -10,10 +10,18 @@
<div class="min-h-screen bg-page-alt">
<header class="bg-surface text-text shadow-modal">
<div
class="mx-auto flex max-w-6xl items-center justify-between px-md py-sm"
class="mx-auto flex max-w-6xl items-center justify-between gap-sm px-md py-sm"
>
<h1 class="text-2xl font-semibold">bitvid UI Kitchen Sink</h1>
<button class="btn">Primary Action</button>
<div class="flex items-center gap-sm">
<label class="sr-only" for="themeSwitcher">Theme</label>
<select id="themeSwitcher" class="select h-10" aria-label="Select theme">
<option value="default">Default (Dark)</option>
<option value="light">Light</option>
<option value="contrast">High Contrast (Preview)</option>
</select>
<button class="btn">Primary Action</button>
</div>
</div>
</header>
@@ -708,5 +716,46 @@
</section>
</main>
</div>
<script>
(() => {
const storageKey = "bitvid-docs-theme";
const root = document.documentElement;
const switcher = document.getElementById("themeSwitcher");
const applyTheme = (value) => {
if (!value || value === "default") {
delete root.dataset.theme;
} else {
root.dataset.theme = value;
}
};
let savedTheme;
try {
savedTheme = window.localStorage.getItem(storageKey) || undefined;
} catch (error) {
savedTheme = undefined;
}
applyTheme(savedTheme);
if (switcher) {
switcher.value = savedTheme ?? "default";
switcher.addEventListener("change", (event) => {
const { value } = event.target;
applyTheme(value);
try {
if (!value || value === "default") {
window.localStorage.removeItem(storageKey);
} else {
window.localStorage.setItem(storageKey, value);
}
} catch (error) {
/* Ignore storage failures (private mode, etc.) */
}
});
}
})();
</script>
</body>
</html>