Files
boc/docs/design/components/RFC-004-Card.md
T
Bernt 78436cecc2 docs: Foundation Freeze v1.0 + directory reorganization
- FOUNDATIONS-v1.0.md:
  - Freeze contract for Landvex Design System
  - Scope: Motion, AI Principles, Semantic Colors, Grid, Elevation, Typography, RFC Template, Definition of Done
  - Reference components: Button, Input, Select, Card (all ~83%)
  - Invariants: token rules, component rules, accessibility rules, AI rules
  - Change policy: no new foundation concepts without v2.0 RFC
  - Versioning: 1.0.x patches, 1.x.0 new components, 2.0.0 new foundations
  - Compatibility matrix for all foundations and components

- Directory reorganization:
  - docs/design/foundations/ → frozen foundation documents
  - docs/design/components/ → component RFCs
  - docs/design/README.md → navigation and structure

- Foundation documents moved:
  - TOKEN_PHILOSOPHY, SEMANTIC_COLOR_SYSTEM, GRID_ELEVATION
  - AI_DESIGN_PRINCIPLES, COMPONENT_TEMPLATE, RFC_DEFINITION_OF_DONE
  - DESIGN_ANTI_PATTERNS, COMPONENT_DECISION_TREE, GLOSSARY
  - BRAND_PALETTE, RELEASE_DEFINITION, SEMANTIC_COLOR_SYSTEM_REVIEW

- Component RFCs moved:
  - RFC-002-Input, RFC-003-Select, RFC-004-Card

Rationale: Clear separation between foundations (stable platform) and
components (built on top). Foundations v1.0 frozen — components can be
added freely within v1.x, but foundations require v2.0 RFC to change.
This prevents gradual erosion of the design system architecture.
2026-07-02 11:23:10 +00:00

266 lines
8.9 KiB
Markdown

