Skip to main content
Urbicon UI
source

ThemeSwitcher

Light/dark/system theme switcher with localStorage persistence, system preference detection, and multiple interaction modes.

Playground

Variant
Size
Strategy
<ThemeSwitcher />

01 Examples

Cycle vs. toggle

Default cycles light → dark → system. Pass strategy='toggle' to flip between light and dark only.
<ThemeSwitcher />
<ThemeSwitcher strategy="toggle" />

Variants and sizes

<ThemeSwitcher variant="ghost" size="sm" />
<ThemeSwitcher variant="outlined" size="md" />
<ThemeSwitcher variant="filled" size="lg" />

In a settings panel

Realistic use — outlined trigger inline with related appearance preferences.

Appearance

Color theme

Reduce motion

<div
  class="bg-surface-elevated border-border-subtle w-full overflow-hidden rounded-2xl border"
>
  <div class="border-border-subtle border-b px-5 py-3">
    <h3 class="text-text-primary text-sm font-semibold">Appearance</h3>
  </div>
  <div class="divide-border-subtle divide-y">
    <div class="flex items-center justify-between px-5 py-3">
      <p class="text-text-primary text-sm font-medium">Color theme</p>
      <ThemeSwitcher variant="outlined" size="sm" />
    </div>
    <div class="flex items-center justify-between px-5 py-3">
      <p class="text-text-primary text-sm font-medium">Reduce motion</p>
      <Toggle size="sm" intent="primary" />
    </div>
  </div>
</div>

02 Customization

Branded trigger

Override the button and icon slots for a gradient brand-look. Pass storageKey=false for ephemeral switching without persistence.
<ThemeSwitcher
  slotClasses={{
    button:
      'bg-linear-to-r from-violet-500 to-fuchsia-500 text-white hover:from-violet-600 hover:to-fuchsia-600 shadow-md shadow-violet-500/20',
    icon: 'h-5 w-5'
  }}
/>

03 Accessibility

The trigger carries a dynamic aria-label and title that name the active theme ("Light mode" / "Dark mode" / "System theme"). Focusable via Tab, activated with Enter / Space; uses focus-visible: for keyboard-only rings. In system mode the UI live-follows prefers-color-scheme changes natively via color-scheme: light dark — no JavaScript needed.

04 API Reference

11 props
11 props
Prop
Type
Default
Description

05 Types

Local type definitions used by this component.

6 types
Name
Kind
Category
Used by
Description

06 Installation

Import

import { ThemeSwitcher } from '@urbicon-ui/blocks';

FOUC Prevention

<!-- Add to app.html <head> for flash-free theme loading -->
<script>
  // Only explicit choices set a class; system mode leaves
  // color-scheme: light dark to follow the OS via light-dark().
  const t = localStorage.getItem('urbicon-theme');
  if (t === 'dark') document.documentElement.classList.add('dark');
  else if (t === 'light') document.documentElement.classList.add('light');
</script>