Theming
The theme is one stylesheet that sets Summit’s colors for light and dark, its radius scale, its typeface, and its motion curves.
tokens.css replaces the stylesheet that a shadcn project starts with. It keeps shadcn’s variable names, adds success and warning, and sets Summit’s values. See Installation for where to import it.
Declarations
| Subject | Declaration | Page |
|---|---|---|
| Color | A variable in :root for each color, with a dark value in .dark and a --color-* theme variable that generates its utilities | Color |
| Radius | --radius at 0.25rem, and the steps computed from it | Radius |
| Typeface | --font-sans and --font-heading, both Hanken Grotesk Variable, with an import of its font files | Typography |
| Display type | A line height and a letter spacing for text-4xl to text-9xl | Typography |
| Motion | --ease-out and --ease-in-out, with --ease-out as the default curve of a transition and of animate-in and animate-out | Motion |
| Reduced motion | One rule under prefers-reduced-motion: reduce that removes movement and scale and keeps fades | Motion |
| Dark mode | The dark variant, which matches inside a .dark element | Dark Mode |
The file also imports Tailwind CSS, tw-animate-css, and shadcn/tailwind.css. The last one defines variants that the components use, such as data-checked.
Base Styles
In the base layer, tokens.css sets the border color of every element to border and its outline color to ring. A border class with no color class is then drawn in border.
body has the background fill, foreground text, tabular figures, and antialiasing. Links, buttons, labels, summary elements, and elements with a role such as switch or tab have touch-action: manipulation.
Overrides
Override a value, not a name. Components read only the names that tokens.css declares, so a new variable has no effect on them.
Colors and Radius
The colors and --radius are custom properties. To override one, redeclare it after the import.
Set both values of a color. When the dark class is on html, a :root rule that follows the import overrides the .dark value in tokens.css, so a color overridden in :root alone keeps that one value in dark.
@import '@bysolstice/tokens/tokens.css';
:root {
--accent: oklch(0.45 0.12 250);
--ring: oklch(0.45 0.12 250);
--sidebar-ring: oklch(0.45 0.12 250);
}
.dark {
--accent: oklch(0.68 0.12 250);
--ring: oklch(0.68 0.12 250);
--sidebar-ring: oklch(0.68 0.12 250);
}ring and sidebar-ring are the same color as accent, so the example changes all three.
An overridden color isn’t checked. The ratios on the Color page are computed from Summit’s own values, so measure a new color against the same floors: 4.5 to 1 for text and 3 to 1 for a mark.
--radius has one value, and every step is computed from it. If you set --radius: 0.5rem, each step doubles, and rounded-lg changes from 4px to 8px.
If you redeclare a variable on any other selector, the new value applies only inside that element because a utility reads the variable where it is used.
Theme Variables
The typeface, the two curves, and the display type settings are Tailwind theme variables. To override one, add a theme block after the import: @theme inline for a font, and @theme for a curve or a display setting.
The font files that tokens.css imports have the Latin, Latin Extended, Vietnamese, and Cyrillic Extended subsets. If the product is in Arabic or Hebrew, set --font-sans to a typeface that has the script. --font-heading points to --font-sans, so it changes too. For the layout of such a product, see Right-to-Left.
@import '@bysolstice/tokens/tokens.css';
@import '@fontsource-variable/noto-sans-arabic';
@theme inline {
--font-sans: 'Noto Sans Arabic Variable', sans-serif;
}Dark Mode
tokens.css has one mechanism for dark mode, a dark class. The color variables each have a second value under .dark; see Color for both. --radius and the theme variables don’t change.
The Class
Add dark to html. body and everything in it then read the dark values.
tokens.css doesn’t add the class. It has no prefers-color-scheme query and no script, so the product decides when the class is present.
You can use next-themes to manage the class. The CLI already installs it with Sonner, whose Toaster reads the theme from it. If you set attribute="class", its ThemeProvider writes the theme’s name to the class of html.
import { ThemeProvider } from 'next-themes';
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class">{children}</ThemeProvider>
</body>
</html>;ThemeProvider also tells the browser which color scheme is active, so the browser’s own controls match. tokens.css doesn’t set color-scheme.
The Variant
By default, Tailwind’s dark: variant follows prefers-color-scheme. tokens.css redefines it to follow the class.
@custom-variant dark (&:is(.dark *));The variant matches the elements inside the element that has the class, but not that element itself. A dark: class on html never applies.
A color class doesn’t need a dark: variant because its variable already changes. Use the variant when the class itself differs between themes, for example an alpha: bg-success/15 dark:bg-success/25.
A Dark Region
If you add dark to any other element, its subtree is dark in a light page. A Dialog or a menu that opens from inside the region renders in a portal on body, outside the region, so it stays light.
There is no class for the reverse. tokens.css declares the light values on :root alone, so nothing inside .dark can return to light.