Skip to content


Theming is done with CSS variables.

The default variables are set on the :root.

Below variables are recommended but not required, since missing variables will be determined automatically.

:root {
--base-background: hsl(0, 0%, 100%);
--base-hover: hsl(0, 0%, 97%); /* hover background */
--base-border: hsl(0, 0%, 83%);
--base-focus: hsl(0, 0%, 10%); /* focus ring */
--base-foreground: hsl(0, 0%, 4%);
--raised-background: hsl(0, 0%, 97%); /* cards, panels, etc. */
--muted-foreground: hsl(0, 0%, 25%);
--outline-border: hsl(0, 0%, 83%); /* inputs, outline buttons, etc. */
--secondary-background: hsl(0, 0%, 94%);
--secondary-hover: hsl(0, 0%, 92%);
--secondary-foreground: var(--base-foreground);
--primary-background: hsl(0, 0%, 0%);
--primary-hover: hsl(0, 0%, 16%);
--primary-foreground: hsl(0, 0%, 100%);
--border-radius: 1; /* Multiplier on all border-radius values */

Dark theme

Dark mode is applied via a simple .theme-dark class.

Optionally, you can use .full.theme-dark to only apply the dark theme to components in the library.

.theme-dark {
--base-background: #020202;
--base-hover: #101010;
--base-border: #333333;
--base-focus: #fff;
--base-foreground: #fff;
/* etc. */

Custom themes

Just like dark mode, you can define any custom theme you want. As many as you want.

.theme-happy {
/* variables go here */


Because of the way the color system works under the hood, there are more variables available than just the ones listed above. The following variants are available:

  • base: the default values
  • raised: used for cards and other panels
  • accent: used for accent colored text, like a tagline
  • muted: used for lower contrast text elements
  • ghost: used for interactive components without a background and border
  • outline: used for interactive components with a border but no background
  • secondary: used for secondary interactive components
  • primary: used for primary interactive components

Each variant has all 5 colors available: background, hover, border, focus and foreground.

In practice, you probably don’t need all of them. For example; the background of ghost defaults to transparent.