# 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**