Themes and Design Tokens
Thyris UI uses semantic CSS variables as its color and shape contract. Components describe meaning through tokens rather than embedding product-specific colors.
Token Families
| Family | Tokens | Purpose |
|---|---|---|
| Page | background, foreground | Application canvas and default text. |
| Card | card, card-foreground | Bounded content surfaces. |
| Popover | popover, popover-foreground | Menus, popovers, and floating surfaces. |
| Primary | primary, primary-foreground | Main actions and strong emphasis. |
| Secondary | secondary, secondary-foreground | Lower-emphasis actions and surfaces. |
| Muted | muted, muted-foreground | Supporting surfaces and metadata. |
| Accent | accent, accent-foreground | Hover, selection, and contextual emphasis. |
| Destructive | destructive, destructive-foreground | Irreversible or dangerous actions. |
| Controls | border, input, ring | Dividers, input boundaries, and focus. |
| Charts | chart-1 through chart-5 | Data-series palette. |
| Shape | radius | Shared component corner radius. |
Token values use HSL channels without the outer hsl() function. Consume them through semantic Tailwind utilities or hsl(var(--token)).
Light and Dark Mode
The light token set is active at :root. Add dark to a shared ancestor, normally the document root, to activate the dark set:
document.documentElement.classList.toggle("dark", isDark)
Use force-light only for a subtree that must remain light regardless of application theme:
<section className="force-light bg-background text-foreground">
<PaymentProviderHostedSurface />
</section>
Theme state should have one owner. Do not let a component maintain a second theme state that can disagree with the document class.
Semantic Usage
export function SummaryPanel() {
return (
<section className="rounded-lg border bg-card p-4 text-card-foreground">
<h2 className="text-lg font-semibold">Usage summary</h2>
<p className="mt-1 text-sm text-muted-foreground">
Data for the current billing period.
</p>
</section>
)
}
Prefer semantic intent:
className="border bg-card text-card-foreground"
className="text-muted-foreground"
className="focus-visible:ring-1 focus-visible:ring-ring"
Avoid literal interface colors:
// Avoid
className="border-gray-200 bg-white text-slate-900"
Brand marks and third-party logos may retain their official colors. Product-specific brand and status tokens belong to the consumer rather than the shared package.
Typography
The standard operational hierarchy is:
| Element | Recommended Scale |
|---|---|
| Page title | text-xl sm:text-2xl |
| Section heading | text-lg |
| Controls and tables | text-sm |
| Supporting metadata | text-xs or text-sm text-muted-foreground |
| Identifiers and machine values | Monospace with wrapping or truncation rules. |
Use one clear primary heading per page. Avoid marketing-scale titles in dense operational interfaces unless the product has a specific requirement.
Spacing and Elevation
- Prefer the shared Tailwind spacing scale and
gap-*over arbitrary margins. - Use spacing and headings before adding another bordered card.
- Keep ordinary surfaces restrained with a border and small shadow where needed.
- Reserve elevation for interactive layers such as menus, popovers, and dialogs.
- Let toolbars wrap before controls become compressed.
Chart Colors
Use stable chart token assignments so a series keeps the same meaning across states and themes:
const config = {
requests: {
label: "Requests",
color: "hsl(var(--chart-1))",
},
errors: {
label: "Errors",
color: "hsl(var(--chart-2))",
},
}
Charts must also provide text labels, units, and an equivalent summary or table for essential values. Color and hover state cannot be the only way to understand the data.
Extending Tokens
A new consumer token should have:
- A semantic name tied to meaning rather than one literal color.
- Light and dark values with readable contrast.
- A documented usage boundary.
- A Tailwind mapping if it is consumed as a utility.
- Visual and accessibility checks across supported themes.
Do not change canonical package tokens in a local component file. Override them once at an application theme boundary when product branding requires a controlled variation.