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:
111
tokens/primitives/colours.json
Normal file
111
tokens/primitives/colours.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
tokens/primitives/effects.json
Normal file
28
tokens/primitives/effects.json
Normal 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" }
|
||||
}
|
||||
}
|
||||
28
tokens/primitives/spacing.json
Normal file
28
tokens/primitives/spacing.json
Normal 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" }
|
||||
}
|
||||
}
|
||||
78
tokens/primitives/typography.json
Normal file
78
tokens/primitives/typography.json
Normal 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 (2xs–4xl) 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" }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user