Theme
An opt-in theme setup with light, dark and system modes, semantic palette variables, a global reset and the Material Symbols font. ThemeModeToggle sets color-scheme metadata for your own mode control.
Usage
Current mode: light. This control and the navbar control share the same mode.
<script lang="ts">
import { Select, Theme, ThemeModeToggle } from 'bref-ui';
import type { ThemeMode, ThemeProps, Palette, Color } from 'bref-ui/types';
let mode = $state<ThemeMode>('auto');
const modes = [
{ id: 'auto', label: 'System' },
{ id: 'light', label: 'Light' },
{ id: 'dark', label: 'Dark' }
];
</script>
<Theme>
<ThemeModeToggle {mode} />
<label for="theme-mode">Theme</label>
<Select
id="theme-mode"
items={modes}
bind:value={() => mode, (next) => (mode = next as ThemeMode)}
/>
</Theme>
Playground
Try a shared palette or separate light and dark colors. Changes apply to the whole demo site while this page is open.
Live preview
Readable text and semantic colors follow the shared theme.
Settings
View generated code
<script>
import { Theme, ThemeModeToggle, Icon, Button } from 'bref-ui';
</script>
<Theme>
<ThemeModeToggle mode="light" />
<Icon name="check_circle" color="success" label="Complete" size="large" />
<Button variant="neutral" color="primary" label="neutral" />
<Button variant="soft" color="primary" label="soft" />
<Button variant="filled" color="primary" label="filled" />
<p>Readable text and semantic colors follow the shared theme.</p>
</Theme>
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
Theme: palette | Palette | { dark: Palette; light: Palette } | No | {} | Optional hex colors for the nine roles; a single palette applies to both modes. Invalid hex values throw. |
Theme: children | Snippet | No | Omitted | Application content. |
ThemeModeToggle: mode | ThemeMode | No | auto | light, dark or auto (system preference). |
Choosing a mode
Use the navbar theme control to test every example in light, dark or system mode. System follows the browser preference.
ThemeModeToggle renders color-scheme metadata and has no visible control. Pass a reactive mode from an application Select or Button. Theme accepts a children snippet; neither theme component
forwards native attributes or exposes an element binding.
Applications can also set data-theme="light" , data-theme="dark" or data-theme="auto" on a container to select its palette.
Palette
The active palette includes foreground and background colors, accents and semantic status colors.
--color-primary--color-secondary--color-foreground--color-background--color-muted--color-info--color-success--color-warning--color-errorCustomization
Pass palette to the application-root Theme. Omitted roles retain defaults. Existing CSS overrides still apply; verify contrast for custom colors.
<Theme palette={{ primary: '#875000' }} />
<Theme palette={{ light: { primary: '#875000' }, dark: { primary: '#e8bb75' } }} />
Override light and dark variables such as --color-primary-light and --color-primary-dark on :root or a themed container, or override an active color alias on a specific component. Verify final foreground/background
contrast.
Theme applies a global reset and loads Material Symbols. Components do not import it automatically.
Body text uses the --font-sans system sans fallback without loading a text font. Set --font-text to use your own font, as this gallery does, or customize --font-sans . Theme does not set font weight or smoothing.
Theme composes internal colors, surfaces, fonts and styles components. Surface and Button
share the surface paint recipe. Use the typed helper from bref-ui on native HTML; copied sources include it at theme/surface.ts .
<Button color="primary" label="Default primary" onClick={save} />
<Button
color="primary"
label="Local color override"
onClick={save}
style="--color-primary: var(--color-secondary);"
/>