Claude
Skills
Sign in
Back

policyengine-design

Included with Lifetime
$97 forever

PolicyEngine design system — tokens, typography, colors, charts, and branding for all project types. Triggers: "brand colors", "design tokens", "PolicyEngine colors", "typography", "font", "color palette", "CSS variables", "design system", "branding guidelines"

Ads & Marketing

What this skill does


# PolicyEngine design system

Single source of truth for PolicyEngine's visual identity. Design tokens are defined as CSS custom properties in `@policyengine/ui-kit/theme.css`. Every frontend project imports this single CSS file.

**When to use which format:**

| Context | Approach | Example |
|---------|----------|---------|
| **React components** | Tailwind semantic classes | `className="bg-primary text-foreground"` |
| **Brand palette** | Tailwind direct classes | `className="bg-teal-500 text-gray-600"` |
| **Recharts (SVG)** | CSS vars directly in fill/stroke | `fill="var(--chart-1)"` |
| **Inline styles** | CSS vars | `style={{ color: "var(--primary)" }}` |
| **Python (Plotly)** | Hex with CSS var comment | `TEAL = "#319795"  # --chart-1` |
| **`<meta>` tags, static HTML** | Hex values with CSS var name in comment | `content="#319795"` |

Python has no CSS runtime, so hex values are acceptable — but always comment with the CSS var name so values stay traceable to the design system.

## The ui-kit theme

**Install:**
```bash
bun install @policyengine/ui-kit
```

**Import the theme CSS in your `globals.css`:**
```css
@import "tailwindcss";
@import "@policyengine/ui-kit/theme.css";
```

The first line enables Tailwind v4 utilities. The second provides all PE design tokens, `@theme` configuration, and base styles. Both are required — see `policyengine-ui-kit-consumer-skill` for details.

**Source:** `PolicyEngine/policyengine-ui-kit/src/theme/tokens.css`

The theme CSS has three layers:
1. **`:root`** — shadcn/ui semantic variables (`--primary`, `--background`, `--chart-1`, etc.)
2. **`@theme inline`** — Bridges `:root` vars to Tailwind utilities (`bg-primary`, `text-foreground`)
3. **`@theme`** — Brand palette (`bg-teal-500`, `text-gray-600`), font sizes, spacing, breakpoints

## Colors

### Primary — teal

| Token | Hex | Tailwind class | Usage |
|-------|-----|---------------|-------|
| `teal-500` | `#319795` | `bg-teal-500` | **Main brand color** — charts, highlights |
| `teal-400` | `#38B2AC` | `bg-teal-400` | Lighter interactive elements |
| `teal-600` | `#2C7A7B` | `bg-teal-600` / `bg-primary` | Hover state, buttons |
| `teal-700` | `#285E61` | `bg-teal-700` | Active/pressed state |
| `teal-50` | `#E6FFFA` | `bg-teal-50` | Tinted backgrounds |
| `teal-800` | `#234E52` | `bg-teal-800` | Dark text on light teal |

### Semantic (shadcn/ui)

| Role | CSS variable | Tailwind class | Hex |
|------|-------------|---------------|-----|
| Primary | `--primary` | `bg-primary` | `#2C7A7B` |
| Background | `--background` | `bg-background` | `#FFFFFF` |
| Foreground | `--foreground` | `text-foreground` | `#000000` |
| Muted | `--muted` | `bg-muted` | `#F2F4F7` |
| Muted foreground | `--muted-foreground` | `text-muted-foreground` | `#6B7280` |
| Border | `--border` | `border-border` | `#E2E8F0` |
| Destructive | `--destructive` | `bg-destructive` | `#DC2626` |
| Card | `--card` | `bg-card` | `#FFFFFF` |
| Ring | `--ring` | `ring-ring` | `#319795` |

### Charts

| CSS variable | Tailwind class | Hex | Usage |
|-------------|---------------|-----|-------|
| `--chart-1` | `fill-chart-1` | `#319795` | Primary series (teal) |
| `--chart-2` | `fill-chart-2` | `#0EA5E9` | Secondary series (blue) |
| `--chart-3` | `fill-chart-3` | `#285E61` | Tertiary series (dark teal) |
| `--chart-4` | `fill-chart-4` | `#026AA2` | Quaternary series (dark blue) |
| `--chart-5` | `fill-chart-5` | `#6B7280` | Quinary series (gray) |

### Additional semantic colors

These are the **brand fill** values — use for status dots, badges, and tinted surfaces. They are *not* WCAG-AA-compliant when set as text on a white background; for text, use the accessible-on-white variants below.

