Brand Color Tokens
1. The Brand Token Mental Model
While @shavin/ui provides a calibrated 24-color semantic accent scale, enterprise applications and brand-driven consumer apps often need custom brand colors (e.g. Oakwood Brown #8B5E3C, Stripe Blurple #635BFF, or Figma Purple).
Instead of manually calculating hover states, translucent tints, and dark mode contrast text for every brand color, Shavin uses an automated luminance-driven token generator. You define raw hex colors in brand-tokens.css, and our build engine produces a 7-token cluster per brand color:
Declare Hex Inputs
Add your brand hex values to the INPUT section of brand-tokens.css.
Auto-Generate Cluster
npm run brand:gen computes WCAG hover, contrast text, subtle bg, and hairline tokens for light and dark modes.
Zero-Config Tailwind
Use standard utilities like bg-brand-coral, text-brand-coral-contrast, and border-brand-teal.
2. Interactive Brand Token Playground
Select a preset brand color or enter a custom hex value to inspect how the luminance engine derives the 7-token cluster in real time:
--brand-oak--brand-oakBase solid fill--brand-oak-fgText on solid fills--brand-oak-hover±12% hover mix--brand-oak-contrastWCAG text on canvas--brand-oak-subtle12% translucent bg--brand-oak-hairline24% border stroke3. Setup & Generator Workflow
Running npx @shavin/cli init automatically creates your brand-tokens.css file, wires build hooks, and adds brand-preset.mjs to your Tailwind config.
Step 1: Declare brand colors in brand-tokens.css
Place raw hex colors or alias them to existing variables in the INPUT section:
/* brand-tokens.css — INPUT section (user-editable) */
/* ─── INPUT ─── */
--brand-primary: var(--accent); /* alias to active DS accent */
--brand-oak: #8B5E3C;
--brand-coral: #FF6B6B;
--brand-teal: #14B8A6;
/* --brand-gold: #F59E0B; */ /* commented lines are skipped */Step 2: Generate derived tokens
Run the generator command (also triggers automatically before npm run dev and npm run build):
npm run brand:gen # computes derived tokens + writes brand-preset.mjs
npm run brand:check # CI validation — exits 1 if brand tokens are staleStep 3: Connect Tailwind Preset
In your application's tailwind.config.ts, include the generated brandPreset:
// tailwind.config.ts
import type { Config } from "tailwindcss";
import shavinPreset from "@shavin/ui/tailwind-preset";
import brandPreset from "./brand-preset.mjs";
const config: Config = {
presets: [shavinPreset, brandPreset],
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/@shavin/ui/**/*.{js,ts,jsx,tsx}",
],
};
export default config;4. Token Cluster Specification
Every entry in brand-tokens.css generates the following seven semantic utilities in your Tailwind bundle:
| Suffix | Tailwind Classes | CSS Custom Property | WCAG Purpose |
|---|---|---|---|
| (base) | bg-brand-{name} | --brand-{name} | Solid brand fill for primary buttons, logos, and header banners. |
| -fg | text-brand-{name}-fg | --brand-{name}-fg | High-contrast text (#0A0A0C or #FFFFFF) on top of solid brand fills. |
| -hover | hover:bg-brand-{name}-hover | --brand-{name}-hover | Luminance-aware ±12% darkened/lightened hover state fill. |
| -contrast | text-brand-{name}-contrast | --brand-{name}-contrast | Guaranteed ≥ 4.5:1 contrast text and icons when rendered directly on page canvas. |
| -subtle | bg-brand-{name}-subtle | --brand-{name}-subtle | 12% translucent background tint for chips, badges, and soft cards. |
| -subtle-hover | hover:bg-brand-{name}-subtle-hover | --brand-{name}-subtle-hover | 18% translucent background hover state for interactive soft items. |
| -hairline | border-brand-{name}-hairline | --brand-{name}-hairline | Subtle border stroke (24% light, 32% dark) for cards and outline buttons. |
5. Production Usage Examples
Here is how you compose accessible branded cards, badges, and action bars using Tailwind utilities:
// Branded Callout Card Component
export function OakwoodFeatureCard() {
return (
// ds-lint-disable-next-line no-unknown-class — brand token example
<div className="p-5 rounded-[var(--radius-panel)] bg-brand-oak-subtle border border-brand-oak-hairline flex flex-col gap-3">
<div className="flex items-center justify-between">
// ds-lint-disable-next-line no-unknown-class — brand token example
<span className="px-2 py-0.5 rounded-[var(--radius-lg)] text-xs font-semibold bg-brand-oak text-brand-oak-fg">
Artisanal Roast
</span>
// ds-lint-disable-next-line no-unknown-class — brand token example
<span className="text-xs font-mono text-brand-oak-contrast">Single Origin</span>
</div>
// ds-lint-disable-next-line no-unknown-class — brand token example
<h3 className="text-sm font-bold text-brand-oak-contrast">
Oakwood Signature Blend
</h3>
<p className="text-xs text-fg-muted leading-relaxed">
Locally roasted with notes of hazelnut and dark chocolate.
</p>
<div className="flex items-center gap-2 pt-1">
// ds-lint-disable-next-line no-unknown-class — brand token example
<button className="px-3 py-1.5 rounded-[var(--radius-lg)] text-xs font-semibold bg-brand-oak hover:bg-brand-oak-hover text-brand-oak-fg transition-colors">
Order Now
</button>
// ds-lint-disable-next-line no-unknown-class — brand token example
<button className="px-3 py-1.5 rounded-[var(--radius-lg)] text-xs font-semibold border border-brand-oak-hairline text-brand-oak-contrast hover:bg-brand-oak-subtle-hover transition-colors">
View Notes
</button>
</div>
</div>
);
}