Skip to main content

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​

FamilyTokensPurpose
Pagebackground, foregroundApplication canvas and default text.
Cardcard, card-foregroundBounded content surfaces.
Popoverpopover, popover-foregroundMenus, popovers, and floating surfaces.
Primaryprimary, primary-foregroundMain actions and strong emphasis.
Secondarysecondary, secondary-foregroundLower-emphasis actions and surfaces.
Mutedmuted, muted-foregroundSupporting surfaces and metadata.
Accentaccent, accent-foregroundHover, selection, and contextual emphasis.
Destructivedestructive, destructive-foregroundIrreversible or dangerous actions.
Controlsborder, input, ringDividers, input boundaries, and focus.
Chartschart-1 through chart-5Data-series palette.
ShaperadiusShared 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:

ElementRecommended Scale
Page titletext-xl sm:text-2xl
Section headingtext-lg
Controls and tablestext-sm
Supporting metadatatext-xs or text-sm text-muted-foreground
Identifiers and machine valuesMonospace 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.