ThemeModeButton
A button that toggles between light and dark mode. Keep ThemeMode in your root layout: the button can flip the mode on its own, but ThemeMode is what applies the saved
choice when a page loads.
onclick handler no longer replaces the toggle: it runs first, and calling preventDefault() in it cancels the toggle. loading shows the spinner again instead of the mode icon, which 2.8.0 had hidden. The button also flips the
mode when ThemeMode is not
mounted, though the saved choice is still only applied on load by ThemeMode.Playground
Basic Usage
Drop in anywhere below ThemeMode.
<script lang="ts">
import { ThemeModeButton } from 'sv5ui';
</script>
<ThemeModeButton />Variants
<ThemeModeButton variant="ghost" />
<ThemeModeButton variant="outline" />
<ThemeModeButton variant="soft" />
<ThemeModeButton variant="subtle" />
<ThemeModeButton variant="solid" />Sizes
<ThemeModeButton size="xs" />
<ThemeModeButton size="sm" />
<ThemeModeButton size="md" />
<ThemeModeButton size="lg" />
<ThemeModeButton size="xl" />Colors
<ThemeModeButton color="surface" />
<ThemeModeButton color="primary" />
<ThemeModeButton color="secondary" />
<ThemeModeButton color="success" />
<ThemeModeButton color="warning" />
<ThemeModeButton color="error" />
<ThemeModeButton color="info" />Accessibility
The button is named Toggle theme, which describes what it does in either mode. Naming it after the target mode reads worse
than it sounds: the name changes under the reader's finger the moment they press it, and it
is wrong for the brief moment between the press and the class landing on <html>.
Both icons are in the DOM at all times and hidden dark:block decides which one shows. That is what keeps the server markup and the first client render identical,
so nothing flickers or sticks on reload.
Custom Icons
Override the default sun/moon icons. Both are rendered; CSS shows one.
<!-- Custom icon set -->
<ThemeModeButton
lightIcon="lucide:sunrise"
darkIcon="lucide:sunset"
/>
<!-- Different icon collections -->
<ThemeModeButton
lightIcon="mdi:white-balance-sunny"
darkIcon="mdi:weather-night"
/>Custom Content
Use children snippet with isDark for
fully custom content.
<ThemeModeButton>
{#snippet children({ isDark })}
{isDark ? '🌙' : '☀️'}
{/snippet}
</ThemeModeButton>Click Handler
Pass onclick to run your own code on a press, for analytics or to save the choice to an account. It runs before
the toggle. To stop the toggle, call event.preventDefault() in the handler.
<script lang="ts">
import { ThemeModeButton, Switch } from 'sv5ui';
let clicks = $state(0);
let locked = $state(true);
</script>
<!-- Runs first, then the mode toggles -->
<ThemeModeButton onclick={() => (clicks += 1)} />
<!-- preventDefault() cancels the toggle -->
<ThemeModeButton
onclick={(event) => {
if (locked) event.preventDefault();
}}
/>
<Switch bind:checked={locked} label="Lock the theme" />Loading
loading swaps
the mode icons for a spinner and disables the button, for the moment a choice is being saved somewhere.
<ThemeModeButton loading />
<ThemeModeButton loading variant="outline" />
<ThemeModeButton loading variant="solid" color="primary" />Styled Examples
<!-- Outline style for navbars -->
<ThemeModeButton variant="outline" color="surface" />
<!-- Solid accent button -->
<ThemeModeButton variant="solid" color="primary" />
<!-- Subtle minimal style -->
<ThemeModeButton variant="subtle" color="surface" size="sm" />UI Slots
| Slot | Description |
|---|---|
base | Root button element - controls layout, colors, transitions |
icon | Icon element - controls icon sizing and shrink behavior |
Snippets
| Snippet | Props | Description |
|---|---|---|
children | isDark: boolean | Custom content replacing default icon, receives current theme state |
Props
| Prop | Type | Default |
|---|---|---|
variant | 'solid'|'outline'|'soft'|'subtle'|'ghost'|'link' | 'ghost' |
color | ColorType | 'surface' |
size | 'xs'|'sm'|'md'|'lg'|'xl' | 'md' |
lightIcon | string | 'lucide:sun' |
darkIcon | string | 'lucide:moon' |
loading | boolean | false |
onclick | (event: MouseEvent) => void | - |
disabled | boolean | false |
square | boolean | true |
block | boolean | false |
class | string | - |
ui | Record<Slot, Class> | - |