Skip to content

Interactive playground

Theme Kit Playground

Everything below runs on Theme Kit's real runtime — the same store, history, and resolver that ships in the library. Switch a family or mode, explore the token tree, audit contrast, run a transition, and watch CSS variables update live.

Live theme switcher

Family controls the palette, mode controls light/dark/system.

theme-kit-default-light
Family
Mode

Theme Scope

Sandbox any subtree with its own theme — independent of the global runtime.

scoped

Component-Scoped Themes

Each card below uses a different scoped theme, independent of the global theme.

Slack Dark (scoped)

This card always uses the forest color palette regardless of the global theme.

Plum Dark (scoped)

This card always uses the plum color palette regardless of the global theme.

Global Theme (no scope)

This card follows the global theme and changes when you toggle.

Live preview

theme-kit · system
T
Theme Kit
theme-kit-default-light
Re-themed live
Muted card
Token-driven UI
Accent
Swaps with the theme
Semantic swatches--theme-color-*
background
foreground
primary
secondary
accent
muted
success
destructive
border
ring
card

History & time travel

Every theme change is recorded as a snapshot. Click any entry to jump to that point in time.

1 snapshot · capped at 50 · theme-kit-default-light is current

Interactive token tree

Expand a group, search a token, or hover a value to copy its CSS variable.

background
foreground
card
cardForeground
popover
popoverForeground
primary
primaryForeground
secondary
secondaryForeground
muted
mutedForeground
accent
accentForeground
destructive
destructiveForeground
success
successForeground
border
input
ring
  • colors21
    • background
    • foreground
    • card
    • cardForeground
    • popover
    • popoverForeground
    • primary
    • primaryForeground
    • secondary
    • secondaryForeground
    • muted
    • mutedForeground
    • accent
    • accentForeground
    • destructive
    • destructiveForeground
    • success
    • successForeground
    • border
    • input
    • ring
  • radius1
    • lg12px
  • code19
    • background#f6f7fc
    • foreground#0f172a
    • comment#6b7280
    • keyword#7c3aed
    • string#07865c
    • number#d97706
    • function#2563eb
    • variable#0f172a
    • type#db2777
    • property#0284c7
    • operator#7c3aed
    • punctuation#475569
    • tag#be185d
    • attribute#0284c7
    • lineNumber#9ca3af
    • selectionrgba(91, 84, 232, 0.12)
    • highlightrgba(91, 84, 232, 0.06)
    • gutter#f6f7fc
    • border#e4e6f2

3 token groups · values are the resolved runtime tokens for the active theme.

Multi-window sync

Theme selections sync across tabs and windows in real time via BroadcastChannel (with SharedWorker and StorageEvent fallbacks).

UnavailableTransport: none
This tablive runtime
Theme: theme-kit-default-light
Family / mode: theme-kit / system
Other tabsimulated

Changes made here flow over the channel to every real tab open on this site — exactly what a second browser tab would do.

0remote changes
0windows opened
last sync

No cross-tab sync method is available in this browser.

Scheduled themes · solar time

Run the real useThemeSchedule() controller: enable the schedule to flip the whole site between light and dark at sunrise/sunset. Leave it on Auto to use your own detected timezone — no coordinates needed — or pick any timezone in the world and watch the sun path follow it. See the Sunrise & Sunset page for per-framework setup.

Schedule off
Applied now: theme-kit-default-light
Sunrise
—:—
Sunset
—:—
Next transition
—:—
Scheduled themes
/

This runs the real useThemeSchedule() controller against the site runtime, switching the whole page between light and dark at sunrise/sunset. With Auto selected, your own timezone is detected — no coordinates needed, anywhere in the world. Pick a timezone below to reposition the schedule, or drag the lat/lon sliders for a manual preview.

Sunrise
—:—
Now
—:—
Sunset
—:—
Sun path today
06121824
Sun position now — pick a timezone above or drag the sliders to move around the world.

Theme Kit computes NOAA-style solar times via calculateSunTimes(date, lat, lon) — with no coordinates it auto-detects the visitor's timezone — and can auto-switch between light and dark at sunrise/sunset with the scheduled runtime option. Current site mode: system.

Theme generator

Generate a complete light/dark theme pair from a seed color, then copy the JSON or CSS variables.

Theme generator

Pick a seed color and generate a matching light/dark theme pair. Optional syntax-highlighting code tokens are generated on request.

Animation & transition lab

Run the real transition pipeline — createThemeDiff, createTransitionPlan and runThemeAnimation — and tune duration, easing and presets live.

brand.appA
Get started
400ms
Easing
Preset
createScopedThemeBinding runs the real pipeline → createThemeDiff → createTransitionPlan → runThemeAnimation (smooth preset) → coordinating 400ms cubic-bezier(0.4, 0, 0.2, 1) on matched properties.
Scoped / nested region — transitions independently
Feature tileScoped via createScopedThemeBinding — runs its own transition while the rest of the page is untouched.

Scoped subtree runs the real theme-kit animation pipeline (createThemeDiffcreateTransitionPlanrunThemeAnimation). Its transition timeline is independent of the page-level theme.

Custom scrollbar

The real overlay engine, integrated on this site — scroll the panel to see the theme-colored strip replace the native bar. For per-framework setup, see Custom Scrollbar.

