Themed #

Fuz provides UI components that use Moss' theming system for dark mode and custom themes.

Themed adds global support for both the browser's color-scheme and custom themes based on Moss style variables, which use CSS custom properties . Themed is a singleton component that's mounted at the top-level of the page:

import Themed from '@ryanatkn/fuz/Themed.svelte';
<!-- +layout.svelte -->
<Themed>
	{@render children()}
</Themed>
Why the singleton?
Why nested children?

Color scheme
#

Themed defaults to automatic color-scheme detection with prefers-color-scheme , and users can also set it directly:

import Color_Scheme_Input from '@ryanatkn/fuz/Color_Scheme_Input.svelte';
<Color_Scheme_Input />

Pass props to override the default:

<Color_Scheme_Input
	value={{color_scheme: 'auto'}}
	onchange={...}
/>

The builtin themes support both dark and light color schemes. Custom themes may support one or both color schemes.

More about Color_Scheme_Input

Builtin themes
#

A theme is a simple JSON collection of Moss style variables that can be transformed into CSS that set custom properties. Each variable can have values for light and/or dark color schemes. In other words, "dark" isn't a theme, it's a mode that any theme can implement.

  • Example usage
    #

    Themes are plain CSS that can be sourced in a variety of ways.

    To use Fuz's base theme:

    <!-- +layout.svelte -->
    <script>
    	import '@ryanatkn/moss/style.css';
    	import '@ryanatkn/moss/theme.css';
    	import Themed from '@ryanatkn/fuz/Themed.svelte';
    	import type {Snippet} from 'svelte';
    
    	interface Props {
    		children: Snippet;
    	}
    	
    	const {children}: Props = $props();
    <script>
    
    <!-- enable theme and color-scheme support -->
    <Themed>
    	{@render children()}
    </Themed>

    Themed can be customized with the the nonreactive prop themer:

    import {Themer} from '@ryanatkn/fuz/theme.svelte.js';
    const themer = new Themer(...);
    <Themed {themer}>
    	{@render children()}
    </Themed>

    Themed sets the themer in the Svelte context:

    // get values from the Svelte context provided by
    // the nearest `Themed` ancestor:
    import {themer_context} from '@ryanatkn/fuz/theme.js';
    const themer = themer_context.get();
    themer.theme.name; // 'base'
    themer.color_scheme; // 'auto'

    For a more complete example, see fuz_template.

    More details
    #

    Themed initializes the system's theme support. Without it, the page will not reflect the user's system color-scheme. By default, Themed applies the base theme to the root of the page via create_theme_setup_script. It uses JS to add the .dark CSS class to the :root element.

    This strategy enables color scheme and theme support with minimal CSS and optimal performance for most use cases. The system supports plain CSS usage that can be static or dynamic, or imported at buildtime or runtime. It also allows runtime access to the underlying data like the style variables if you want to pay the performance costs. Scoped theming to one part of the page is planned.

    The theme setup script interacts with sync_color_scheme to save the user's preference to localStorage. See also Color_Scheme_Input.

    The setup script avoids flash-on-load due to color scheme, but currently themes flash in after loading. We'll try to fix this when the system stabilizes.