Colour theme
Dark-first tokens live on :root; light mode overrides use [data-theme="light"]. Call wckdThemeToggle() so buttons with id="theme-toggle" or data-wckd-theme-toggle stay in sync with localStorage (wckd-theme). Override colours in theme.css after core CSS instead of editing the kit files.
Download & setup
Start with the package download and setup steps in Get Started, then use the style guide for utility and token references while implementing this component.
Default implementation
Theme control
Use a <button> (or other clickable element) with the hook before the bootstrap runs. For text-only controls, the script sets textContent to Theme: Dark / Theme: Light. If the button contains svg or img, it does not replace inner markup; it updates aria-pressed and aria-label. To avoid a flash before JS runs, add a pre-paint snippet in <head> that reads localStorage and sets data-theme on <html> before CSS paints.
Use your existing button utilities.
Markup
<script>
(function () {
try {
var theme = localStorage.getItem("wckd-theme");
if (theme === "light" || theme === "dark") {
document.documentElement.setAttribute("data-theme", theme);
}
} catch (e) {}
})();
</script>
<button type="button" class="outline size-xs" id="theme-toggle" aria-label="Toggle colour theme" aria-pressed="false">Theme: Dark</button>
<!-- extra controls on the same page: -->
<button type="button" class="outline size-xs" data-wckd-theme-toggle aria-label="Toggle colour theme">Theme: Dark</button>
Configuration options
Start from the default implementation, then apply one of these intent-driven variations based on your content and interaction goals.
Theme output: buttons and surface levels
Reference swatches only: the same surface utilities and buttons rendered once per palette so you can eyeball contrast.
Default (:root)
Light override
Markup
<!-- output uses the same button + surface utility classes -->
<div class="columns count-2 gap-s">...</div>
Root theme tokens in CSS
These values mirror wckd-ui.css: dark defaults in :root, with [data-theme="light"] as the override layer.
:root (default)
--background-color: #24292E
--text-color: #f0f4f8
--line-color: rgb(255 255 255 / 0.12)
--primary-color: #4dabf7
Light tokens
--background-color: #f0f4f8
--text-color: #1a1f26
--line-color: rgb(26 31 38 / 0.14)
--primary-color: #05578a
Markup
:root{
--text-color:#f0f4f8;
--text-color-secondary:rgba(240, 244, 248, 0.92);
--primary-color:#4dabf7;
--background-color:#24292E;
--background-color-light:#2f363d;
--background-color-dark:#1f2227;
--background-color-fade:rgb(0 0 0 / 20%);
--line-color:rgb(255 255 255 / 0.12);
}
[data-theme="light"] {
--text-color:#1a1f26;
--text-color-secondary:rgba(26, 31, 38, 0.88);
--background-color:#f0f4f8;
--background-color-light:#ffffff;
--background-color-dark:#d8dee4;
--background-color-fade:rgba(0, 0, 0, 0.04);
--line-color:rgb(26 31 38 / 0.14);
--primary-color:#05578a;
}
DESIGN.md-style theme contract
Document where theme state lives (data-theme on <html>), which file owns token overrides, and how persistence maps to product requirements.
Theme contract
- Root state lives on
<html>by default, with optionaldata-theme="light". - Core defaults stay in
wckd-ui.css; project overrides live intheme.css(or a custom override file loaded later). - Use token overrides first (
--background-color,--text-color,--line-color,--primary-color,--secondary-color), selector overrides second. - Theme toggle persistence uses
localStorage["wckd-theme"]throughwckdThemeToggle().
Markup
# Theme Contract (DESIGN.md excerpt)
## Source of truth
- Root theme: <html> (default from :root), optional <html data-theme="light">
- Core tokens/defaults: wckd-ui.css
- Project overrides: theme.css or custom-theme.css (loaded after core CSS)
## Token-first customization
- Override tokens before writing component-specific selectors.
- Keep light/dark parity for readability and line contrast.
## Runtime
- wckdThemeToggle() syncs root data-theme with localStorage key "wckd-theme".
theme.css customization playbook
Checklist for loading order, token overrides in :root vs [data-theme="light"], and smoke-testing surfaces, without copying vendor CSS wholesale.
theme.css playbook
- Load
theme.css(or your custom stylesheet name) afterwckd-ui.cssandwckd-ui-components.css. - Set global brand + neutral tokens in
:root(your default theme). - Override light deltas in
[data-theme="light"]. - Test key surfaces: cards, borders, muted text, and buttons in both themes.
- Avoid direct hex overrides in component markup unless intentionally one-off.
Markup
/* theme.css checklist */
/* 1) load after core css */
/* 2) set global brand tokens */
:root { --primary-color: #5b7cfa; }
/* 3) light tokens */
[data-theme="light"] {
--background-color: #f6f8fc;
--text-color: #10131a;
}
/* 4) no dark block needed because :root is the default */
When to use
- User-chosen light or dark surfaces on marketing and app chrome.
- A second control in a drawer or settings panel should use
data-wckd-theme-toggleon the extras; reserveid="theme-toggle"for one control if you use the id hook at all.
Implementation notes
- Icon buttons: put the sun/moon (or similar) inside the button; the toggle script detects
svgorimgand keeps children intact. - To disable the feature in your build, remove the
wckdThemeToggle();call from the BOOTSTRAP block at the end ofwckd-ui.js, or ship a bootstrap that does not call it. - With dark-first defaults, no
data-themeattribute is required for initial dark render. Adddata-theme="light"only when you intentionally start in light mode. - This pattern is a manual light/dark switch, not automatic
prefers-color-schemeby itself. Document any media-query defaults you add intheme.cssseparately.
Developer checklist
- Use
<html>with nodata-themefor dark default, or setdata-theme="light"when light should be initial state. - Check project colours in
theme.cssfor both theme values if you override tokens. - Never duplicate
id="theme-toggle"in one document.