# RFC-004: Canonical Card Component
**Status:** 🟡 Draft — Under review
**Tier:** 1 (Canonical)
**Inherits From:** — (root component)
**Author:** AI Agent
**Date:** 2026-07-02
---
## 1. COGNITIVE PURPOSE
Card exists to group related information into a bounded, scannable unit. It creates visual hierarchy by separating content from its surroundings without requiring explicit borders or dividers.
**Design Goal:** The user can scan, compare, and act on grouped information as a single unit.
---
## 2. WHEN TO USE
- Grouping related data (KPI, dataset, asset summary)
- Presenting actionable items that need context
- Creating scannable lists of heterogeneous content
- Elevating content above the page background
- Containing forms or workflows in a bounded area
## 3. WHEN NOT TO USE
- Single line of text (use plain text or List Item)
- Simple navigation (use Link or Navigation)
- Modal content (use Modal)
- Full-page content (use Page layout)
- When elevation is unnecessary (use flat surface)
---
## 4. USER EXPECTATION
- Card is visually distinct from background
- Card content is related and scannable
- Card may be clickable (if actionable)
- Card maintains consistent internal spacing
- Card adapts to container width
- Multiple cards align in grids or lists
---
## 5. INTERACTION CONTRACT
| Event | Response |
|-------|----------|
| Click (actionable) | Navigate or trigger primary action |
| Hover (actionable) | Elevation increases, cursor changes |
| Focus (actionable) | Focus ring appears |
| None (static) | No interaction, purely presentational |
---
## 6. FAILURE BEHAVIOUR
| Scenario | Response |
|----------|----------|
| Content overflows | Scroll internally or truncate with ellipsis |
| Image fails to load | Show placeholder or fallback icon |
| Action fails | Show error state on card or in adjacent area |
| Card is loading | Show skeleton state |
| Card is empty | Show empty state with guidance |
---
## 7. ACCESSIBILITY CONTRACT
- **Role:** Static cards use no ARIA role. Actionable cards use `role="button"` or `role="link"`.
- **Focus:** Actionable cards MUST have visible focus ring
- **Label:** Actionable cards MUST have accessible name (aria-label or visible text)
- **Screen reader:** MUST announce card as group or link/button
- **Keyboard:** Actionable cards MUST be activatable with Enter or Space
- **Color:** MUST NOT rely on color alone to indicate actionability
---
## 8. AI CONTRACT
| Scenario | AI Choice |
|----------|-----------|
| Group related data with actions | Card |
| Single data point with label | List Item |
| Navigation to another page | Link |
| Modal content | Modal |
| Full-page layout | Page |
| Simple text without grouping | Plain text |
---
## 9. TOKEN DEPENDENCIES
| Token | Semantic Alias | Primitive | Usage |
|-------|---------------|-----------|-------|
| `card-bg` | `color.surface.raised` | `gray-50` | Background |
| `card-border` | `color.border.default` | `gray-200` | Border (optional) |
| `card-radius` | `radius-lg` | `12px` | Border radius |
| `card-padding` | `space-4` | `16px` | Internal padding |
| `card-shadow` | `shadow-sm` | `0 1px 2px rgba(0,0,0,0.05)` | Default elevation |
| `card-shadow-hover` | `shadow-md` | `0 4px 6px rgba(0,0,0,0.07)` | Hover elevation (actionable) |
| `card-shadow-active` | `shadow-sm` | `0 1px 2px rgba(0,0,0,0.05)` | Active elevation |
| `card-divider` | `color.border.default` | `gray-200` | Divider between sections |
| `card-header-text` | `color.text.primary` | `gray-900` | Header text |
| `card-body-text` | `color.text.secondary` | `gray-600` | Body text |
| `card-footer-text` | `color.text.muted` | `gray-400` | Footer text |
| `card-loading-bg` | `color.surface.default` | `gray-0` | Skeleton background |
---
## 10. LAYOUT
```
┌─────────────────────────────────────┐
│ ┌─────────────────────────────────┐ │
│ │ Header (title, action) │ │
│ ├─────────────────────────────────┤ │
│ │ │ │
│ │ Body (content, data, media) │ │
│ │ │ │
│ ├─────────────────────────────────┤ │
│ │ Footer (metadata, actions) │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────┘
```
- **Header:** Top section, title + optional action, padding `space-4`
- **Body:** Main content, padding `space-4`, flexible height
- **Footer:** Bottom section, metadata or actions, padding `space-4`, top border `card-divider`
- **Divider:** 1px line between sections, `card-divider`
- **Gap:** No gap between sections (padding handles spacing)
---
## 11. SIZES
| Size | Width | Padding | Usage |
|------|-------|---------|-------|
| Small | 240px | `space-3` | Dense grids, compact data |
| Medium | 320px | `space-4` | Default, most content |
| Large | 480px | `space-5` | Featured content, dashboards |
| Fluid | 100% | `space-4` | Responsive, full-width |
---
## 12. VARIANTS
| Variant | Visual | Usage |
|---------|--------|-------|
| Default | Border, subtle shadow | Standard content grouping |
| Elevated | No border, stronger shadow | Featured content, dashboards |
| Outlined | Border, no shadow | Dense layouts, tables |
| Interactive | Hover elevation, cursor pointer | Clickable cards |
---
## 13. STATES
| State | Visual | Motion |
|-------|--------|--------|
| Default | `card-bg`, `card-shadow` | — |
| Hover (interactive) | `card-shadow-hover`, cursor pointer | `duration-interaction` |
| Active (interactive) | `card-shadow-active` | `duration-instant` |
| Focus (interactive) | Focus ring | `duration-instant` |
| Loading | Skeleton state | `duration-background` |
| Empty | Empty state illustration + text | — |
| Error | Error border or error message | `duration-interaction` |
---
## 14. KEYBOARD
| Key | Action |
|-----|--------|
| `Tab` | Move focus to next focusable element |
| `Enter` / `Space` | Activate actionable card |
| `Arrow keys` | Navigate between cards in grid/list |
---
## 15. TOUCH
- Touch target: Entire card if actionable
- Active state: Brief elevation reduction
- No gesture support (no swipe, pinch)
- Scroll: Card content scrolls internally if overflow
---
## 16. MOTION
| Transition | Animation | Duration | Easing |
|-----------|-----------|----------|--------|
| Hover (interactive) | Elevation increase | `duration-interaction` | `ease-out` |
| Active (interactive) | Elevation decrease | `duration-instant` | `ease-in` |
| Focus | Focus ring appear | `duration-instant` | `ease-out` |
| Loading skeleton | Shimmer animation | `duration-background` | `linear` |
| Error appear | Border color change | `duration-interaction` | `ease-out` |
**Reduced Motion:** No elevation animation. Focus ring appears instantly.
---
## 17. ANTI-PATTERNS
-**Nested cards:** Cards inside cards create visual confusion
-**Too much padding:** Wastes space, reduces information density
-**No visual distinction from background:** Defeats purpose of card
-**Inconsistent internal spacing:** Breaks scannability
-**Actionable without focus ring:** Accessibility failure
-**Clickable entire card with internal buttons:** Event collision
-**Card as only layout tool:** Use grid or flexbox for layout, card for grouping
-**Excessive elevation:** Competes with modals and overlays
---
## 18. RELATED COMPONENTS
- **Modal** — Overlay content, not inline
- **Panel** — Larger container, often full-height
- **List Item** — Single row, no grouping
- **Tile** — Image-first card variant
- **KPI Card** — Domain-specific card (Tier 3)
- **Dataset Card** — Domain-specific card (Tier 3)
---
## 19. DDR REFERENCES
- **DDR-001:** Device Adaptive over Desktop First (affects sizing and grid)
- **DDR-002:** Information-level typography (affects header and body text)
- **DDR-003:** Semantic color system (affects states)
- **DDR-005:** Elevation system (affects shadow tokens)
---
## 20. ACCEPTANCE CRITERIA
- [ ] All 12 Definition of Done criteria met
- [ ] Works with screen reader (announces as group or link/button)
- [ ] Keyboard navigation works (Tab, Enter, Space, Arrow keys)
- [ ] Touch target minimum 44px for actionable cards
- [ ] Focus ring visible on actionable cards
- [ ] Loading skeleton state implemented
- [ ] Empty state with guidance
- [ ] Error state handled
- [ ] Reduced motion respected
- [ ] No nested cards
---
## ÄNDRINGSHISTORIA
| Version | Datum | Beskrivning |
|---------|-------|-------------|
| 1.0 | 2026-07-02 | Initial RFC-004 following RFC-001 structure |
---
## STATUS
**DRAFT — Awaiting review**