Component Library
Every button, card, badge, input, modal, and pattern that exists in the FranchiseHQ design system. Source of truth for the web platform, the bot dashboards, and the future React Native app.
Color
Brand uses cyan for action and gold for emotional weight. Status colors are semantic — use them for what they mean, not as decoration. Contrast labels show WCAG compliance against --bg-canvas.
Typography
Two families. Barlow Condensed for display, headings, labels, and buttons. Barlow for body. Headings stay white — the primary brand emphasis comes from Barlow Condensed at heavy weights, not from coloring text cyan.
Barlow Condensed 900 · 56px
line-height 0.95 · uppercase
Barlow Condensed 800 · 38px
Barlow Condensed 800 · 28px
Barlow Condensed 700 · 22px
Barlow Condensed 700 · 11px
tracking 2px · cyan
Barlow Condensed 700 · 11px
tracking 2px · gold
Barlow 400 · 15px
line-height 1.65
Barlow 400 · 13px
color: text-muted
JetBrains Mono · 13px
cyan — used for slash commands
Spacing
8px base grid. Use these values for padding, margins, and gaps in new components. Existing components keep current values; migrate during regular maintenance, not as a sweeping refactor.
Border Radius
Corner radius scale. Use the smallest radius that reads correctly — buttons (md), cards (lg), modals (xl).
xs
sm
md
lg
xl
Buttons
Primary CTAs use the cyan gradient. Secondary uses outline. Ghost is for tertiary actions. All buttons meet 44×44 minimum tap target. Keyboard focus shows a visible cyan outline.
Cards
Standard cards have a card background, 1px border, 24px padding. Hoverable cards lift on hover. Featured cards have a cyan border and corner badge.
Default card pattern — used everywhere. Padding follows the 8px grid (24px = --space-6).
Hover me — lifts and shows cyan border with shadow glow.
Has a cyan border and "FEATURED" badge above. Used sparingly.
Forms & Inputs
All inputs share the same baseline: bg-surface, border, 13px text, 7px radius. Focus state shows a cyan border + glow ring. Min height 44px.
3–32 characters. Used for your public profile URL.
Please enter a valid email address.
Badges & Pills
Badges use color semantically. Cyan = brand/info, Gold = premium/award, Success = active, Warning = attention, Error = problem, Muted = neutral.
Stats
Big number + small uppercase label. Use semantic colors: cyan for default data, gold for ratings, success for positive financial.
Tables
Cyan uppercase column headers on bg-card-hi. Body rows with hover state. Use for standings, leaderboards, audit logs.
| Rank | Team | Record | PF | PA |
|---|---|---|---|---|
| 1 | Bills | 11-3 | 389 | 241 |
| 2 | Patriots | 9-5 | 312 | 278 |
| 3 | Dolphins | 8-6 | 301 | 289 |
| 4 | Jets | 4-10 | 234 | 351 |
Modals
14px radius, modal shadow, max-width 460px. On mobile, bottom-sheet pattern with swipe-down dismiss is preferred.
This will permanently delete the LEFTY42 league profile, including all rules, open team listings, and history. This cannot be undone.
Toasts
Brief feedback messages. Auto-dismiss after 2.5s. Position: bottom-center, 80px above bottom edge to avoid mobile CTA bar collision.
Loading States (Skeletons)
Match the eventual layout shape. Better than spinners on data-heavy screens — perceived performance is faster, no layout shift when content arrives.
Empty States
When there's no data, give the user something to do. Every empty state has an icon, a headline, a one-sentence explanation, and exactly one CTA.
No Matching Leagues
Try removing a filter or broadening your search.
No Leagues Listed Yet
Be the first commish to list your league. Takes 30 seconds and you get a permanent profile.
Embed Previews
How Discord embeds look against Discord's actual chat background (#2b2d31). Color = semantic meaning. Cyan for default, gold for awards, green for success/accepted, red for declined/error.
Accessibility Rules
These are not guidelines, they're requirements. Any new component that violates these rules doesn't ship.
- ✅ Min tap target 44×44px — WCAG 2.5.5. Buttons, nav items, checkboxes. Use
min-height: var(--tap-min). - ✅ Min text contrast 4.5:1 — WCAG AA. Text-muted (#8BA5C8) and text-dimmed (#6F8AAC) both pass.
--n-500does NOT — borders only. - ✅ Focus-visible outline — 2px solid cyan, offset 2px. Already in
nav-styles.css. - ✅ Color is never the only signal — trade-accepted has ✅ icon AND green color. Trade-declined has ❌ icon AND red color. Color-blind users need redundancy.
- ✅ Reduced motion variant — components define
@media (prefers-reduced-motion: reduce)behavior. Already wired intokens.css. - ✅ Body copy minimum 13px — Barlow at 13px reads on phones. Captions in text-dimmed only at ≥13px.
- ✅ Form labels are persistent, not placeholder-only — placeholder text disappears on focus, leaving users guessing what field they're in.
- ✅ Loading states announce themselves — use
aria-live="polite"on result counts and skeleton containers. - ✅ Modal close on Escape key — every modal binds Escape to its close handler.