Theming

A reader whose OS is in dark mode should get a dark page, and one who picks Catppuccin Latte should keep getting Latte on every page after that. chimera handles both with themes. A theme is a class that sets the colors, fonts and spacing every element reads.

Defaults

Each page has one default theme for light mode and one for dark mode. Until the reader picks a theme of their own, the page follows their OS setting:

site
    :default_dark_theme(catppuccin.Mocha)
    :default_light_theme(catppuccin.Latte)

Without defaults, pages use Light and Dark. A lone Document has the same methods.

Offering more themes

offer_theme adds a theme readers can pick, and a ThemeSwitcher lists it next to the defaults. This site offers six:

site
    :offer_theme(catppuccin.Macchiato)
    :offer_theme(catppuccin.Frappe)
    :offer_theme(Light)
    :offer_theme(Dark)

Try a theme:

const picker = Row({ Paragraph("Try a theme:"), ThemeSwitcher() }):align("center")

The browser saves the reader's pick, and links between pages carry it too. That way it sticks even on a site opened straight from disk.

Built-in themes

Your own theme

A theme is a class that implements Theme with a name, a mode and a palette. Any token you leave out of the Palette keeps its Light value:

class Sepia() implements Theme
    const name = "sepia"
    const mode = "Light"

    function palette(self): Palette
        return Palette {
            background = Color.hex("#f4ecd8"),
            text = Color.hex("#5b4636"),
            primary = Color.hex("#8b5e3c"),
            radius = "2px",
        }
    end
end

site:offer_theme(Sepia)

The parser finds every theme class by its name. label() sets the name the switcher shows. To restyle the built-in elements themselves, override base_styles().

Every built-in style reads its colors from tokens. Write yours the same way and they'll follow your theme as well (see Styling).