Pick a preset or any brand colour, choose a base gray and a radius, and get the CSS, a shareable preset code and the CLI command.
A preset is four decisions: an eleven-step brand ramp, a base gray, a radius scale and, optionally, fonts. Pick a shipped preset or type any hex colour (the ramp is derived in OKLCH so every step keeps the same hue and step 600 stays readable under white text), then adjust the gray and the radius. The preview renders real Proper UI components with the result, in light or dark mode.
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
Invite your team
Collaborators get access to every project in this workspace.
Preset code
AZMABWJyYW5kApply it with the CLI
npx @properui/cli@latest theme apply AZMABWJyYW5kOr paste this after your Proper UI stylesheet import
/* properui:theme-preset */
/*
* Proper UI theme preset "Brand (default)" (code AZMABWJyYW5k).
* Re-apply with `npx @properui/cli@latest theme apply AZMABWJyYW5k` rather than editing by hand.
*/
@theme {
/* Brand ramp */
--color-brand-50: rgb(249 245 255);
--color-brand-100: rgb(244 235 255);
--color-brand-200: rgb(233 215 254);
--color-brand-300: rgb(214 187 251);
--color-brand-400: rgb(182 146 246);
--color-brand-500: rgb(158 119 237);
--color-brand-600: rgb(127 86 217);
--color-brand-700: rgb(105 65 198);
--color-brand-800: rgb(83 56 158);
--color-brand-900: rgb(66 48 125);
--color-brand-950: rgb(44 28 95);
/* Base gray: neutral. Every gray semantic token reads the neutral ramp, in both modes. */
--color-neutral-50: oklch(98.5% 0 none);
--color-neutral-100: oklch(97% 0 none);
--color-neutral-200: oklch(92.2% 0 none);
--color-neutral-300: oklch(87% 0 none);
--color-neutral-400: oklch(70.8% 0 none);
--color-neutral-500: oklch(55.6% 0 none);
--color-neutral-600: oklch(43.9% 0 none);
--color-neutral-700: oklch(37.1% 0 none);
--color-neutral-800: oklch(26.9% 0 none);
--color-neutral-900: oklch(20.5% 0 none);
--color-neutral-950: oklch(14.5% 0 none);
/* Radius: md */
--radius-xs: 0.125rem;
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--radius-2xl: 1rem;
--radius-3xl: 1.5rem;
--radius-4xl: 2rem;
}
/* /properui:theme-preset */
Applying the result
Any of these three does the same thing:
- CLI:
npx @properui/cli@latest theme apply <code>writes the block into your global stylesheet between/* properui:theme-preset */markers. Run it again with another preset or code and only that block is replaced. - During setup:
npx @properui/cli@latest init --preset <name|code>applies the preset as part ofinit. - By hand: paste the generated CSS after the Proper UI stylesheet import (
@import "@properui/ui/styles/globals.css", or your copiedtheme.css). Tailwind merges@themeblocks in source order, so the later block wins.
npx @properui/cli@latest theme list prints the shipped presets with their codes.
What a preset changes
A preset only redeclares primitives. Every semantic token (bg-brand-solid, text-primary, border-secondary, ring-brand and the rest) reads
them, in light and dark mode alike, so nothing else needs to change:
| Decision | Tokens it redeclares |
|---|---|
| Brand | --color-brand-50 to --color-brand-950 |
| Base gray | --color-neutral-50 to --color-neutral-950 |
| Radius | --radius-xs to --radius-4xl |
| Fonts | --font-body, --font-display (only when set) |
The base gray works by redeclaring the neutral ramp with the values of Tailwind's gray, slate, zinc or stone, because that ramp is what every
gray surface, border and text token resolves to. The radius options scale Tailwind's stock radius scale: none is square, md is the default, xl
doubles it. rounded-full pills stay pills.
The preset code is a short url-safe string that encodes all of it, so it can be pasted into the CLI, a pull request or an agent prompt. This page's address updates with the code, so the link reproduces the theme.