Live — the actual scrollbarruns on this docs site

This panel is a plain scrollable container, exactly like the one you would wrap in include to scope the overlay. On this site the real ThemeScrollbar from @theme-kit/next is mounted in the root layout — so every scrollable area on this page, including this one, is an integrated custom scrollbar. Run your cursor over the edge to reveal the theme-colored strip, then scroll.

1

Managed container — row 1. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

2

Managed container — row 2. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

3

Managed container — row 3. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

4

Managed container — row 4. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

5

Managed container — row 5. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

6

Managed container — row 6. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

7

Managed container — row 7. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

8

Managed container — row 8. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

9

Managed container — row 9. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

10

Managed container — row 10. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

11

Managed container — row 11. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

12

Managed container — row 12. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

13

Managed container — row 13. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

14

Managed container — row 14. The native bar is hidden by the pre-paint bootstrap and the overlay strip represents the scroll position instead.

Accessibility lab

Check WCAG contrast on any pair, simulate color-vision deficiency, and audit the active theme's semantic pairs.

Contrast checker

Pick any two colors and check WCAG AA/AAA compliance instantly.

foreground
background
Aaratio 17.85 : 1
AAAA largeAAAAAA large

This pair passes AA for normal text.

Live theme audit · theme-kit-default-light

validateThemeContrast() run against the active theme's semantic pairs.

foreground on background
18.37AA
cardForeground on card
19.00AA
popoverForeground on popover
19.00AA
primaryForeground on primary
5.41AA
secondaryForeground on secondary
15.11AA
mutedForeground on muted
5.61AA
accentForeground on accent
5.63AA
destructiveForeground on destructive
3.76AA

Color vision deficiency simulation

simulateCVD() of the active primary (#5b54e8).

Re-themes the site with every color run through simulateThemeForCVD() so you can check readability exactly as a user with that condition sees it.

Accessibility profiles

Ready-made high-contrast and large-text themes shipped in getBuiltInThemes().

High Contrast · Light

Maximum contrast for readability.

High Contrast · Dark

Maximum contrast on dark backgrounds.

Large Text · Light

Enlarged type on light backgrounds.

Large Text · Dark

Enlarged type on dark backgrounds.

The accessibility plugin — reacting to violations

createAccessibilityPlugin() audits every applied theme at WCAG AA and fires onViolation when a theme breaks the configured requirements. This is that callback, live.

Try it: a “low-contrast-demo” theme (white foreground on white background) is handed to the plugin's onAfterThemeChange hook — exactly what happens when such a theme is applied to a runtime.

Theme studio

Generate a full light/dark pair from a seed with generateTheme(), preview it, and apply it to this site live.

Indigo Lightindigo-light
A
Generated light theme
Derived from your seed with HSL math
Indigo Darkindigo-dark
A
Generated dark theme
Derived from your seed with HSL math
Theme JSON
indigo-light · indigo-darkjson
1{
2  "light": {
3    "name": "indigo-light",
4    "meta": {
5      "family": "indigo",
6      "mode": "light",
7      "label": "Indigo Light",
8      "order": 10
9    },
10    "tokens": {
11      "colors": {
12        "background": "#f8fafc",
13        "foreground": "#0f172a",
14        "card": "#ffffff",
15        "cardForeground": "#0f172a",
16        "popover": "#ffffff",
17        "popoverForeground": "#0f172a",
18        "primary": "#6366f1",
19        "primaryForeground": "#ffffff",
20        "secondary": "#e4e4f1",
21        "secondaryForeground": "#0f172a",
22        "muted": "#efeff5",
23        "mutedForeground": "#64748b",
24        "accent": "#c6c6ec",
25        "accentForeground": "#0f172a",
26        "destructive": "#ef4444",
27        "destructiveForeground": "#ffffff",
28        "success": "#22c55e",
29        "successForeground": "#ffffff",
30        "border": "#d9d9e8",
31        "input": "#d9d9e8",
32        "ring": "#6366f1"
33      },
34      "radius": {
35        "lg": "8px"
36      }
37    }
38  },
39  "dark": {
40    "name": "indigo-dark",
41    "meta": {
42      "family": "indigo",
43      "mode": "dark",
44      "label": "Indigo Dark",
45      "order": 20
46    },
47    "tokens": {
48      "colors": {
49        "background": "#020617",
50        "foreground": "#f8fafc",
51        "card": "#0f172a",
52        "cardForeground": "#f8fafc",
53        "popover": "#0f172a",
54        "popoverForeground": "#f8fafc",
55        "primary": "#9596ea",
56        "primaryForeground": "#020617",
57        "secondary": "#060846",
58        "secondaryForeground": "#f8fafc",
59        "muted": "#050638",
60        "mutedForeground": "#94a3b8",
61        "accent": "#151651",
62        "accentForeground": "#f8fafc",
63        "destructive": "#f87171",
64        "destructiveForeground": "#020617",
65        "success": "#4ade80",
66        "successForeground": "#020617",
67        "border": "#080a5e",
68        "input": "#080a5e",
69        "ring": "#9596ea"
70      },
71      "radius": {
72        "lg": "8px"
73      }
74    }
75  }
76}
Playground — Theme Kit