| Color | Hex | Tailwind class |
|-------|-----|---------------|
| Success | `#22C55E` | `text-success` / `bg-success` |
| Error | `#DC2626` | `text-destructive` / `bg-destructive` |
| Warning | `#FEC601` | `text-warning` / `bg-warning` |
| Info | `#1890FF` | `text-info` / `bg-info` |

### Accessible-on-white text variants

Distinct from the brand fills above — these are the values you use when you actually need to render colored text on a white background and want to clear WCAG 2.2 AA (4.5:1 contrast at small text). Available since ui-kit 0.5.0 as `--text-warning` / `--text-error` / `--text-success` and the corresponding Tailwind utilities.

| Token | Hex | Tailwind class | Contrast on white |
|-------|-----|---------------|-------------------|
| `--text-warning` | `#c2410c` (Tailwind orange-700) | `text-warning-foreground` | 5.18:1 ✓ |
| `--text-error` | `#B91C1C` (Tailwind red-700) | `text-error-foreground` | 5.94:1 ✓ |
| `--text-success` | `#285E61` (PE teal-700) | `text-success-foreground` | 7.07:1 ✓ |

The plain `text-warning` / `text-destructive` / `text-success` brand classes are intentionally *not* AA on white — they're meant for soft-tinted backgrounds and badge fills, not paragraph text.

### Dark mode

Available since ui-kit 0.6.0. Activate by adding `class="dark"` to any ancestor element — no JS or media query required. Every shadcn semantic token (`--primary`, `--background`, `--card`, `--border`, etc.) and accessible text variant has a dark-mode value pinned to clear AA on the dark page background `#0B0E14`. Dark-mode values are tested by `tests/theme/contrast.test.ts` in ui-kit and exposed under the `:root.dark` selector in `theme.css`.

```html
<!-- consumer site dark-mode toggle: just toggle the .dark class on <html> -->
<html class="dark">
  ...
</html>
```

If you're rendering charts, prefer the CSS-var form (`fill="var(--chart-1)"`) over a hex literal — that way the chart picks up dark-mode swaps automatically. For Plotly / Python where there's no CSS runtime, use `chartPalette.light` and `chartPalette.dark` from `@policyengine/ui-kit` and pick by detected theme.

### Gray scale

ui-kit's `palette.gray` is Slate-flavored (matches the dashboard's neutral surfaces and `--border` / `--muted` tokens). The legacy `@policyengine/ui-kit/legacy/tokens` shim still exports the Tailwind-3 grays (`#6B7280` for 500, `#4B5563` for 600) for design-system migration parity, but new code should use the canonical Slate values below.

| Token | Hex | Tailwind class |
|-------|-----|---------------|
| `gray-50` | `#F0F9FF` | `bg-gray-50` |
| `gray-100` | `#F2F4F7` | `bg-gray-100` |
| `gray-200` | `#E2E8F0` | `bg-gray-200` |
| `gray-300` | `#CBD5E1` | `bg-gray-300` |
| `gray-400` | `#94A3B8` | `bg-gray-400` |
| `gray-500` | `#64748B` | `text-gray-500` |
| `gray-600` | `#475569` | `text-gray-600` |
| `gray-700` | `#344054` | `text-gray-700` |
| `gray-800` | `#1E293B` | `text-gray-800` |
| `gray-900` | `#101828` | `text-gray-900` |

## Typography

### Font families

**Two font families only: Inter + JetBrains Mono.** No serif fonts, no Roboto, no Public Sans.

| Context | Font | CSS variable | Tailwind |
|---------|------|-------------|----------|
| **Everything** (UI, charts, blog, tools) | Inter | `--font-sans` | `font-sans` |
| **Code** | JetBrains Mono | `--font-mono` | `font-mono` |

**Loading Inter:**
```html
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
```

### Font sizes

| Tailwind class | Size | Usage |
|---------------|------|-------|
| `text-xs` | 12px | Small labels, captions |
| `text-sm` | 14px | Body text, form labels |
| `text-base` | 16px | Large body text |
| `text-lg` | 18px | Subheadings |
| `text-xl` | 20px | Section titles |
| `text-2xl` | 24px | Page titles |
| `text-3xl` | 28px | Large headings |

### Sentence case

All UI text uses sentence case — capitalize only the first word and proper nouns.

- "Your saved policies" not "Your Saved Policies"
- "Tax liability by income" not "Tax Liability by Income"
- Proper nouns stay capitalized: "Child Tax Credit", "PolicyEngine", "California"

## Spacing

Standard Tailwind spacing classes (`p-4`, `gap-2`, `m-6`) use the default Tailwind scale. Named spacing tokens:

| Token | V

Related in Ads & Marketing