Guides
Theming
Customise the widget appearance with CSS variables, fonts, and images
The widget is themed entirely through CSS variables. Pass an object of overrides to the cssVariables prop — they're written onto the widget's host element, so everything inside reacts.
import { Widget } from "@superbridge/widget";
<Widget
cssVariables={{
"--color-foreground": "hsl(240 10% 4%)",
"--color-card": "hsl(0 0% 100%)",
"--color-card-foreground": "hsl(240 10% 4%)",
"--color-primary": "hsl(240 6% 10%)",
"--color-primary-foreground": "hsl(0 0% 98%)",
"--radius": "0.75rem",
"--sb-card-corner": "squircle",
"--sb-card-shadow": "0 1px 2px rgba(0,0,0,0.06)",
}}
/>The cssVariables object is fully typed via WidgetCssVariables — your editor autocompletes every available token, so the reference list below is intentionally high-level.
Variable groups
The variables fall into a few categories:
Colors
Semantic color roles, each with a background, a -foreground for text/icons on top, and an -outline for the border ring.
--color-foreground— default body text--color-card/--color-popover— main surfaces and floating menus--color-primary/--color-secondary/--color-muted/--color-accent/--color-destructive— action roles--color-border,--color-input,--color-ring— separators, input borders, focus rings
Typography
--font-heading,--font-button,--font-body— font families per role--tracking-heading,--tracking-button,--tracking-body— letter-spacing per role
See Styling fonts below.
Radius
--radius— base radius. The full--radius-2xs…--radius-4xlscale is derived from this viacalc(), so retuning the base retunes everything.
Styling fonts
Font variables accept any valid CSS font-family value. To use a custom font, load it yourself with @font-face (or a <link> to a hosted provider) and then point the variables at it:
/* your-app.css */
@font-face {
font-family: "Acme Display";
src: url("/fonts/acme-display.woff2") format("woff2");
font-display: swap;
}
@font-face {
font-family: "Acme Text";
src: url("/fonts/acme-text.woff2") format("woff2");
font-display: swap;
}<Widget
cssVariables={{
"--font-heading": '"Acme Display", ui-sans-serif, system-ui, sans-serif',
"--font-button": '"Acme Display", ui-sans-serif, system-ui, sans-serif',
"--font-body": '"Acme Text", ui-sans-serif, system-ui, sans-serif',
"--tracking-heading": "-0.01em",
"--tracking-body": "0em",
}}
/>Tips:
- Always include a system fallback stack — the widget renders before your font finishes loading.
- Prefer
woff2andfont-display: swapto avoid invisible text during load. - Hosted fonts (Google Fonts, Fontsource, etc.) work the same way — load the stylesheet, then reference the family name.
- If
--font-buttonis unset it inherits whatever the surrounding role uses; set it explicitly when you want buttons to look distinct from headings.