docs: Motion System v1 + Button gold standard + Component Template + Decision Tree
- Motion System v1 (chapter 5):
- Motion principles: when to animate, when NOT to animate
- Duration scale (instant to slower: 0ms to 500ms)
- Easing functions (linear, in, out, in-out, spring)
- Component-specific motion: Button, Modal, Drawer, Map, Skeleton,
Progress, Error/Success
- Reduced motion support (prefers-reduced-motion)
- Interruption rules (animations must be interruptible)
- Error/success animations (shake, checkmark, pulse)
- Button gold standard (chapter 8.3.1):
- Full specification: purpose, design goal, token dependencies,
layout, sizes, variants, states, keyboard, touch, accessibility,
anti-patterns, related components, DDR references
- Sets the bar for all future component specifications
- COMPONENT_TEMPLATE.md (v1.0, LOCKED):
- Standard template for all component specifications
- Sections: purpose, tokens, layout, sizes, variants, states,
keyboard, touch, accessibility, motion, acceptance criteria,
anti-patterns, related components, DDR references
- COMPONENT_DECISION_TREE.md (v1.0, LOCKED):
- Decision trees for: user actions, information display, user input,
feedback, navigation, Landvex-specific
- Quick reference table mapping needs to components
- Prevents invention of unnecessary components
Rationale: Motion before brand (affects every interaction). Button as
reference implementation. Template ensures consistency. Decision tree
guides AI agents and developers to correct component choice.
This commit is contained in:
@@ -0,0 +1,222 @@
|
|||||||
|
# COMPONENT DECISION TREE
|
||||||
|
|
||||||
|
**Which Component Should I Use?**
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| **Version** | 1.0 |
|
||||||
|
| **Status** | LOCKED |
|
||||||
|
| **Scope** | All Landvex & quiXzoom products |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Use This Document
|
||||||
|
|
||||||
|
Start at the top. Answer each question. Follow the path to the recommended component.
|
||||||
|
|
||||||
|
If no existing component fits, apply the **New Component Rule** (see Design Specification §8.2):
|
||||||
|
1. Can an existing component be used?
|
||||||
|
2. Can a variant be created?
|
||||||
|
3. Can a modifier be used?
|
||||||
|
4. Can a new state solve the problem?
|
||||||
|
|
||||||
|
Only then define a new component.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## User Actions
|
||||||
|
|
||||||
|
```
|
||||||
|
Need user action?
|
||||||
|
├── Yes → Primary action?
|
||||||
|
│ ├── Yes → Button (Primary)
|
||||||
|
│ └── No → Multiple options?
|
||||||
|
│ ├── Yes → Select / Dropdown
|
||||||
|
│ └── No → Toggle state?
|
||||||
|
│ ├── Yes → Switch / Checkbox
|
||||||
|
│ └── No → Navigation?
|
||||||
|
│ ├── Yes → Navigation / Sidebar
|
||||||
|
│ └── No → Search?
|
||||||
|
│ ├── Yes → Search
|
||||||
|
│ └── No → Command Palette
|
||||||
|
└── No → Need information display?
|
||||||
|
└── Yes → See Information Display
|
||||||
|
```
|
||||||
|
|
||||||
|
## Information Display
|
||||||
|
|
||||||
|
```
|
||||||
|
Need to display information?
|
||||||
|
├── Yes → Tabular data?
|
||||||
|
│ ├── Yes → Simple table?
|
||||||
|
│ │ ├── Yes → Table
|
||||||
|
│ │ └── No → Sorting, filtering, pagination?
|
||||||
|
│ │ ├── Yes → Data Grid
|
||||||
|
│ │ └── No → Table
|
||||||
|
│ └── No → Spatial data?
|
||||||
|
│ ├── Yes → Map Panel
|
||||||
|
│ └── No → Summary metric?
|
||||||
|
│ ├── Yes → KPI Card
|
||||||
|
│ └── No → Grouped content?
|
||||||
|
│ ├── Yes → Card / Accordion
|
||||||
|
│ └── No → Single item?
|
||||||
|
│ ├── Yes → Badge / Alert
|
||||||
|
│ └── No → Tooltip
|
||||||
|
└── No → Need user input?
|
||||||
|
└── Yes → See User Input
|
||||||
|
```
|
||||||
|
|
||||||
|
## User Input
|
||||||
|
|
||||||
|
```
|
||||||
|
Need user input?
|
||||||
|
├── Yes → Text input?
|
||||||
|
│ ├── Yes → Single line?
|
||||||
|
│ │ ├── Yes → Input
|
||||||
|
│ │ └── No → Textarea
|
||||||
|
│ └── No → Choice from options?
|
||||||
|
│ ├── Yes → Single choice?
|
||||||
|
│ │ ├── Yes → Radio / Select
|
||||||
|
│ │ └── No → Multiple choice?
|
||||||
|
│ │ ├── Yes → Checkbox / Multi-select
|
||||||
|
│ │ └── No → Toggle?
|
||||||
|
│ │ ├── Yes → Switch
|
||||||
|
│ │ └── No → Date / time?
|
||||||
|
│ │ ├── Yes → Date Picker
|
||||||
|
│ │ └── No → Coordinate?
|
||||||
|
│ │ ├── Yes → Coordinate Picker
|
||||||
|
│ │ └── No → File?
|
||||||
|
│ │ ├── Yes → File Upload
|
||||||
|
│ │ └── No → Input (custom)
|
||||||
|
│ └── No → Search / filter?
|
||||||
|
│ ├── Yes → Search
|
||||||
|
│ └── No → Command Palette
|
||||||
|
└── No → Need feedback?
|
||||||
|
└── Yes → See Feedback
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
|
||||||
|
```
|
||||||
|
Need to provide feedback?
|
||||||
|
├── Yes → Blocking action?
|
||||||
|
│ ├── Yes → Modal / Dialog
|
||||||
|
│ └── No → Transient notification?
|
||||||
|
│ ├── Yes → Toast
|
||||||
|
│ └── No → Contextual message?
|
||||||
|
│ ├── Yes → Alert (inline) / Tooltip
|
||||||
|
│ └── No → Status indicator?
|
||||||
|
│ ├── Yes → Badge
|
||||||
|
│ └── No → Progress?
|
||||||
|
│ ├── Yes → Progress / Skeleton
|
||||||
|
│ └── No → Empty State
|
||||||
|
└── No → Navigation or structure?
|
||||||
|
└── Yes → See Navigation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
```
|
||||||
|
Need navigation?
|
||||||
|
├── Yes → Primary navigation?
|
||||||
|
│ ├── Yes → Top-level sections?
|
||||||
|
│ │ ├── Yes → Navigation
|
||||||
|
│ │ └── No → Sidebar
|
||||||
|
│ └── No → Secondary navigation?
|
||||||
|
│ ├── Yes → Tabs / Breadcrumb
|
||||||
|
│ └── No → Contextual navigation?
|
||||||
|
│ ├── Yes → Pagination / Menu
|
||||||
|
│ └── No → Command Palette
|
||||||
|
└── No → Consider: is this a new component?
|
||||||
|
└── Apply New Component Rule
|
||||||
|
```
|
||||||
|
|
||||||
|
## Landvex-Specific (Domain Components)
|
||||||
|
|
||||||
|
```
|
||||||
|
Need Landvex-specific component?
|
||||||
|
├── Yes → Geospatial data?
|
||||||
|
│ ├── Yes → Map visualization?
|
||||||
|
│ │ ├── Yes → Map Panel
|
||||||
|
│ │ └── No → Layer control?
|
||||||
|
│ │ ├── Yes → Layer Selector
|
||||||
|
│ │ └── No → Feature inspection?
|
||||||
|
│ │ ├── Yes → Geospatial Inspector
|
||||||
|
│ │ └── No → Coordinate input?
|
||||||
|
│ │ └── Yes → Coordinate Picker
|
||||||
|
│ └── No → Mission data?
|
||||||
|
│ ├── Yes → Mission status?
|
||||||
|
│ │ ├── Yes → Mission Status
|
||||||
|
│ │ └── No → Mission timeline?
|
||||||
|
│ │ └── Yes → Timeline Panel
|
||||||
|
│ └── No → Asset data?
|
||||||
|
│ ├── Yes → Asset summary?
|
||||||
|
│ │ ├── Yes → Asset Summary
|
||||||
|
│ │ └── No → Dataset preview?
|
||||||
|
│ │ └── Yes → Dataset Card
|
||||||
|
│ └── No → KPI display?
|
||||||
|
│ └── Yes → KPI Card
|
||||||
|
└── No → See general decision trees above
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference Table
|
||||||
|
|
||||||
|
| Need | Component | Tier |
|
||||||
|
|------|-----------|------|
|
||||||
|
| Primary action | Button | 1 |
|
||||||
|
| Text input | Input | 1 |
|
||||||
|
| Choice from list | Select | 1 |
|
||||||
|
| Content container | Card | 1 |
|
||||||
|
| Overlay dialog | Modal | 1 |
|
||||||
|
| Navigation | Navigation / Sidebar | 1 |
|
||||||
|
| Tabular data | Table / Data Grid | 1 |
|
||||||
|
| Search | Search | 1 |
|
||||||
|
| Map display | Map Panel | 1 |
|
||||||
|
| Status indicator | Badge | 2 |
|
||||||
|
| Message | Alert / Toast | 2 |
|
||||||
|
| Help text | Tooltip | 2 |
|
||||||
|
| Collapsible content | Accordion | 2 |
|
||||||
|
| Content switching | Tabs | 2 |
|
||||||
|
| Location indicator | Breadcrumb | 2 |
|
||||||
|
| Page navigation | Pagination | 2 |
|
||||||
|
| No content | Empty State | 2 |
|
||||||
|
| Loading | Skeleton | 2 |
|
||||||
|
| Key metric | KPI Card | 3 |
|
||||||
|
| Map tools | Map Overlay Panel | 3 |
|
||||||
|
| Layer control | Layer Selector | 3 |
|
||||||
|
| Mission state | Mission Status | 3 |
|
||||||
|
| Data preview | Dataset Card | 3 |
|
||||||
|
| Feature details | Geospatial Inspector | 3 |
|
||||||
|
| Asset overview | Asset Summary | 3 |
|
||||||
|
| Coordinate input | Coordinate Picker | 3 |
|
||||||
|
| Time data | Timeline Panel | 3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Relationship to Other Documents
|
||||||
|
|
||||||
|
| Document | Role |
|
||||||
|
|----------|------|
|
||||||
|
| `LANDVEX_DESIGN_SPECIFICATION.md` §8 | Component tiers and inheritance |
|
||||||
|
| `COMPONENT_TEMPLATE.md` | How to document a component |
|
||||||
|
| `DESIGN_ANTI_PATTERNS.md` | What not to do |
|
||||||
|
| `COMPONENT_DECISION_TREE.md` | Which component to use |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ÄNDRINGSHISTORIA
|
||||||
|
|
||||||
|
| Version | Datum | Beskrivning |
|
||||||
|
|---------|-------|-------------|
|
||||||
|
| 1.0 | 2026-07-02 | Initial decision trees for actions, information, input, feedback, navigation, and Landvex-specific |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## STATUS
|
||||||
|
|
||||||
|
**LOCKED**
|
||||||
|
|
||||||
|
- Mindre revideringar: 1.x-serien
|
||||||
|
- Brytande ändringar: Kräver Architecture Review, ny major-version (2.0+)
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
# COMPONENT TEMPLATE
|
||||||
|
|
||||||
|
**Template for All Component Specifications**
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| **Version** | 1.0 |
|
||||||
|
| **Status** | LOCKED |
|
||||||
|
| **Scope** | All Landvex & quiXzoom components |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Copy this template for each new component. Remove sections that do not apply. Add sections that are component-specific.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [Component Name]
|
||||||
|
|
||||||
|
**Purpose:** One sentence describing what this component does.
|
||||||
|
|
||||||
|
**Design Goal:** One sentence describing the ideal user experience.
|
||||||
|
|
||||||
|
**Tier:** [1 (Canonical) / 2 (Derived) / 3 (Domain)]
|
||||||
|
|
||||||
|
**Inherits From:** [Parent component, or "—" if canonical]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Token Dependencies
|
||||||
|
|
||||||
|
| Token | Semantic Reference | Usage |
|
||||||
|
|-------|-------------------|-------|
|
||||||
|
| `component-token-1` | `semantic-token-1` | Description |
|
||||||
|
| `component-token-2` | `semantic-token-2` | Description |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Layout
|
||||||
|
|
||||||
|
- Dimensions
|
||||||
|
- Padding
|
||||||
|
- Margins
|
||||||
|
- Border radius
|
||||||
|
- Internal structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Sizes
|
||||||
|
|
||||||
|
| Size | Dimensions | Usage |
|
||||||
|
|------|-----------|-------|
|
||||||
|
| Small | [dimensions] | [context] |
|
||||||
|
| Default | [dimensions] | [context] |
|
||||||
|
| Large | [dimensions] | [context] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Variants
|
||||||
|
|
||||||
|
| Variant | Visual | Usage |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| Variant 1 | [description] | [context] |
|
||||||
|
| Variant 2 | [description] | [context] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### States
|
||||||
|
|
||||||
|
| State | Visual | Motion |
|
||||||
|
|-------|--------|--------|
|
||||||
|
| Default | [description] | [animation] |
|
||||||
|
| Hover | [description] | [animation] |
|
||||||
|
| Focus | [description] | [animation] |
|
||||||
|
| Active | [description] | [animation] |
|
||||||
|
| Disabled | [description] | [animation] |
|
||||||
|
| Loading | [description] | [animation] |
|
||||||
|
| Error | [description] | [animation] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Keyboard
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `Tab` | [behavior] |
|
||||||
|
| `Enter` / `Space` | [behavior] |
|
||||||
|
| `Escape` | [behavior] |
|
||||||
|
| Arrow keys | [behavior] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Touch
|
||||||
|
|
||||||
|
- Touch target size
|
||||||
|
- Active state behavior
|
||||||
|
- Gesture support (if any)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Accessibility
|
||||||
|
|
||||||
|
- ARIA roles
|
||||||
|
- ARIA states
|
||||||
|
- Screen reader behavior
|
||||||
|
- Focus management
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Motion
|
||||||
|
|
||||||
|
| Transition | Animation | Duration | Easing |
|
||||||
|
|-----------|-----------|----------|--------|
|
||||||
|
| [state change] | [description] | [duration] | [easing] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] Criterion 1
|
||||||
|
- [ ] Criterion 2
|
||||||
|
- [ ] Criterion 3
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Anti-Patterns
|
||||||
|
|
||||||
|
- ❌ [What not to do]
|
||||||
|
- ❌ [What not to do]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Related Components
|
||||||
|
|
||||||
|
- [Component A] — [relationship]
|
||||||
|
- [Component B] — [relationship]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DDR References
|
||||||
|
|
||||||
|
- DDR-XXX: [Decision rationale]
|
||||||
@@ -511,29 +511,129 @@ Dedicated palette for geospatial visualization. Defined by **layer**, not indivi
|
|||||||
|
|
||||||
## 5. Motion System
|
## 5. Motion System
|
||||||
|
|
||||||
> **Status:** ⏳ Ej påbörjad
|
> **Status:** ✅ Specified
|
||||||
|
> **Principle:** Motion supports understanding. It never decorates.
|
||||||
|
|
||||||
### 5.1 Duration Scale
|
### 5.1 Motion Principles
|
||||||
|
|
||||||
|
**When to animate:**
|
||||||
|
- State changes that need attention (modal open, toast appear)
|
||||||
|
- Spatial relationships (drawer slide, page transition)
|
||||||
|
- Feedback on user action (button press, form submit)
|
||||||
|
- Loading and progress (skeleton, progress bar)
|
||||||
|
|
||||||
|
**When NOT to animate:**
|
||||||
|
- Static content that does not change
|
||||||
|
- Data updates that are frequent (live dashboards)
|
||||||
|
- Elements entering viewport on scroll (use Intersection Observer, not animation)
|
||||||
|
- Anything that delays user action
|
||||||
|
|
||||||
|
**Rules:**
|
||||||
|
- Animations must be interruptible
|
||||||
|
- Multiple animations must not conflict
|
||||||
|
- Motion must respect `prefers-reduced-motion`
|
||||||
|
|
||||||
|
### 5.2 Duration Scale
|
||||||
|
|
||||||
| Token | Value | Usage |
|
| Token | Value | Usage |
|
||||||
|-------|-------|-------|
|
|-------|-------|-------|
|
||||||
| `duration-instant` | 0ms | No animation |
|
| `duration-instant` | 0ms | No animation |
|
||||||
| `duration-fast` | 100ms | Hover states |
|
| `duration-fast` | 100ms | Hover states, focus rings |
|
||||||
| `duration-normal` | 200ms | Standard transitions |
|
| `duration-normal` | 200ms | Standard transitions |
|
||||||
| `duration-slow` | 300ms | Page transitions |
|
| `duration-slow` | 300ms | Page transitions, drawers |
|
||||||
| `duration-slower` | 500ms | Complex animations |
|
| `duration-slower` | 500ms | Complex animations, modals |
|
||||||
|
|
||||||
### 5.2 Easing Functions
|
### 5.3 Easing Functions
|
||||||
|
|
||||||
| Token | Value | Usage |
|
| Token | Value | Usage |
|
||||||
|-------|-------|-------|
|
|-------|-------|-------|
|
||||||
| `ease-linear` | linear | Continuous motion |
|
| `ease-linear` | linear | Continuous motion, progress bars |
|
||||||
| `ease-in` | cubic-bezier(0.4, 0, 1, 1) | Exit animations |
|
| `ease-in` | cubic-bezier(0.4, 0, 1, 1) | Exit animations, dismiss |
|
||||||
| `ease-out` | cubic-bezier(0, 0, 0.2, 1) | Enter animations |
|
| `ease-out` | cubic-bezier(0, 0, 0.2, 1) | Enter animations, appear |
|
||||||
| `ease-in-out` | cubic-bezier(0.4, 0, 0.2, 1) | Standard |
|
| `ease-in-out` | cubic-bezier(0.4, 0, 0.2, 1) | Standard, symmetric |
|
||||||
| `ease-spring` | cubic-bezier(0.34, 1.56, 0.64, 1) | Playful interactions |
|
| `ease-spring` | cubic-bezier(0.34, 1.56, 0.64, 1) | Playful, overshoot |
|
||||||
|
|
||||||
### 5.3 Motion Principles
|
### 5.4 Component-Specific Motion
|
||||||
|
|
||||||
|
#### 5.4.1 Button
|
||||||
|
|
||||||
|
| State | Animation | Duration | Easing |
|
||||||
|
|-------|-----------|----------|--------|
|
||||||
|
| Hover | Background color shift | 100ms | ease-out |
|
||||||
|
| Press | Scale to 0.98 | 50ms | ease-in |
|
||||||
|
| Release | Scale to 1.0 | 100ms | ease-out |
|
||||||
|
| Loading | Spinner rotation | 1s | linear infinite |
|
||||||
|
| Disabled | Opacity to 0.5 | 100ms | ease-in-out |
|
||||||
|
|
||||||
|
#### 5.4.2 Modal
|
||||||
|
|
||||||
|
| State | Animation | Duration | Easing |
|
||||||
|
|-------|-----------|----------|--------|
|
||||||
|
| Open | Fade in + scale from 0.95 | 300ms | ease-out |
|
||||||
|
| Close | Fade out + scale to 0.95 | 200ms | ease-in |
|
||||||
|
| Backdrop | Fade to 50% opacity | 300ms | ease-in-out |
|
||||||
|
|
||||||
|
#### 5.4.3 Drawer
|
||||||
|
|
||||||
|
| State | Animation | Duration | Easing |
|
||||||
|
|-------|-----------|----------|--------|
|
||||||
|
| Open | Slide from edge | 300ms | ease-out |
|
||||||
|
| Close | Slide to edge | 200ms | ease-in |
|
||||||
|
| Backdrop | Fade to 50% opacity | 300ms | ease-in-out |
|
||||||
|
|
||||||
|
#### 5.4.4 Map Transitions
|
||||||
|
|
||||||
|
| State | Animation | Duration | Easing |
|
||||||
|
|-------|-----------|----------|--------|
|
||||||
|
| Pan | None (instant) | 0ms | — |
|
||||||
|
| Zoom | Smooth interpolation | 300ms | ease-in-out |
|
||||||
|
| Layer toggle | Cross-fade | 200ms | ease-in-out |
|
||||||
|
| Feature select | Highlight pulse | 300ms | ease-out |
|
||||||
|
|
||||||
|
**Rule:** Map panning is never animated. Users need instant feedback on drag.
|
||||||
|
|
||||||
|
#### 5.4.5 Skeleton
|
||||||
|
|
||||||
|
| State | Animation | Duration | Easing |
|
||||||
|
|-------|-----------|----------|--------|
|
||||||
|
| Loading | Shimmer sweep | 1.5s | ease-in-out infinite |
|
||||||
|
| Complete | Fade to content | 200ms | ease-out |
|
||||||
|
|
||||||
|
#### 5.4.6 Progress
|
||||||
|
|
||||||
|
| State | Animation | Duration | Easing |
|
||||||
|
|-------|-----------|----------|--------|
|
||||||
|
| Indeterminate | Sweep | 1s | linear infinite |
|
||||||
|
| Determinate | Width growth | 300ms | ease-out |
|
||||||
|
| Complete | Checkmark draw | 200ms | ease-out |
|
||||||
|
|
||||||
|
### 5.5 Reduced Motion
|
||||||
|
|
||||||
|
When `prefers-reduced-motion: reduce` is active:
|
||||||
|
|
||||||
|
- All animations become instant (0ms)
|
||||||
|
- Skeleton shows static placeholder (no shimmer)
|
||||||
|
- Progress shows static bar (no sweep)
|
||||||
|
- Map zoom uses instant jump (no interpolation)
|
||||||
|
- Modals and drawers appear instantly (no fade/scale)
|
||||||
|
|
||||||
|
**Exception:** Loading spinners may rotate slowly (2s per rotation) to indicate activity without motion.
|
||||||
|
|
||||||
|
### 5.6 Interruptions
|
||||||
|
|
||||||
|
**Rule:** Animations must be interruptible.
|
||||||
|
|
||||||
|
- If a modal is closing and user opens another, the first must complete or reverse instantly
|
||||||
|
- If a drawer is sliding and user taps backdrop, it must reverse direction
|
||||||
|
- No animation queue buildup
|
||||||
|
|
||||||
|
### 5.7 Error and Success Animations
|
||||||
|
|
||||||
|
| Type | Animation | Duration | Purpose |
|
||||||
|
|------|-----------|----------|---------|
|
||||||
|
| Error | Subtle shake (4px, 3 cycles) | 300ms | Indicate invalid input |
|
||||||
|
| Success | Checkmark draw + fade | 400ms | Confirm completion |
|
||||||
|
| Warning | Pulse border color | 2s | Draw attention without alarm |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -666,46 +766,86 @@ Only then may a new component be defined.
|
|||||||
|
|
||||||
### 8.3.1 Button
|
### 8.3.1 Button
|
||||||
|
|
||||||
**States:**
|
**Purpose:** Trigger primary user actions. The most used interactive element.
|
||||||
- Default
|
|
||||||
- Hover
|
**Design Goal:** Immediately recognizable, consistently responsive, accessible without thought.
|
||||||
- Focus
|
|
||||||
- Pressed (Active)
|
**Token Dependencies:**
|
||||||
- Loading
|
- `button-primary-bg` → `brand-500`
|
||||||
- Disabled
|
- `button-primary-bg-hover` → `brand-600`
|
||||||
|
- `button-primary-text` → `text-inverse`
|
||||||
|
- `button-secondary-bg` → `surface-secondary`
|
||||||
|
- `button-secondary-border` → `border-default`
|
||||||
|
- `button-ghost-text` → `brand-500`
|
||||||
|
- `space-padding-button` → `space-3` (12px vertical, `space-4` horizontal)
|
||||||
|
- `radius-button` → `radius-2` (4px)
|
||||||
|
|
||||||
|
**Layout:**
|
||||||
|
- Height: 40px (default), 32px (small), 48px (large)
|
||||||
|
- Padding: 12px vertical, 16px horizontal
|
||||||
|
- Icon + text gap: 8px
|
||||||
|
- Border radius: 4px
|
||||||
|
|
||||||
|
**Sizes:**
|
||||||
|
|
||||||
|
| Size | Height | Padding | Font | Usage |
|
||||||
|
|------|--------|---------|------|-------|
|
||||||
|
| Small | 32px | 8px 12px | `text-sm` | Dense UIs, tables |
|
||||||
|
| Default | 40px | 12px 16px | `text-base` | Standard |
|
||||||
|
| Large | 48px | 16px 24px | `text-lg` | Hero actions, mobile |
|
||||||
|
|
||||||
**Variants:**
|
**Variants:**
|
||||||
- Primary
|
|
||||||
- Secondary
|
|
||||||
- Tertiary (Ghost)
|
|
||||||
- Danger
|
|
||||||
- Icon-only
|
|
||||||
|
|
||||||
**ARIA:**
|
| Variant | Background | Border | Text | Usage |
|
||||||
|
|---------|------------|--------|------|-------|
|
||||||
|
| Primary | `brand-500` | None | White | Main action |
|
||||||
|
| Secondary | `surface-secondary` | `border-default` | `text-primary` | Alternative action |
|
||||||
|
| Ghost | Transparent | None | `brand-500` | Low emphasis |
|
||||||
|
| Danger | `semantic-red-500` | None | White | Destructive action |
|
||||||
|
| Icon-only | Any above | None | CurrentColor | Toolbar, compact |
|
||||||
|
|
||||||
|
**States:**
|
||||||
|
|
||||||
|
| State | Visual | Motion |
|
||||||
|
|-------|--------|--------|
|
||||||
|
| Default | As variant | None |
|
||||||
|
| Hover | Darken 10% | Background shift 100ms ease-out |
|
||||||
|
| Focus | 2px ring `border-focus` | Ring appear 100ms ease-out |
|
||||||
|
| Pressed | Scale 0.98 | Scale 50ms ease-in |
|
||||||
|
| Loading | Spinner replaces text | Spinner 1s linear infinite |
|
||||||
|
| Disabled | Opacity 0.5, no pointer | None |
|
||||||
|
|
||||||
|
**Keyboard:**
|
||||||
|
- `Tab`: Focus
|
||||||
|
- `Enter` / `Space`: Activate
|
||||||
|
- Disabled: Not focusable
|
||||||
|
|
||||||
|
**Touch:**
|
||||||
|
- Min 44x44px touch target
|
||||||
|
- Active state on press (immediate)
|
||||||
|
- No hover state on touch
|
||||||
|
|
||||||
|
**Accessibility:**
|
||||||
- `role="button"`
|
- `role="button"`
|
||||||
- `aria-label` for icon-only
|
- `aria-label` for icon-only
|
||||||
- `aria-disabled` for disabled
|
- `aria-disabled` for disabled
|
||||||
- `aria-busy` for loading
|
- `aria-busy` for loading
|
||||||
|
- Focus ring always visible
|
||||||
|
|
||||||
**Keyboard:**
|
**Anti-Patterns:**
|
||||||
- `Enter` / `Space` to activate
|
- ❌ Two primary buttons in same view
|
||||||
- `Tab` to focus
|
- ❌ Disabled button without explanation
|
||||||
|
- ❌ Button that looks like link
|
||||||
|
- ❌ Loading button that remains clickable
|
||||||
|
|
||||||
**Touch:**
|
**Related Components:**
|
||||||
- Min 44x44px touch target
|
- Split Button (extends Button)
|
||||||
- Active state on press
|
- Icon Button (extends Button)
|
||||||
|
- Floating Action Button (extends Button)
|
||||||
|
|
||||||
**Animation:**
|
**DDR References:**
|
||||||
- Hover: background-color 100ms ease-out
|
- DDR-001: Why buttons use brand color for primary action
|
||||||
- Press: scale(0.98) 50ms
|
- DDR-002: Why ghost variant exists (low emphasis without border)
|
||||||
- Loading: spinner rotation 1s linear infinite
|
|
||||||
|
|
||||||
**Acceptance Criteria:**
|
|
||||||
- [ ] All states are visually distinct
|
|
||||||
- [ ] Focus ring is visible
|
|
||||||
- [ ] Loading state prevents double-submit
|
|
||||||
- [ ] Disabled state is not focusable
|
|
||||||
- [ ] Touch target meets 44px minimum
|
|
||||||
|
|
||||||
### 8.3.2 Input / Text Field
|
### 8.3.2 Input / Text Field
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user