Initial commit: FA 2.0 Design System foundation

Token pipeline (Style Dictionary v4, DTCG format):
- Primitive tokens: colour palettes (brand, sage, neutral, feedback),
  typography (3 font families, 21-variant type scale), spacing (4px grid),
  border radius, shadows, opacity
- Semantic tokens: text, surface, border, interactive, feedback colours;
  typography roles; layout spacing
- Component tokens: Button (4 sizes), Input (2 sizes)
- Generated outputs: CSS custom properties, JS ES6 module, flat JSON

Atoms (3 components):
- Button: contained/soft/outlined/text × primary/secondary, 4 sizes,
  loading state, underline for text variant
- Typography: 21 variants across display/heading/body/label/caption/overline,
  maxLines truncation
- Input: external label, helper text, error/success validation,
  start/end icons, required indicator, 2 sizes, multiline support

Infrastructure:
- MUI v5 theme with full token mapping
- Storybook 8 with autodocs
- Claude Code agents and skills for token/component workflows
- Design system documentation and cross-session memory

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 15:08:15 +11:00
commit 732c872576
56 changed files with 12690 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
{
"color": {
"$type": "color",
"brand": {
"$description": "Warm gold/copper palette — FA primary brand hue. Derived from Parsons brand swatches.",
"50": { "$value": "#FEF9F5", "$description": "Lightest warm tint — warm section backgrounds" },
"100": { "$value": "#F7ECDF", "$description": "Light warm — hover backgrounds, subtle fills" },
"200": { "$value": "#EBDAC8", "$description": "Warm light — secondary backgrounds, divider tones" },
"300": { "$value": "#D8C3B5", "$description": "Warm beige — from brand swatch. Surface warmth, card tints" },
"400": { "$value": "#D0A070", "$description": "Mid gold — from brand swatch. Secondary interactive, step indicators" },
"500": { "$value": "#BA834E", "$description": "Base brand gold — from brand swatch. Primary CTA colour, main interactive. 3.7:1 contrast on white" },
"600": { "$value": "#B0610F", "$description": "Rich copper — from brand swatch. Hover/emphasis on brand elements. 4.8:1 contrast on white" },
"700": { "$value": "#8B4E0D", "$description": "Deep copper — active states, strong brand text on light backgrounds. 6.7:1 contrast on white" },
"800": { "$value": "#6B3C13", "$description": "Dark brown — bold brand accents, high-contrast brand text" },
"900": { "$value": "#51301B", "$description": "Chocolate — from brand swatch. Deep emphasis, dark brand surfaces" },
"950": { "$value": "#251913", "$description": "Espresso — from brand swatch. Darkest brand tone, near-black warm" }
},
"sage": {
"$description": "Cool grey-green/slate palette — FA secondary hue. Calming, professional tone for the funeral services context.",
"50": { "$value": "#F2F5F6", "$description": "Lightest sage — subtle cool backgrounds" },
"100": { "$value": "#E3EAEB", "$description": "Light sage — hover states on cool surfaces" },
"200": { "$value": "#D7E1E2", "$description": "From brand swatch — light cool surface, soft borders" },
"300": { "$value": "#C8D4D6", "$description": "Mid-light sage — dividers, secondary borders" },
"400": { "$value": "#B9C7C9", "$description": "From brand swatch — mid sage, secondary text on dark backgrounds" },
"500": { "$value": "#8EA2A7", "$description": "Base sage — secondary content, muted icons" },
"600": { "$value": "#687D84", "$description": "Dark sage — secondary text, subtle icons" },
"700": { "$value": "#4C5B6B", "$description": "From brand swatch — strong secondary, dark accents. 6.1:1 contrast on white" },
"800": { "$value": "#4C5459", "$description": "From brand swatch — near-dark grey, supplementary text. 6.7:1 contrast on white" },
"900": { "$value": "#343C40", "$description": "Very dark sage — high-contrast secondary elements" },
"950": { "$value": "#1E2528", "$description": "Near-black cool — darkest secondary tone" }
},
"neutral": {
"$description": "True grey palette for text, borders, and UI chrome. Slight cool undertone to complement the sage palette.",
"50": { "$value": "#FAFAFA", "$description": "Lightest neutral — default page background alternative" },
"100": { "$value": "#F5F5F5", "$description": "Light neutral — subtle background differentiation" },
"200": { "$value": "#E8E8E8", "$description": "Light grey — standard borders, dividers" },
"300": { "$value": "#D4D4D4", "$description": "Mid-light grey — disabled borders, subtle separators" },
"400": { "$value": "#A3A3A3", "$description": "Mid grey — placeholder text, disabled content" },
"500": { "$value": "#737373", "$description": "Base grey — secondary body text, icons" },
"600": { "$value": "#525252", "$description": "Dark grey — body text, labels. 7.1:1 contrast on white" },
"700": { "$value": "#404040", "$description": "Strong grey — headings, emphasis text. 9.7:1 contrast on white" },
"800": { "$value": "#2C2E35", "$description": "From brand swatch — charcoal with cool tint. Primary text colour. 13.2:1 contrast on white" },
"900": { "$value": "#1A1A1C", "$description": "Near-black — maximum contrast text" },
"950": { "$value": "#0A0A0B", "$description": "Deepest neutral — use sparingly" }
},
"red": {
"$description": "Red palette for error states, destructive actions, and urgent feedback. Warm-leaning for brand cohesion.",
"50": { "$value": "#FEF2F2", "$description": "Error tint — error message backgrounds" },
"100": { "$value": "#FDE8E8", "$description": "Light error — hover on error surfaces" },
"200": { "$value": "#F9BFBF", "$description": "Light red — error borders, subtle indicators" },
"300": { "$value": "#F09898", "$description": "Mid-light red — error icon backgrounds" },
"400": { "$value": "#E56B6B", "$description": "Mid red — error indicators, badges" },
"500": { "$value": "#D64545", "$description": "Base red — form validation errors, alert accents" },
"600": { "$value": "#BC2F2F", "$description": "Strong red — error text on light backgrounds. 5.7:1 contrast on white" },
"700": { "$value": "#9B2424", "$description": "Dark red — error headings, strong alerts" },
"800": { "$value": "#7A1D1D", "$description": "Deep red — high-contrast error emphasis" },
"900": { "$value": "#5C1616", "$description": "Very dark red — use sparingly" },
"950": { "$value": "#3D0E0E", "$description": "Darkest red" }
},
"amber": {
"$description": "Amber/yellow palette for warning states, price alerts, and important notices.",
"50": { "$value": "#FFF9EB", "$description": "Warning tint — warning message backgrounds" },
"100": { "$value": "#FFF0CC", "$description": "Light amber — hover on warning surfaces" },
"200": { "$value": "#FFE099", "$description": "Light amber — warning borders" },
"300": { "$value": "#FFCC66", "$description": "Mid-light amber — warning icon backgrounds" },
"400": { "$value": "#FFB833", "$description": "Mid amber — warning badges, price alerts" },
"500": { "$value": "#F5A000", "$description": "Base amber — warning accents" },
"600": { "$value": "#CC8500", "$description": "Strong amber — warning text. 3.6:1 contrast on white (large text AA)" },
"700": { "$value": "#A36B00", "$description": "Dark amber — warning headings. 5.1:1 contrast on white" },
"800": { "$value": "#7A5000", "$description": "Deep amber — high-contrast warning emphasis" },
"900": { "$value": "#523600", "$description": "Very dark amber — use sparingly" },
"950": { "$value": "#331F00", "$description": "Darkest amber" }
},
"green": {
"$description": "Green palette for success states, confirmations, and positive feedback. Slightly muted for the sensitive context.",
"50": { "$value": "#F0F7F0", "$description": "Success tint — success message backgrounds" },
"100": { "$value": "#D8ECD8", "$description": "Light green — hover on success surfaces" },
"200": { "$value": "#B8D8B8", "$description": "Light green — success borders" },
"300": { "$value": "#8DC08D", "$description": "Mid-light green — success icon backgrounds" },
"400": { "$value": "#66A866", "$description": "Mid green — success badges, completion indicators" },
"500": { "$value": "#4A8F4A", "$description": "Base green — success accents, completed steps" },
"600": { "$value": "#3B7A3B", "$description": "Strong green — success text on light backgrounds. 4.8:1 contrast on white" },
"700": { "$value": "#2E6B2E", "$description": "Dark green — success headings" },
"800": { "$value": "#235523", "$description": "Deep green — high-contrast success emphasis" },
"900": { "$value": "#1A3F1A", "$description": "Very dark green — use sparingly" },
"950": { "$value": "#0F2A0F", "$description": "Darkest green" }
},
"blue": {
"$description": "Blue palette for informational states, supplementary info, and non-brand links.",
"50": { "$value": "#EFF6FF", "$description": "Info tint — info message backgrounds" },
"100": { "$value": "#DBEAFE", "$description": "Light blue — hover on info surfaces" },
"200": { "$value": "#BFDBFE", "$description": "Light blue — info borders" },
"300": { "$value": "#93C5FD", "$description": "Mid-light blue — info icon backgrounds" },
"400": { "$value": "#60A5FA", "$description": "Mid blue — info badges" },
"500": { "$value": "#3B82F6", "$description": "Base blue — info accents, supplementary links" },
"600": { "$value": "#2563EB", "$description": "Strong blue — info text on light backgrounds. 4.6:1 contrast on white" },
"700": { "$value": "#1D4ED8", "$description": "Dark blue — info headings" },
"800": { "$value": "#1E40AF", "$description": "Deep blue — high-contrast info emphasis" },
"900": { "$value": "#1E3A8A", "$description": "Very dark blue — use sparingly" },
"950": { "$value": "#172554", "$description": "Darkest blue" }
},
"white": {
"$value": "#FFFFFF",
"$description": "Pure white — card backgrounds, inverse text, primary surface"
},
"black": {
"$value": "#000000",
"$description": "Pure black — from brand swatch. Use sparingly; prefer neutral.800-900 for text"
}
}
}

