Getting Started

Dark Mode

One component in your root layout and every sv5ui component follows the theme, with the right one on the page before the first paint rather than after it.

Setup

Two things are needed: the ThemeMode component in your layout, and the @custom-variant CSS rule. There is nothing else to install: sv5ui handles dark mode itself.

src/routes/+layout.svelte
<script lang="ts">
  import './layout.css';
  import { ThemeMode } from 'sv5ui';

  let { children } = $props();
</script>

<ThemeMode />
{@render children()}
src/routes/layout.css
@import 'tailwindcss';
@import 'sv5ui/theme.css';

/* Required for Tailwind dark mode to follow the .dark class ThemeMode sets */
@custom-variant dark (&:where(.dark, .dark *));

Toggle Button

SV5UI provides a ready-to-use ThemeModeButton component that toggles between light and dark mode with a smooth icon animation.

<script lang="ts">
  import { ThemeModeButton } from 'sv5ui';
</script>

<!-- Default -->
<ThemeModeButton />

<!-- Outline variant, small -->
<ThemeModeButton size="sm" variant="outline" />

<!-- Soft primary, large -->
<ThemeModeButton size="lg" variant="soft" color="primary" />

<!-- Custom icons -->
<ThemeModeButton lightIcon="lucide:sun-medium" darkIcon="lucide:moon-star" />

Programmatic Control

Six helpers come from sv5ui itself. They are runes rather than stores, so read .current without a $ prefix.

+page.svelte
<script lang="ts">
  import { mode, resetMode, setMode, toggleMode, userPrefersMode } from 'sv5ui';
</script>

<!-- These are runes, not stores: read .current, with no $ prefix -->
<p>On screen: {mode.current}</p>          <!-- 'dark' | 'light' -->
<p>Chosen: {userPrefersMode.current}</p>  <!-- 'dark' | 'light' | 'system' -->

<!-- Set specific mode -->
<button onclick={() => setMode('dark')}>Dark</button>
<button onclick={() => setMode('light')}>Light</button>

<!-- Toggle, or hand control back to the operating system -->
<button onclick={toggleMode}>Toggle</button>
<button onclick={resetMode}>Follow the system</button>

Styling with Dark Mode

Use Tailwind's dark: variant for custom styles, or use sv5ui's semantic color classes that adapt automatically.

Example.svelte
<!-- Tailwind dark: variant works automatically -->
<div class="bg-white dark:bg-gray-900">
  <p class="text-gray-900 dark:text-white">
    This text adapts to the theme.
  </p>
</div>

<!-- sv5ui semantic colors adapt automatically -->
<div class="bg-surface text-on-surface">
  <p class="text-on-surface/60">
    Semantic colors handle dark mode for you.
  </p>
</div>

Why Semantic Colors?

SV5UI's OKLCH tokens adapt automatically - you rarely need Tailwind's dark: variant.

ApproachCode
Manual (verbose)
bg-white dark:bg-gray-900 text-gray-900 dark:text-white
Semantic (automatic)
bg-surface text-on-surface