The systemLumos 0.0.1

Theming

Four themes that are classes, not settings, and why that means anything can sit inside anything.

Lumos has four color themes: theme-light, theme-dark, theme-brand and theme-invert. Each one redeclares the same set of tokens (background, text, border, button colors, link colors), so anything inside it picks up the right colors without knowing where it is.

astro
<div class="theme-light padding-4">Light</div>
<div class="theme-dark padding-4">Dark</div>
<div class="theme-brand padding-4">Brand</div>
<div class="theme-invert padding-4">The opposite of whatever is around it</div>

Each swatch is a plain div with a theme class, and the buttons inside are the same Button component every page uses. Nothing in them is styled per theme: they read the theme's tokens, hover states and all. theme-invert has no colors of its own, so it flips whichever theme it lands in.

Why classes and not a setting

A site-wide dark mode toggle can only answer one question: is the page dark? Real designs need more than that: a dark section in a light page, a brand-colored card inside the dark section, a light panel inside that.

Because a theme is a class, it applies to a subtree. Every level can set its own, and everything inside inherits until something changes it. A Button never asks what page it is on; it reads --button-background, which is whatever the nearest theme says it is.

The four

ThemeWhat it is for
theme-lightLight surfaces. What :root starts as.
theme-darkDark surfaces.
theme-brandThe brand color as a background, with text chosen for contrast.
theme-invertThe opposite of its parent. Inside a light theme it is dark; inside a dark theme it is light.

theme-invert is the one to reach for when a panel should contrast with whatever it lands in: a callout that must stand out in both a light and a dark section, without you having to know which.

Applying one

Section, BaseLayout and Card take a theme prop:

astro
<Section theme="dark">
  <Heading tag="h2">On a dark surface</Heading>
  <Card theme="brand" heading="And a brand card inside it" />
</Section>

Anywhere else, use the class directly. It is just CSS:

astro
<div class="theme-invert padding-5 radius-main">
  Contrasts with whatever surrounds it.
</div>

The contract

Every theme declares the same tokens. If you add a fifth theme, declare all of them or components inside it will fall back to whatever the parent said.

What a theme sets

NameValueNotes
--backgroundthe surface colorApplied automatically to any element carrying a theme class.
--background-2a raised surfaceFor cards and panels sitting on the background.
--background-skeletona faint tintThe placeholder behind an image or video while it loads.
--textbody textAlso the basis for borders and muted text through color-mix.
--borderhairline colorDerived from the text color, so it works on any surface.
--heading-accentaccent colorUsed by .heading-accent for a highlighted word inside a heading.
--button-*background, border, text, and their hover pairsThe primary button set.
--button-2-*the same, for the secondary buttonOutlined by default.