View File

@@ -0,0 +1,28 @@
{
"shadow": {
"$description": "Elevation shadows for layered UI. Values are CSS box-shadow shorthand strings.",
"sm": {
"$value": "0 1px 2px rgba(0,0,0,0.05)",
"$description": "Subtle lift — resting buttons, input focus subtle elevation"
},
"md": {
"$value": "0 4px 6px rgba(0,0,0,0.07)",
"$description": "Medium elevation — cards at rest, dropdowns, popovers"
},
"lg": {
"$value": "0 10px 15px rgba(0,0,0,0.1)",
"$description": "High elevation — modals, popovers, card hover states"
},
"xl": {
"$value": "0 20px 25px rgba(0,0,0,0.1)",
"$description": "Maximum elevation — elevated panels, dialog boxes"
}
},
"opacity": {
"$type": "number",
"$description": "Opacity values for interactive states and overlays.",
"disabled": { "$value": 0.4, "$description": "Disabled state — 40% opacity. Clearly diminished but still distinguishable" },
"hover": { "$value": 0.08, "$description": "Hover overlay — subtle 8% tint applied over backgrounds on hover" },
"overlay": { "$value": 0.5, "$description": "Modal/dialog backdrop — 50% black overlay behind modals" }
}
}

View File

@@ -0,0 +1,28 @@
{
"spacing": {
"$type": "dimension",
"$description": "Spacing scale based on 4px base unit. All values are multiples of 4.",
"0-5": { "$value": "2px", "$description": "Hairline — icon-to-text tight spacing, fine adjustments" },
"1": { "$value": "4px", "$description": "Tight — inline spacing, minimal gaps between related elements" },
"2": { "$value": "8px", "$description": "Small — related element gaps, compact padding, icon margins" },
"3": { "$value": "12px", "$description": "Component internal padding (small), chip padding" },
"4": { "$value": "16px", "$description": "Default component padding, form field gap, card grid gutter (mobile)" },
"5": { "$value": "20px", "$description": "Medium component spacing" },
"6": { "$value": "24px", "$description": "Card padding, section gap (small), card grid gutter (desktop)" },
"8": { "$value": "32px", "$description": "Section gap (medium), form section separation" },
"10": { "$value": "40px", "$description": "Section gap (large)" },
"12": { "$value": "48px", "$description": "Page section separation, vertical rhythm break" },
"16": { "$value": "64px", "$description": "Hero/banner vertical spacing" },
"20": { "$value": "80px", "$description": "Major page sections, large vertical spacing" }
},
"borderRadius": {
"$type": "dimension",
"$description": "Border radius scale for consistent rounding across components.",
"none": { "$value": "0px", "$description": "Square corners — tables, dividers, sharp elements" },
"sm": { "$value": "4px", "$description": "Small radius — inputs, small interactive elements, chips" },
"md": { "$value": "8px", "$description": "Medium radius — cards, buttons, dropdowns (default)" },
"lg": { "$value": "12px", "$description": "Large radius — modals, large cards" },
"xl": { "$value": "16px", "$description": "Extra large — feature cards, hero elements" },
"full": { "$value": "9999px", "$description": "Full/pill — avatars, pill buttons, circular elements" }
}
}

