Theme Authoring
Create custom themes to customize Sireno Deck’s appearance.
Theme Structure
Section titled “Theme Structure”my-theme/├── sirenodeck.json # Manifest├── components.css # Component styles└── assets/ # Fonts and images ├── IBM_Plex_Sans/ │ └── IBMPlexSans-Medium.ttf └── IBM_Plex_Mono/ └── IBMPlexMono-Regular.ttfManifest (sirenodeck.json)
Section titled “Manifest (sirenodeck.json)”{ "kind": "theme", "apiVersion": 1, "name": "my-theme", "version": "1.0.0", "description": "My custom theme", "colorTokens": { "background": "#000000", "frame": "#333333", "foreground": "#ffffff", "foreground-contrast": "#ffffff", "primary": "#3b82f6", "accent": "#8b5cf6", "success": "#22c55e", "danger": "#ef4444", "tintBlue": "#3b82f6", "tintGreen": "#22c55e", "tintPurple": "#8b5cf6" }, "typography": { "main_text": { "fontFamily": "IBM Plex Sans", "fontSize": 12, "fontWeight": 500, "letterSpacing": 0 }, "auxiliary_text": { "fontFamily": "IBM Plex Sans", "fontSize": 10, "fontWeight": 400, "letterSpacing": 0 }, "monospace": { "fontFamily": "IBM Plex Mono", "fontSize": 11, "fontWeight": 400, "letterSpacing": 0 } }, "fonts": [ { "fontFamily": "IBM Plex Sans", "fontWeight": 500, "fontStyle": "normal", "src": "./assets/IBMPlexSans-Medium.ttf" } ], "assets": { "styles": ["./components.css"] }}Color Tokens
Section titled “Color Tokens”Available Tokens
Section titled “Available Tokens”| Token | CSS Variable | Description |
|---|---|---|
background |
--sireno-color-bg |
Main background |
frame |
--sireno-color-frame |
Button border |
foreground |
--sireno-color-fg |
Primary text |
foreground-contrast |
--sireno-color-fg-contrast |
High-contrast text |
primary |
--sireno-color-primary |
Primary accent |
accent |
--sireno-color-accent |
Secondary accent |
success |
--sireno-color-success |
Success state |
danger |
--sireno-color-danger |
Error state |
tintBlue |
--sireno-color-tint-blue |
Blue variant |
tintGreen |
--sireno-color-tint-green |
Green variant |
tintPurple |
--sireno-color-tint-purple |
Purple variant |
Typography
Section titled “Typography”Role Definitions
Section titled “Role Definitions”{ "typography": { "main_text": { "fontFamily": "IBM Plex Sans", "fontSize": 12, "fontWeight": 500, "letterSpacing": 0 }, "auxiliary_text": { "fontFamily": "IBM Plex Sans", "fontSize": 10, "fontWeight": 400 }, "monospace": { "fontFamily": "IBM Plex Mono", "fontSize": 11, "fontWeight": 400 } }}Usage in CSS
Section titled “Usage in CSS”.main-text { font-family: var(--sireno-font-main_text); font-size: var(--sireno-font-size-main_text); font-weight: var(--sireno-font-weight-main_text);}Font Loading
Section titled “Font Loading”Font Face Format
Section titled “Font Face Format”{ "fonts": [ { "fontFamily": "IBM Plex Sans", "fontWeight": 500, "fontStyle": "normal", "src": "./assets/IBMPlexSans-Medium.ttf" } ]}Component Styling
Section titled “Component Styling”components.css
Section titled “components.css”/* Button styles */.sireno-button { border-radius: 8px; transition: all 0.15s ease;}
.sireno-button:active { transform: scale(0.95);}
/* Custom surface */.my-surface { background: var(--sireno-color-bg); border: 1px solid var(--sireno-color-frame);}
/* Animation */@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; }}CSS Variables Available
Section titled “CSS Variables Available”--sireno-color-*— All color tokens--sireno-font-*— Typography values--sireno-spacing-*— Spacing values
Testing Themes
Section titled “Testing Themes”# Use theme during developmentsireno run --config config.yml
# Config references theme by name, path, or npm packagetheme: defaulttheme: ./packages/themes/my-themetheme: @sirenodeck/theme-neon-gridsThe theme: value is a single string resolved in three passes:
- Registered theme name —
default,light, or any theme already loaded into the registry. - Path — any string starting with
./,../,/, or a Windows drive letter resolves to a theme directory on disk. - npm package — anything else is treated as a package name and
resolved via Node’s resolver to
<pkg>/package.json. The package directory is then loaded as a theme.
Theme UI Overrides
Section titled “Theme UI Overrides”Advanced: Replace React components entirely:
{ "ui-overrides": "./components"}The ui-overrides path resolves to a module that exports three optional buckets. Each is shallow-merged into the default presentation; missing slots fall back to the built-in component.
export const components = { ButtonFrame: MyCustomButtonFrame,}
export const surfaces = { IconLabel: MyCustomIconLabel, IconLabelProgress: MyCustomIconLabelProgress, TemporaryError: MyCustomTemporaryError,}
export const primitives = { Label: MyCustomLabel, TapIndicator: MyCustomTapIndicator,}Override fns receive the same props as the default component plus an
optional second argument — a ThemeOverrideContext with the active theme
name, colors, and typography — so they can read sibling tokens without
parsing CSS variables.
Top-level helpers (deckBackground) also live in the same module:
export const deckBackground = ({ className }) => `${className} bg-[radial-gradient(...)]`