182 lines
9.2 KiB
Markdown
182 lines
9.2 KiB
Markdown
# Component Design System
|
||
|
||
**36 component archetypes with variation knobs** — derived from Hallmark's component cookbook, adapted for design asset generation.
|
||
|
||
Use these as building blocks for UI designs. Pick one archetype per section, and vary the knobs to prevent repetition.
|
||
|
||
---
|
||
|
||
## Archetype Index
|
||
|
||
### CTAs / Buttons (C1–C5)
|
||
|
||
| ID | Archetype | Use when | Don't confuse with |
|
||
|---|---|---|---|
|
||
| **C1** | Outlined chip | Default primary action, restrained tone | Solid fill (that's C3) |
|
||
| **C2** | Filled pill | Confident, modern-minimal, SaaS | Outlined (too weak for action) |
|
||
| **C3** | Text link | Editorial, minimal, trust typography | When you need a button (C1/C2) |
|
||
| **C4** | Oversized solid | Manifesto, statement, high-impact | When restraint is needed |
|
||
| **C5** | Inline form-as-CTA | Newsletter, signup — form IS the CTA | When CTA is separate from form |
|
||
|
||
### Cards (K1–K5)
|
||
|
||
| ID | Archetype | Use when | Don't confuse with |
|
||
|---|---|---|---|
|
||
| **K1** | Bordered minimal | Single feature, restrained, modern-minimal | Shadow card (too decorative) |
|
||
| **K2** | Elevated shadow | Card wants to lift, light background | Dark background (shadow invisible) |
|
||
| **K3** | Accent-top | Hierarchy signal, section emphasis | When no hierarchy exists |
|
||
| **K4** | Image-lead | Product card, portfolio, visual first | Text-heavy content (wrong layout) |
|
||
| **K5** | Stat block | Single large number, metric callout | Multi-feature (use K1) |
|
||
|
||
### Form Inputs (F1–F4)
|
||
|
||
| ID | Archetype | Use when | Don't confuse with |
|
||
|---|---|---|---|
|
||
| **F1** | Minimal line | Clean, modern-minimal, single field | Multi-field forms (too fragile) |
|
||
| **F2** | Bordered box | Clear field definition, any background | When minimal is preferred |
|
||
| **F3** | Filled subtle | Subtle background, grouped fields | Single field (overkill) |
|
||
| **F4** | Floating label | Animated, modern, interactive focus | Simple labels (skip animation) |
|
||
|
||
### Navigation (N1–N5)
|
||
|
||
| ID | Archetype | Use when | Don't confuse with |
|
||
|---|---|---|---|
|
||
| **N1** | Wordmark + links | Simple nav, 2–3 destinations | Complex nav (too limited) |
|
||
| **N2** | Floating pill | Modern-minimal, detached, blur backdrop | Editorial (wrong voice) |
|
||
| **N3** | Bottom bar | Mobile-first, thumb zone | Desktop (wrong placement) |
|
||
| **N4** | Side rail | Editorial, vertical, portfolio | Wide layouts (wrong rhythm) |
|
||
| **N5** | Edge-aligned minimal | Apple style, luxury, vast whitespace | When space is tight |
|
||
|
||
### Hero Patterns (H1–H6)
|
||
|
||
| ID | Archetype | Use when | Don't confuse with |
|
||
|---|---|---|---|
|
||
| **H1** | Centered display | Formal, welcoming, simple brief | Complex content (overflows) |
|
||
| **H2** | Split diptych | Headline left, visual right | Visual IS the story (use H6) |
|
||
| **H3** | Stat-led | Data hero, metric is message | When no strong metric exists |
|
||
| **H4** | Quote-led | Social proof hero, borrowed credibility | When no strong quote exists |
|
||
| **H5** | Letter | Personal, first-person, intimate | Formal/B2B (wrong tone) |
|
||
| **H6** | Full-bleed image | Visual story, photography-first | When text is primary (wrong) |
|
||
|
||
### Testimonials / Proof (T1–T4)
|
||
|
||
| ID | Archetype | Use when | Don't confuse with |
|
||
|---|---|---|---|
|
||
| **T1** | Pull quote | Single strong quote, editorial | Multiple quotes (split) |
|
||
| **T2** | Logo wall | Social proof, multiple clients | Single client (use T1) |
|
||
| **T3** | Stat strip | 3–5 metrics in a row | When stats don't matter |
|
||
| **T4** | Card carousel | Multiple testimonials, varied | Single testimonial (use T1) |
|
||
|
||
---
|
||
|
||
## 8-State Component Checklist
|
||
|
||
Every interactive component MUST have code for all 8 states:
|
||
|
||
| State | Trigger | Design requirements |
|
||
|---|---|---|
|
||
| **default** | Base state | Visual clarity, readable at arm's length |
|
||
| **hover** | `:hover` | Subtle lift (translateY(-2px)), shadow increase, or color shift. Max 1 effect per element. |
|
||
| **focus** | `:focus-visible` | `outline: 2px solid var(--color-focus)`, offset 1px. Appears *instantly* — no fade-in. |
|
||
| **active** | `:active` | Press feedback — scale(0.98) or translateY(1px). Not bouncy. |
|
||
| **disabled** | `disabled` attr | 3 signals: `opacity: 0.55` + `cursor: not-allowed` + `aria-disabled="true"`. |
|
||
| **loading** | `data-state="loading"` | Spinner or skeleton, reduced opacity (0.7), `cursor: wait`. |
|
||
| **error** | `data-state="error"` | Red border/underline, error icon, helper text appears. No layout shift. |
|
||
| **success** | `data-state="success"` | Green checkmark, confirmation message. Silent (no toast unless effect is invisible). |
|
||
|
||
### 8-State Demo Wrapper Template
|
||
|
||
For each component, emit a demo wrapper showing all 8 states:
|
||
|
||
```html
|
||
<div class="component-demo">
|
||
<div class="state-label">default</div>
|
||
<button class="btn">Click me</button>
|
||
|
||
<div class="state-label">hover</div>
|
||
<button class="btn is-hover">Click me</button>
|
||
|
||
<div class="state-label">focus</div>
|
||
<button class="btn is-focus">Click me</button>
|
||
|
||
<div class="state-label">active</div>
|
||
<button class="btn is-active">Click me</button>
|
||
|
||
<div class="state-label">disabled</div>
|
||
<button class="btn" disabled>Click me</button>
|
||
|
||
<div class="state-label">loading</div>
|
||
<button class="btn" data-state="loading">⏳ Working…</button>
|
||
|
||
<div class="state-label">error</div>
|
||
<button class="btn" data-state="error">⚠ Try again</button>
|
||
|
||
<div class="state-label">success</div>
|
||
<button class="btn" data-state="success">✓ Saved</button>
|
||
</div>
|
||
|
||
<style>
|
||
.btn:hover, .btn.is-hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
|
||
.btn:focus-visible, .btn.is-focus { outline: 2px solid var(--color-focus); outline-offset: 1px; }
|
||
.btn:active, .btn.is-active { transform: scale(0.98); }
|
||
.btn[disabled], .btn[data-state="loading"], .btn[data-state="error"], .btn[data-state="success"] {
|
||
opacity: 0.55; cursor: not-allowed;
|
||
}
|
||
.btn[data-state="loading"] { cursor: wait; }
|
||
</style>
|
||
```
|
||
|
||
---
|
||
|
||
## Variation Knobs
|
||
|
||
Picking an archetype is the first axis. Varying the knobs is the second. Two outputs using the same archetype must differ on at least one knob.
|
||
|
||
| Archetype | Knob A | Knob B | Knob C |
|
||
|---|---|---|---|
|
||
| **C1 Outlined chip** | Shape: rectangular / pill | Density: spacious / compact | Arrow: yes / no |
|
||
| **C2 Filled pill** | Size: sm / md / lg | Color: accent / ink / muted | Icon: yes / no |
|
||
| **C3 Text link** | Underline: solid / dashed / none | Hover: thicken / shift / slide | Arrow: yes / no |
|
||
| **K1 Bordered** | Border: hairline / medium | Radius: 0 / 4px / 8px | Shadow: none / subtle |
|
||
| **K2 Elevated** | Shadow: sm / md / lg | Radius: 4px / 8px / 12px | Border: yes / no |
|
||
| **K3 Accent-top** | Accent: top / left / corner | Width: full / partial | Color: accent / secondary |
|
||
| **K4 Image-lead** | Ratio: 16:9 / 4:3 / 1:1 | Caption: overlay / below | Overlay: yes / no |
|
||
| **K5 Stat block** | Number: display / body-large | Weight: 700 / 800 | Label: below / inline |
|
||
| **F1 Minimal line** | Label: above / floating / none | Width: full / partial | Border: bottom / full |
|
||
| **F2 Bordered box** | Radius: 4px / 8px | Border: 1px / 2px | Focus: outline / border |
|
||
| **H1 Centered** | Width: narrow / medium / wide | Eyebrow: yes / no | CTA: centered / left |
|
||
| **H2 Split** | Ratio: 50/50 / 60/40 / 40/60 | Visual: image / color / gradient | Divider: rule / space |
|
||
| **H3 Stat-led** | Number: display / body-large | Qualifier: below / inline | Background: solid / gradient |
|
||
| **H4 Quote-led** | Quote: italic / roman | Attribution: below / side | Width: 60ch / full |
|
||
| **H5 Letter** | Greeting: yes / no | Length: short / medium | Signoff: name / initials |
|
||
| **H6 Full-bleed** | Image: photo / gradient | Caption: corner / inline | Overlay: dark / light / none |
|
||
| **T1 Pull quote** | Width: 60ch / 40ch | Attribution: signed / stamped | Style: italic / roman |
|
||
| **T2 Logo wall** | Layout: row / grid | Color: mono / brand | Size: sm / md / lg |
|
||
| **T3 Stat strip** | Count: 3 / 4 / 5 | Layout: row / 2-up | Style: display / body |
|
||
| **T4 Card carousel** | Card: bordered / elevated | Navigation: dots / arrows / none | Auto-play: yes / no |
|
||
| **N1 Wordmark + links** | Position: split / centered | Links: text / icon | Sticky: yes / no |
|
||
| **N2 Floating pill** | Backdrop: blur / solid | Width: auto / max | Anchor: center / left / right |
|
||
| **N3 Bottom bar** | Actions: 1 / 2 / 3 | Style: outline / filled | Icon: yes / no |
|
||
| **N4 Side rail** | Width: narrow / medium | Content: icons / text | Alignment: top / center |
|
||
| **N5 Edge-aligned** | CTA: pill / text / arrow | Space: generous / tight | Sticky: yes / no |
|
||
|
||
---
|
||
|
||
## Component Stamp Format
|
||
|
||
```
|
||
/* Design · component: button · genre: modern-minimal · theme: quiet */
|
||
/* Design · states: default · hover · focus · active · disabled · loading · error · success */
|
||
/* Design · knobs: shape=rectangular, density=spacious, arrow=yes */
|
||
```
|
||
|
||
---
|
||
|
||
## Anti-Patterns
|
||
|
||
- **Card nesting** — Never put a card inside a card.
|
||
- **3-column equal grid** — Use asymmetric spans instead (1:2:1, 2:1, mosaic).
|
||
- **Uniform hover scale** — Vary or skip. `scale(1.05)` on everything reads as template.
|
||
- **Icon above heading** — Always icon above heading reads as template. Vary the pattern.
|
||
- **Same-state-for-everything** — All cards with identical hover = no design thought.
|
||
- **Ghost button everywhere** — Outlined buttons for primary actions read as weak. Use filled for primary. |