Theming
A theme sets the presentation's colors, typography, and surfaces. Start with a preset, then override the values you need.
TypeScript or CSS?
Use TypeScript to choose values. Use CSS to define how components display them.
| Task | Where |
|---|---|
| Set shared colors, fonts, and surfaces | new Stage({ theme }) or stage.theme(...) in TypeScript |
| Override tokens for one element | The element's theme option in TypeScript |
| Set content, position, size, or animated state | Component options and element properties in TypeScript |
| Define a component's appearance | A CSS class that uses theme variables |
| Adjust one instance's CSS details | className for reusable styles, or style for a small override |
Theme options become CSS variables. Component styles read those variables, so the same CSS works with different palettes.
Choose a theme
The default is themes.defaultDark. Set a preset when creating the stage:
import { Stage, themes } from "stageroutine";
const stage = new Stage({ theme: themes.tokyoNight });
| Preset | Palette |
|---|---|
themes.defaultDark | Dark canvas, cyan and indigo accents |
themes.defaultLight | Light canvas, blue and indigo accents |
themes.tokyoNight | Navy canvas, blue and cyan accents |
themes.dracula | Dark violet canvas, pink and purple accents |
themes.cyberpunk | Deep purple canvas, crimson and purple accents, cyan text |
Preview these palettes on the brand page.
Use stage.theme(...) to change values for later steps. Omitted values keep their current settings. Going backward restores the theme saved for the earlier step.
stage.theme(themes.dracula);
Customize the palette
Four colors control the main palette. All are optional.
| Property | Default | Role |
|---|---|---|
background | #0c0d12 | Stage canvas |
text | #ffffff | Headings and source color for text tints |
primary | #38bdf8 | Kickers, focus borders, connectors |
secondary | #818cf8 | Decorative glow and surface highlights |
stage.theme({
background: "#1e1e2e",
text: "#cdd6f4",
primary: "#cba6f7",
secondary: "#89b4fa",
});
Muted text, glass fills, borders, and shadows follow these colors automatically. gradient() uses the palette; glow() uses secondary. See Visual Effects for effect options and backgrounds.
Adjust surfaces
Override a derived value when you need a different appearance:
stage.theme({
surface: "#1e293b",
surfaceBorderColor: "#475569",
surfaceBorderWidth: "2px",
radius: "0.75rem",
});
These defaults apply to the dark theme at scale: 1:
| Property | Default |
|---|---|
textMuted | Text color at 72% opacity |
textDim | Text color at 50% opacity |
surface | Glass gradient mixed from text and canvas colors |
surfaceBorderColor | Text color at 15% opacity |
surfaceBorderWidth | 1px |
surfaceHighlight | Text color at 25% opacity |
surfaceShadow | Dark drop shadow, primary outer glow, secondary inset highlight |
surfaceBackdrop | blur(16px) |
surfaceSolid | #18181b |
surfaceSubtle | #1e293b |
radius | 0.5rem |
surfaceBackdrop is a CSS backdrop-filter value. Set it to "none" to remove blur.
surfaceSolid and surfaceSubtle are fixed colors. The light preset overrides them with #f4f4f5 and #e2e8f0. They are not derived from background.
Style one element
Use color for an element's foreground. Use style for CSS details such as letter spacing:
import { Title } from "stageroutine";
const title = Title("Architecture", {
color: "#38bdf8",
style: { letterSpacing: "-0.04em" },
});
Use element properties for position, dimensions, scale, rotation, and opacity. The runtime manages these values during transitions. The style option accepts CSS properties typed with csstype.
Set a local theme
An element's theme overrides tokens for that element and its DOM children:
import { TerminalBlock } from "stageroutine";
const terminal = TerminalBlock({
title: "zsh",
theme: {
surface: "#11111b",
primary: "#a6e3a1",
secondary: "#cba6f7",
},
});
Omitted tokens inherit from the surrounding theme. Local primary and secondary overrides are independent. Changing one preserves the other.
Derived values recalculate where their source colors change. For example, local text changes recalculate text tints, borders, and the glass fill. Local accent changes recalculate the surface shadow. To keep a specific derived value, set it explicitly in the same local theme.
Change typography
The bundled fonts are:
| Property | Default | Used for |
|---|---|---|
fontSans | Inter | Titles, body text, lists, tables |
fontSerif | Newsreader | Serif titles and italic emphasis inside standard titles |
fontMono | JetBrains Mono | Code, terminals, kickers, connector labels |
Adjust text size
The stage scale option defaults to 1. It multiplies default font sizes, spacing, and radii. Explicit theme lengths keep their supplied values.
| Property | Default at scale: 1 | Used for |
|---|---|---|
fontSizeHero | 5rem | Title({ variant: "hero" }) |
fontSizeTitle | 2.75rem | Title() |
fontSizeLead | 1.875rem | Title({ variant: "serif" }) |
fontSizeBody | 1.375rem | Body text, lists, tables |
fontSizeCode | 1.125rem | Code and terminal body text |
fontSizeKicker | 1rem | Kickers and window labels |
stage.theme({
fontSizeTitle: "3.2rem",
fontSizeBody: "1.6rem",
});
Body text uses a line height of 1.5. Code and terminal text also use 1.5.
Add a custom font
Install a font package so the build can bundle it for offline use:
pnpm add @fontsource/plus-jakarta-sans
Import the weights you use in your presentation entry file:
import "@fontsource/plus-jakarta-sans/400.css";
import "@fontsource/plus-jakarta-sans/700.css";
Assign the family. Include a fallback font:
stage.theme({
fontSans: '"Plus Jakarta Sans", sans-serif',
});
Use CSS overrides
Add a className to an element and write a CSS rule:
const title = Title("Architecture", { className: "section-title" });
.section-title {
letter-spacing: -0.04em;
text-transform: uppercase;
color: var(--sr-secondary);
}
Import your stylesheet from the presentation entry file, for example import "./presentation.css".
Normal CSS rules outside a cascade layer override the library's normal layered rules. Inline options such as color and runtime geometry take precedence over normal stylesheet rules. Host-page CSS can also affect stage content.
Stage tokens are scoped to .sr-stage. Shared brand colors and font families are defined on :root. The stylesheet leaves host-page margins and scrolling to your application.
When building a custom component, define its defaults in a companion stylesheet inside @layer sr-components. Keep content and behavior in TypeScript. Reference theme tokens in CSS instead of copying preset colors into component code. Common mappings are:
| Theme property | CSS variable |
|---|---|
primary | --sr-primary |
secondary | --sr-secondary |
textMuted | --sr-text-muted |
surface | --sr-surface |
surfaceBorderColor | --sr-surface-border-color |
fontSans | --sr-font-sans |
Use border: var(--sr-surface-border) for the combined border width, style, and color. CSS-only appearance changes are not saved as step state; use theme and element properties for changes that must restore on backward navigation. See the ThemeConfig API for all configurable properties.