duck.html.components.theme

Theme system for HTML components.

Provides design tokens (colors, spacing, typography, etc.) as CSS custom properties so any component can reference var(–theme-) instead of hardcoded literals. Tokens are open-ended — add any name/value pair, not just the built-in defaults.

Package Contents

Classes

Theme

An extensible set of design tokens.

ThemeMeta

Metaclass for Theme that provides class-level current theme access.

Data

DEFAULT_THEME

_current_theme

API

duck.html.components.theme.DEFAULT_THEME

‘Theme(…)’

class duck.html.components.theme.Theme(name: str = 'default', base: Optional[duck.html.components.theme.Theme] = None, dynamic: bool = False, **tokens: str)[source]

An extensible set of design tokens.

Tokens live in a plain dict so new ones can be added at construction time or later via update() — useful for overrides, plugin tokens, or runtime values. Each token becomes –<CSS_PREFIX>- in CSS.

Tokens read like plain attributes; writes go through update() or the constructor. Attempting to set a token via attribute assignment raises, so a typo like theme.border_color = “white” fails loudly instead of silently shadowing the token:

theme.update(border_color="white")
theme.border_color # "white"
theme.border_color = "red" # raises AttributeError

The dynamic flag changes what attribute reads return: off, you get the literal value; on, you get the CSS var name instead, so the same read can be dropped straight into a stylesheet. It can be flipped at any time:

theme.dynamic = True
theme.border_color # "--theme-border-color"
theme.dynamic = False
theme.border_color # "white"

var() always returns the CSS var name regardless of the flag, and get() takes a per-call dynamic override:

theme.var("border_color") # "--theme-border-color"
theme.get("border_color", dynamic=True) # "--theme-border-color"
theme.get("border_color") # "white"

Access the globally active theme at the class level:

active = Theme.current
Theme.current = my_custom_theme

Initialization

Initialize a new theme with layered tokens.

Parameters:
  • name – Identifier for this theme.

  • base – Optional Theme to inherit from before applying defaults and explicit overrides.

  • dynamic – Whether attribute reads return the CSS var name instead of the literal value. Can be toggled on this instance at any time after construction.

  • **tokens – Any token name/value pairs. Unknown names are accepted, this is what makes the theme extensible.

CSS_PREFIX: ClassVar[str]

‘theme’

DEFAULTS: ClassVar[dict[str, str]]

None

RESERVED_ATTRS: ClassVar[frozenset[str]]

‘frozenset(…)’

__getattr__(key: str) str[source]

Allow attribute-style reads, e.g. theme.accent_color.

Returns the literal token value, or the CSS var name instead when dynamic is on for this instance.

Parameters:

key – Token name to look up.

Returns:

The token’s literal value, or its CSS var name if dynamic.

Raises:

AttributeError – If the token does not exist.

__setattr__(key: str, value: str) None[source]

Block attribute-style writes to tokens; only real instance state (name, dynamic, tokens) can be set this way.

Parameters:
  • key – Attribute name being set.

  • value – Value being assigned.

Raises:

AttributeError – If key isn’t reserved instance state — tokens must be set via update() or the constructor instead.

extend(name: str, **overrides: str) duck.html.components.theme.Theme[source]

Create a new Theme inheriting this theme’s tokens.

Parameters:
  • name – Name for the derived theme.

  • **overrides – Tokens to change or add.

Returns:

A new Theme instance; this theme is left unchanged.

get(key: str, default: str = '', dynamic: Optional[bool] = None) str[source]

Return a token’s value or CSS var name safely, without raising.

Parameters:
  • key – Token name to look up.

  • default – Fallback if the token is missing.

  • dynamic – Overrides this instance’s dynamic flag for just this call. Leave unset to use the instance’s current setting.

Returns:

The literal value, the CSS var name, or default if missing.

to_css_vars() dict[str, str][source]

Convert every token into a CSS custom property.

Always uses literal values regardless of the dynamic flag, since a CSS custom property can’t declare itself as its own var name.

Returns:

Dict mapping –<CSS_PREFIX>- to its literal value.

to_style(selector: str = ':root') duck.html.components.style.Style[source]

Build a Style component declaring this theme’s CSS variables.

Parameters:

selector – CSS selector to scope variables under. Defaults to :root for global theming. Pass .theme-dark to scope to a subtree.

Returns:

A Style component, ready for page.add_to_head().

update(**tokens: str) duck.html.components.theme.Theme[source]

Add new tokens or override existing ones after construction.

Parameters:

**tokens – Token name/value pairs to merge in.

Returns:

self, for chaining.

var(key: str) str[source]

Return a token’s CSS var name, regardless of the dynamic flag.

Parameters:

key – Token name to look up.

Returns:

The CSS var name, e.g. “–theme-border-color”.

Raises:

AttributeError – If the token does not exist.

class duck.html.components.theme.ThemeMeta[source]

Bases: type

Metaclass for Theme that provides class-level current theme access.

property current: duck.html.components.theme.Theme

Return the globally active theme.

Returns:

The active Theme instance, or DEFAULT_THEME if none was set.

duck.html.components.theme._current_theme: duck.html.components.theme.Theme

None