cv-theme-palette-controller and cv-theme-palette-editor
Provides a constrained HWB palette customization surface for cv-theme-provider.
Headless: cv-theme-palette-controller
Anatomy
The controller owns persistence, preview application, and save events. The editor renders controls and calls controller model actions.
Controller Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
for | String | "" | id of the target cv-theme-provider |
storage-key | String | cv-theme-palette:v1 | localStorage key for the saved palette recipe |
theme-name | String | cv-user-palette | Runtime theme name registered in the theme engine |
Palette Recipe
The saved data is a versioned semantic recipe, not arbitrary CSS tokens:
ts
interface CVThemePaletteRecipe {
version: 1
schemes: {
light: Record<CVThemePaletteRole, CVHwbColor>
dark: Record<CVThemePaletteRole, CVHwbColor>
}
}Editable roles are:
bgsurfacetextprimaryaccentsuccesswarningdanger
Each role uses HWB channels:
ts
interface CVHwbColor {
h: number
w: number
b: number
}The model clamps values through CV_THEME_PALETTE_RANGES. Hue is limited to 0..359; whiteness and blackness are limited per role/scheme and normalized so w + b <= 100.
Behavior
- Draft edits apply immediately as live preview to the target provider.
- The editor separates light and dark scheme controls into tabs.
- Save writes only the compact recipe to
localStorage. - Save dispatches
cv-palette-savewith{version, themeName, recipe, tokens, savedAt}. - The event includes resolved light/dark token maps so app or SSR code can persist the generated result elsewhere.
- Corrupt or unsupported stored records are ignored and fall back to defaults.
- Save is blocked while contrast validation fails.
Events
| Event | Detail | Description |
|---|---|---|
cv-palette-save | CVThemePaletteSavedSnapshot | Fired by the controller after save |
Accessibility
- The editor uses labeled slider and number inputs for every channel.
- Validation messages are exposed through
role="status"andaria-live="polite". - Generated text/background pairings must pass WCAG AA contrast before save.
Styling
Component styles consume existing --cv-* tokens. Runtime palette values are generated by the model as hwb(...) theme tokens and applied through the theme engine.