View File

@@ -0,0 +1,78 @@
{
"fontFamily": {
"$type": "fontFamily",
"body": {
"$value": "'Montserrat', 'Helvetica Neue', Arial, sans-serif",
"$description": "Primary font — Montserrat. Used for headings (h1-h6), body text, labels, and all UI elements"
},
"display": {
"$value": "'Noto Serif SC', Georgia, 'Times New Roman', serif",
"$description": "Display font — Noto Serif SC. Elegant serif for hero/display text only. Adds warmth and gravitas at large sizes"
},
"mono": {
"$value": "'JetBrains Mono', 'Fira Code', Consolas, monospace",
"$description": "Monospace font — for reference numbers (FA-2026-00847), tabular pricing data, and code"
}
},
"fontSize": {
"$type": "dimension",
"$description": "Font size scale. General-purpose sizes (2xs4xl) plus display-specific sizes for hero/marketing text.",
"2xs": { "$value": "0.6875rem", "$description": "11px — smallest UI text: compact captions, compact overlines" },
"xs": { "$value": "0.75rem", "$description": "12px — small text: captions, labels, overlines, body/xs" },
"sm": { "$value": "0.875rem", "$description": "14px — body small, labels, helper text" },
"base": { "$value": "1rem", "$description": "16px — default body text, heading/6, label/lg" },
"md": { "$value": "1.125rem", "$description": "18px — body large, heading/5" },
"lg": { "$value": "1.25rem", "$description": "20px — heading/4" },
"xl": { "$value": "1.5rem", "$description": "24px — heading/3" },
"2xl": { "$value": "1.875rem", "$description": "30px — heading/2" },
"3xl": { "$value": "2.25rem", "$description": "36px — heading/1" },
"4xl": { "$value": "3rem", "$description": "48px — reserved (legacy)" },
"display": {
"$description": "Display-specific sizes for hero and marketing text. Used exclusively with Noto Serif SC.",
"sm": { "$value": "2rem", "$description": "32px — display/sm, smallest display text" },
"3": { "$value": "2.5rem", "$description": "40px — display/3" },
"2": { "$value": "3.25rem", "$description": "52px — display/2" },
"1": { "$value": "4rem", "$description": "64px — display/1" },
"hero": { "$value": "5rem", "$description": "80px — display/hero, largest display text" }
},
"mobile": {
"$description": "Reduced font sizes for mobile breakpoints (< 600px). Display and headings scale down; body sizes stay constant.",
"displayHero": { "$value": "2rem", "$description": "32px — mobile display/hero (from 80px desktop)" },
"display1": { "$value": "1.75rem", "$description": "28px — mobile display/1 (from 64px desktop)" },
"display2": { "$value": "1.5rem", "$description": "24px — mobile display/2 (from 52px desktop)" },
"display3": { "$value": "1.375rem", "$description": "22px — mobile display/3 (from 40px desktop)" },
"displaySm": { "$value": "1.25rem", "$description": "20px — mobile display/sm (from 32px desktop)" },
"h1": { "$value": "1.625rem", "$description": "26px — mobile heading/1 (from 36px desktop)" },
"h2": { "$value": "1.375rem", "$description": "22px — mobile heading/2 (from 30px desktop)" },
"h3": { "$value": "1.25rem", "$description": "20px — mobile heading/3 (from 24px desktop)" },
"h4": { "$value": "1.125rem", "$description": "18px — mobile heading/4 (from 20px desktop)" },
"h5": { "$value": "1rem", "$description": "16px — mobile heading/5 (from 18px desktop)" },
"h6": { "$value": "0.875rem", "$description": "14px — mobile heading/6 (from 16px desktop)" }
}
},
"fontWeight": {
"$type": "fontWeight",
"regular": { "$value": 400, "$description": "Regular weight — captions, display text (serif carries inherent weight)" },
"medium": { "$value": 500, "$description": "Medium weight — body text, labels. Slightly bolder than regular for improved readability" },
"semibold": { "$value": 600, "$description": "Semibold — overlines, button text, navigation" },
"bold": { "$value": 700, "$description": "Bold — all headings (h1-h6)" }
},
"lineHeight": {
"$type": "number",
"$description": "Generic line-height scale. Typography variants use specific values for precise control.",
"tight": { "$value": 1.25, "$description": "Tight leading — large headings, display text" },
"snug": { "$value": 1.375, "$description": "Snug leading — sub-headings, labels, small text" },
"normal": { "$value": 1.5, "$description": "Normal leading — default body text, optimal readability" },
"relaxed": { "$value": 1.75, "$description": "Relaxed leading — large body text, long-form content" }
},
"letterSpacing": {
"$type": "dimension",
"$description": "Generic letter-spacing scale. Typography variants use specific values for precise control.",
"tighter": { "$value": "-0.02em", "$description": "Tighter tracking — large display text" },
"tight": { "$value": "-0.01em", "$description": "Tight tracking — headings" },
"normal": { "$value": "0em", "$description": "Normal tracking — body text, most content" },
"wide": { "$value": "0.02em", "$description": "Wide tracking — captions, small text" },
"wider": { "$value": "0.05em", "$description": "Wider tracking — labels, UI text" },
"widest": { "$value": "0.08em", "$description": "Widest tracking — overlines, uppercase text" }
}
}