Theming
The design tokens, light and dark mode, and how to override them.
Every colour, radius and shadow in GlobUI is a CSS custom property with the --glob- prefix. The components use only the glob-* utilities (bg-glob-surface, text-glob-text-secondary), so changing a token changes every component.
Tokens
Light values are the default. Dark values apply when data-theme="dark" is set on <html>, or when the user prefers a dark colour scheme and has not chosen a theme. The values below are read from packages/styles/glob-ui.css at build time.
| Token | Light | Dark | Swatch |
|---|---|---|---|
| --glob-primary | #33CFA8 | #33CFA8 | |
| --glob-primary-hover | #2BB894 | #5CE3C1 | |
| --glob-primary-light | #E8FAF5 | #0F2A24 | |
| --glob-primary-foreground | #171717 | #0A0A0A | |
| --glob-primary-text | #0F7F68 | #33CFA8 | |
| --glob-surface | #FFFFFF | #0A0A0A | |
| --glob-surface-hover | #F5F5F5 | #1A1A1A | |
| --glob-surface-secondary | #FAFAFA | #141414 | |
| --glob-border | #E5E5E5 | #2A2A2A | |
| --glob-border-light | #F0F0F0 | #1F1F1F | |
| --glob-border-strong | #8C8C8C | #6B6B6B | |
| --glob-text | #171717 | #F5F5F5 | |
| --glob-text-secondary | #6B6B6B | #A3A3A3 | |
| --glob-muted | #A3A3A3 | #666666 | |
| --glob-ring | #1A9E80 | #33CFA8 | |
| --glob-danger | #B91C1C | #F87171 | |
| --glob-danger-light | #FEF2F2 | #2A1215 | |
| --glob-success | #15803D | #4ADE80 | |
| --glob-success-light | #F0FDF4 | #0F2A1A | |
| --glob-warning | #B45309 | #FBBF24 | |
| --glob-warning-light | #FFFBEB | #2A2010 | |
| --glob-info | #2563EB | #60A5FA | |
| --glob-info-light | #EFF6FF | #0F1A2E | |
| --glob-overlay | rgba(0, 0, 0, 0.5) | rgba(0, 0, 0, 0.7) |
Which token for which text
Use --glob-text for body text and --glob-text-secondary for helper text, placeholders, and icons that carry meaning (a chevron that shows an open list, for example). Both pass WCAG AA on every surface GlobUI uses, in light and dark.
--glob-muted is for decorative use only (dividers, purely visual icons) and is not used for text. Its light value fails 4.5:1 on white, so it must not carry information.
Light and dark
Set data-theme="light" or data-theme="dark" on <html> to force a theme. Leave it unset to follow the system.
This site uses next-themes through Fumadocs' RootProvider, with attribute: ["class", "data-theme"]. One toggle then sets both the dark class that Fumadocs reads and the data-theme attribute that GlobUI reads. A blocking script in <head> sets the attribute before the first paint, so there is no flash.
import { RootProvider } from "fumadocs-ui/provider/next"
<RootProvider theme={{ attribute: ["class", "data-theme"], defaultTheme: "system", enableSystem: true }}>
{children}
</RootProvider>Your app does not need Fumadocs. Without it, write the attribute yourself, for example with a small script that reads localStorage before paint.
Overriding tokens
Redefine a token on :root after importing the styles. The later rule wins.
@import "@glob-ui/styles";
:root {
--glob-primary: #0f766e;
--glob-primary-foreground: #ffffff;
}
:root[data-theme="dark"] {
--glob-primary: #5eead4;
--glob-primary-foreground: #042f2e;
}Primary and its foreground
--glob-primary is the brand colour: the fill of buttons, selected states and the active marker. The default is a teal (#33CFA8). Dark text sits on it (--glob-primary-foreground, #171717), at about 9:1, so the foreground is dark in both themes.
The teal is light, so it fails as text or as a focus line on white (about 2:1). Use --glob-primary-text for anything the primary colour does as text, links, or a line: it is a darker teal in light mode (#0F7F68, at least 4.5:1 on white and on the pale tint) and the same teal as the fill in dark mode. --glob-ring is the focus ring: at least 3:1 on the surface.
--glob-primary-hover and --glob-primary-light (the tint behind selected chips) are set beside the primary. If you change the primary, check that the foreground keeps at least 4.5:1 on the fill and on its hover, and that the text token keeps 4.5:1 on the tint.