AnglinAI Color System (v2)
The v2 color system lives in @anglinai/ui and provides a WCAG AAA-compliant palette, semantic CSS custom properties, Tailwind utilities, and a dark-mode ThemeProvider. All AnglinAI projects should use it.
Approved Palette
Every production token meets WCAG AAA (7:1 minimum) contrast ratio on the stated background.
| Token | Hex | On | Ratio | Level |
|---|---|---|---|---|
| Primary (deep blue) | #054fb9 | white | 7.3:1 | β AAA |
| Primary hover | #0057b0 | white | 7.1:1 | β AAA |
| Accent / sky blue | #8babf1 | black | 9.2:1 | β AAA |
| Secondary (dark orange) | #8b3200 | white | 7.2:1 | β AAA |
| Vivid orange | #f57600 | black | 7.4:1 | β AAA |
Aspirational tokens (AA only on white β stored as references, not for direct use in UI):
| Token | Hex | Ratio | Note |
|---|---|---|---|
#0073e6 | mid blue | 4.6:1 AA | Design reference only |
#c44601 | orange | 4.8:1 AA | Design reference only |
Never use teal or green in any AnglinAI UI β see global
CLAUDE.md.
CSS Custom Properties
After importing @anglinai/ui/theme.css, these variables are available everywhere.
Semantic tokens (use these in components)
/* Light mode values shown. Dark mode inverts automatically via .dark class. */
/* Primary */--anglin-color-primary /* #054fb9 light / #8babf1 dark */--anglin-color-primary-hover /* #0057b0 light / #a5bff5 dark */--anglin-color-primary-active /* #03368a light / #c0d3f9 dark */--anglin-color-primary-subtle /* #dde8fb light / #1a2d5a dark */--anglin-color-on-primary /* #ffffff light / #000000 dark */
/* Secondary */--anglin-color-secondary /* #8b3200 light / #f57600 dark */--anglin-color-secondary-hover /* #7a2b00 light / #f78c1f dark */--anglin-color-secondary-subtle /* #fdebd6 light / #3d1e00 dark */--anglin-color-on-secondary /* #ffffff light / #000000 dark */
/* Accent */--anglin-color-accent /* #8babf1 light / #0057b0 dark */--anglin-color-on-accent /* #000000 light / #ffffff dark */
/* Vivid */--anglin-color-vivid /* #f57600 both modes */--anglin-color-on-vivid /* #000000 both modes */
/* Surfaces */--anglin-color-surface /* #ffffff light / #0f172a dark */--anglin-color-surface-subtle /* #f8fafc light / #1e293b dark */--anglin-color-surface-muted /* #eff6ff light / #162044 dark */--anglin-color-on-surface /* #0f172a light / #f1f5f9 dark */--anglin-color-on-surface-muted /* #475569 light / #94a3b8 dark */
/* Borders & focus */--anglin-color-border /* #e2e8f0 light / #334155 dark */--anglin-color-focus-ring /* #054fb9 light / #8babf1 dark */Palette reference tokens (raw values β not for components)
--anglin-palette-blue-deep /* #054fb9 */--anglin-palette-blue-hover-aaa /* #0057b0 */--anglin-palette-blue-sky /* #8babf1 */--anglin-palette-orange-dark-aaa /* #8b3200 */--anglin-palette-orange-vivid /* #f57600 *//* Aspirational (AA only) */--anglin-palette-blue-mid /* #0073e6 */--anglin-palette-orange-dark /* #c44601 */Usage in plain CSS
.my-button { background-color: var(--anglin-color-primary); color: var(--anglin-color-on-primary);}
.my-button:hover { background-color: var(--anglin-color-primary-hover);}Tailwind Utilities
After adding @anglinai/ui as a Tailwind preset, these classes are available.
Setting up the preset
module.exports = { darkMode: 'class', presets: [require('@anglinai/ui/tailwind-preset')], content: [ './src/**/*.{ts,tsx}', './node_modules/@anglinai/ui/dist/**/*.{js,mjs}', ],};Available classes
All anglin-* utilities support Tailwind opacity modifiers (e.g. bg-anglin-primary/80).
bg-anglin-primary text-anglin-primary border-anglin-primarybg-anglin-primary-hover hover:bg-anglin-primary-hoverbg-anglin-primary-subtle text-anglin-primary-subtlebg-anglin-on-primary text-anglin-on-primary
bg-anglin-secondary text-anglin-secondarybg-anglin-secondary-hover hover:bg-anglin-secondary-hoverbg-anglin-secondary-subtlebg-anglin-on-secondary text-anglin-on-secondary
bg-anglin-accent text-anglin-accentbg-anglin-on-accent text-anglin-on-accent
bg-anglin-vivid text-anglin-vividbg-anglin-on-vivid text-anglin-on-vivid
bg-anglin-surface bg-anglin-surface-subtle bg-anglin-surface-mutedtext-anglin-on-surface text-anglin-on-surface-muted
border-anglin-borderStatic hex classes (for SVG/canvas where CSS vars donβt work)
bg-anglin-static-blue-deep text-anglin-static-blue-deepbg-anglin-static-blue-hoverbg-anglin-static-blue-sky text-anglin-static-blue-skybg-anglin-static-orange-darkbg-anglin-static-orange-vivid text-anglin-static-orange-vividExample component
<button className="bg-anglin-primary text-anglin-on-primary hover:bg-anglin-primary-hover px-4 py-2 rounded-lg"> Save changes</button>
<div className="bg-anglin-surface-subtle border border-anglin-border rounded-xl p-6"> <p className="text-anglin-on-surface">Content here</p> <p className="text-anglin-on-surface-muted">Supporting text</p></div>Dark Mode Setup
1. Import theme.css
In your root globals.css, import before @tailwind directives:
@import '@anglinai/ui/theme.css';
@tailwind base;@tailwind components;@tailwind utilities;2. Add ThemeScript to prevent FOUC
In your root layout.tsx (Next.js App Router), place ThemeScript inside <head> before the first paint:
import { ThemeScript, ThemeProvider } from '@anglinai/ui';
export default function RootLayout({ children }) { return ( <html lang="en" suppressHydrationWarning> <head> <ThemeScript /> </head> <body> <ThemeProvider defaultTheme="system"> {children} </ThemeProvider> </body> </html> );}
suppressHydrationWarningon<html>is required becauseThemeScriptmodifies the class list before React hydrates.
3. Use the useTheme hook
'use client';import { useTheme } from '@anglinai/ui';
export function ThemeToggle() { const { theme, resolvedTheme, setTheme } = useTheme();
return ( <button onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}> {resolvedTheme === 'dark' ? 'βοΈ Light' : 'π Dark'} </button> );}useTheme returns
| Field | Type | Description |
|---|---|---|
theme | 'light' | 'dark' | 'system' | The stored user preference |
resolvedTheme | 'light' | 'dark' | What is actually rendered right now |
setTheme | (t: Theme) => void | Persists to localStorage and applies immediately |
The default localStorage key is anglin-theme. Override it via <ThemeScript storageKey="my-key" /> and <ThemeProvider storageKey="my-key">.
How dark mode works
ThemeScriptruns as a blocking inline script before paint β readslocalStorage, falls back toprefers-color-scheme, setsclass="dark"anddata-theme="dark"on<html>.- Tailwindβs
darkMode: 'class'activates the.darkvariant for alldark:*utilities. - All
--anglin-*CSS variables defined intheme.cssswap to their dark-mode values inside.dark {}. ThemeProvidermanages React state and re-syncs on system preference changes whentheme === 'system'.
TypeScript: Color Palette Constants
Import raw palette values for non-CSS contexts (e.g. chart libraries, canvas, email templates):
import { COLOR_PALETTE, CONTRAST_TABLE } from '@anglinai/ui';
// Use in a chart configconst chartColors = { primary: COLOR_PALETTE.blueDeep, // '#054fb9' secondary: COLOR_PALETTE.orangeVivid, // '#f57600'};
// Print contrast auditCONTRAST_TABLE.forEach(({ token, ratio, wcag }) => console.log(`${token}: ${ratio} ${wcag}`));COLOR_PALETTE keys
| Key | Value | WCAG |
|---|---|---|
blueDeep | #054fb9 | AAA |
blueHoverAaa | #0057b0 | AAA |
blueSky | #8babf1 | AAA |
orangeDarkAaa | #8b3200 | AAA |
orangeVivid | #f57600 | AAA |
blueMid | #0073e6 | AA (reference) |
orangeDark | #c44601 | AA (reference) |
Installation in a New Project
# Add .npmrc if not presentecho "@anglinai:registry=https://npm.pkg.github.com" >> .npmrcecho "//npm.pkg.github.com/:_authToken=\${NODE_AUTH_TOKEN}" >> .npmrc
NODE_AUTH_TOKEN=<your-github-pat> npm install @anglinai/uiThen follow the Dark Mode Setup section above.
Migration: Replacing Old Colors
These search patterns find old primary blues and orange accents to migrate to v2 utilities:
# Old primary bluesgrep -rn "#2563eb\|#1d4ed8\|#1e40af\|#0284c7\|#0369a1\|#0ea5e9" src/
# Old orange/accent valuesgrep -rn "#f97316\|#ea580c\|#1E40AF\|#3B82F6" src/
# Old Tailwind primary-scale classesgrep -rn "bg-primary-\|text-primary-\|border-primary-\|ring-primary-" src/Known hardcoded values to migrate later
accessible-org-chart:
src/utils/versionCheck.ts:33β'color: #2563eb'β'color: #054fb9'src/components/templates/org-chart-radial/themes.tsβ SVG theme colors (useanglin-static-*values)src/app/preview/page.tsx:45β'#1e40af'in color picker preset
Replacement map
| Old value | New CSS var | New Tailwind class |
|---|---|---|
#2563eb | var(--anglin-color-primary) | text-anglin-primary |
#1d4ed8 | var(--anglin-color-primary-hover) | bg-anglin-primary-hover |
#1e40af | var(--anglin-color-primary) | bg-anglin-primary |
#0284c7 | var(--anglin-color-primary) | bg-anglin-primary |
#eff6ff | var(--anglin-color-surface-muted) | bg-anglin-surface-muted |
#f8fafc | var(--anglin-color-surface-subtle) | bg-anglin-surface-subtle |
#f97316 | var(--anglin-color-vivid) | bg-anglin-vivid |
Files Reference
| File | Package path | Purpose |
|---|---|---|
src/theme.css | @anglinai/ui/theme.css | CSS vars only β safe to import anywhere |
src/globals.css | @anglinai/ui/globals.css | CSS vars + @tailwind directives β use in the UI package itself |
tailwind.config.cjs | @anglinai/ui/tailwind-preset | Tailwind preset with all anglin-* utilities |
src/tokens/palette.ts | @anglinai/ui (named export) | COLOR_PALETTE, CONTRAST_TABLE, PaletteColor |
src/components/theme-provider.tsx | @anglinai/ui (named export) | ThemeProvider, useTheme, Theme type |
src/components/theme-script.tsx | @anglinai/ui (named export) | ThemeScript β FOUC prevention |
Changelog
| Version | Date | Changes |
|---|---|---|
| v0.2.0 | 2026-02-24 | v2 color system β WCAG AAA palette, CSS vars, Tailwind preset, ThemeProvider, ThemeScript |
| v0.1.1 | 2025 | Initial release with legacy anglin.deep-blue utilities |