78436cecc2
- 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.
266 lines
8.6 KiB
Markdown
266 lines
8.6 KiB
Markdown
# RFC-002: Canonical Input Component
|
|
|
|
**Status:** 🟡 Draft — Under review
|
|
**Tier:** 1 (Canonical)
|
|
**Inherits From:** — (root component)
|
|
**Author:** AI Agent
|
|
**Date:** 2026-07-02
|
|
|
|
---
|
|
|
|
## 1. COGNITIVE PURPOSE
|
|
|
|
Input exists to capture free-form text or numeric data from the user. It is the primary interface for data entry in forms, filters, and search.
|
|
|
|
**Design Goal:** The user knows what to enter, where to enter it, and whether the entry is valid — without reading documentation.
|
|
|
|
---
|
|
|
|
## 2. WHEN TO USE
|
|
|
|
- Free-form text entry (name, address, description)
|
|
- Numeric entry (quantity, price, coordinates)
|
|
- Password entry
|
|
- Search queries
|
|
- Filter values
|
|
|
|
## 3. WHEN NOT TO USE
|
|
|
|
- Selection from predefined options (use Select)
|
|
- Boolean toggle (use Switch or Checkbox)
|
|
- Date/time selection (use Date Picker)
|
|
- File upload (use File Input)
|
|
- Rich text (use Rich Text Editor)
|
|
|
|
---
|
|
|
|
## 4. USER EXPECTATION
|
|
|
|
- Input field is identifiable as editable
|
|
- Placeholder text hints at expected format
|
|
- Focus state indicates where typing will appear
|
|
- Validation errors are shown immediately or on blur
|
|
- Required fields are marked
|
|
- Disabled fields are visually distinct
|
|
|
|
---
|
|
|
|
## 5. INTERACTION CONTRACT
|
|
|
|
| Event | Response |
|
|
|-------|----------|
|
|
| Click | Focus input, place cursor |
|
|
| Type | Character appears at cursor position |
|
|
| Tab | Move focus to next field |
|
|
| Shift+Tab | Move focus to previous field |
|
|
| Blur | Validate (if configured), show error if invalid |
|
|
| Enter | Submit form (if single-line), new line (if multi-line) |
|
|
| Escape | Clear input (if configured), or cancel |
|
|
|
|
---
|
|
|
|
## 6. FAILURE BEHAVIOUR
|
|
|
|
| Scenario | Response |
|
|
|----------|----------|
|
|
| Invalid input on blur | Show error message below input, red border |
|
|
| Invalid input on submit | Show error, scroll to first error, focus it |
|
|
| Network validation fails | Show error, allow retry |
|
|
| Input exceeds max length | Prevent further input, show character count |
|
|
| Input is required but empty | Show error on blur or submit |
|
|
| Input is disabled | Ignore all interactions, show disabled state |
|
|
|
|
---
|
|
|
|
## 7. ACCESSIBILITY CONTRACT
|
|
|
|
- **Label:** Every input MUST have an associated `<label>` or `aria-label`
|
|
- **Focus:** Focus ring MUST be visible (WCAG 2.4.7)
|
|
- **Error:** Error message MUST be associated with `aria-describedby`
|
|
- **Required:** Required state MUST be communicated with `aria-required` or `required` attribute
|
|
- **Screen reader:** MUST announce label, current value, and error state
|
|
- **Color:** Error state MUST NOT rely on color alone (icon or text required)
|
|
|
|
---
|
|
|
|
## 8. AI CONTRACT
|
|
|
|
| Scenario | AI Choice |
|
|
|----------|-----------|
|
|
| Free-form text entry | Input |
|
|
| Predefined options | Select |
|
|
| Boolean toggle | Switch / Checkbox |
|
|
| Date/time | Date Picker |
|
|
| File upload | File Input |
|
|
| Search with suggestions | Search (specialized component) |
|
|
|
|
---
|
|
|
|
## 9. TOKEN DEPENDENCIES
|
|
|
|
| Token | Semantic Reference | Usage |
|
|
|-------|-------------------|-------|
|
|
| Token | Semantic Alias | Primitive | Usage |
|
|
|-------|---------------|-----------|-------|
|
|
| `input-bg` | `color.surface.default` | `gray-0` | Background |
|
|
| `input-border` | `color.border.default` | `gray-200` | Default border |
|
|
| `input-border-focus` | `color.border.focus` | `blue-500` | Focus border |
|
|
| `input-border-error` | `color.border.error` | `red-500` | Error border |
|
|
| `input-text` | `color.text.primary` | `gray-900` | Input text |
|
|
| `input-placeholder` | `color.text.muted` | `gray-400` | Placeholder text |
|
|
| `input-padding` | `space-3` | `12px` | Internal padding |
|
|
| `input-radius` | `radius-md` | `8px` | Border radius |
|
|
| `input-height-sm` | `space-8` | `32px` | Small height |
|
|
| `input-height-md` | `space-10` | `40px` | Medium height |
|
|
| `input-height-lg` | `space-12` | `48px` | Large height |
|
|
| `input-error-bg` | `color.status.danger` (at 5%) | `red-50` | Error background tint |
|
|
| `input-disabled-bg` | `color.surface.raised` | `gray-50` | Disabled background |
|
|
| `input-disabled-text` | `color.text.muted` | `gray-400` | Disabled text |
|
|
|
|
---
|
|
|
|
## 10. LAYOUT
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ Label (optional) │
|
|
├─────────────────────────────────────┤
|
|
│ ┌─────────────────────────────────┐ │
|
|
│ │ Placeholder text... │ │
|
|
│ └─────────────────────────────────┘ │
|
|
│ Helper text / Error message │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
- **Label:** Above input, left-aligned, `text-sm`, `font-medium`
|
|
- **Input:** Full width of container, padding `space-3`
|
|
- **Helper/Error:** Below input, `text-xs`, `color.text.muted` (helper) or `color.status.danger` (error)
|
|
- **Gap:** `space-1` between label and input, `space-1` between input and helper
|
|
|
|
---
|
|
|
|
## 11. SIZES
|
|
|
|
| Size | Height | Font Size | Padding | Usage |
|
|
|------|--------|-----------|---------|-------|
|
|
| Small | 32px | 14px | `space-2` | Dense forms, tables |
|
|
| Medium | 40px | 16px | `space-3` | Default, most forms |
|
|
| Large | 48px | 18px | `space-4` | Mobile, touch-first |
|
|
|
|
---
|
|
|
|
## 12. VARIANTS
|
|
|
|
| Variant | Visual | Usage |
|
|
|---------|--------|-------|
|
|
| Default | Border, background | Standard form input |
|
|
| Ghost | No border, underline only | Minimal UI, filters |
|
|
| Filled | Solid background, no border | High-contrast forms |
|
|
|
|
---
|
|
|
|
## 13. STATES
|
|
|
|
| State | Visual | Motion |
|
|
|-------|--------|--------|
|
|
| Default | `input-border`, `input-bg` | — |
|
|
| Hover | Border darkens slightly | `duration-instant` |
|
|
| Focus | `input-border-focus`, focus ring | `duration-instant` |
|
|
| Active | Same as focus | — |
|
|
| Disabled | `input-disabled-bg`, `input-disabled-text` | — |
|
|
| Error | `input-border-error`, `input-error-bg` | `duration-interaction` |
|
|
| Loading | Spinner inside input, disabled | `duration-attention` |
|
|
| Valid | Green checkmark icon (optional) | `duration-interaction` |
|
|
|
|
---
|
|
|
|
## 14. KEYBOARD
|
|
|
|
| Key | Action |
|
|
|-----|--------|
|
|
| `Tab` | Move focus to next field |
|
|
| `Shift+Tab` | Move focus to previous field |
|
|
| `Enter` | Submit form (single-line) |
|
|
| `Escape` | Clear input (if clearable) |
|
|
| `Ctrl+A` | Select all text |
|
|
| `Ctrl+C/V/X` | Copy/paste/cut |
|
|
|
|
---
|
|
|
|
## 15. TOUCH
|
|
|
|
- Touch target: Minimum 40px height (Medium size)
|
|
- Active state: Brief background tint
|
|
- No gesture support (no swipe, pinch)
|
|
|
|
---
|
|
|
|
## 16. MOTION
|
|
|
|
| Transition | Animation | Duration | Easing |
|
|
|-----------|-----------|----------|--------|
|
|
| Focus | Border color change | `duration-instant` | `ease-out` |
|
|
| Error appear | Border + background tint | `duration-interaction` | `ease-out` |
|
|
| Error disappear | Revert to default | `duration-interaction` | `ease-in` |
|
|
| Loading spinner | Rotate | `duration-background` | `linear` |
|
|
|
|
**Reduced Motion:** All transitions become instant (`duration-instant`).
|
|
|
|
---
|
|
|
|
## 17. ANTI-PATTERNS
|
|
|
|
- ❌ **Placeholder as label:** Placeholder disappears on typing, user loses context
|
|
- ❌ **Validation only on submit:** User should know immediately if input is wrong
|
|
- ❌ **No visual feedback on focus:** User cannot see where they are typing
|
|
- ❌ **Error message in color only:** Screen reader users miss it
|
|
- ❌ **Input without label:** Accessibility failure, unclear purpose
|
|
- ❌ **Too many variations:** Stick to Default, Ghost, Filled
|
|
|
|
---
|
|
|
|
## 18. RELATED COMPONENTS
|
|
|
|
- **Select** — Predefined options instead of free-form
|
|
- **Textarea** — Multi-line text entry
|
|
- **Search** — Input with autocomplete and suggestions
|
|
- **Form** — Groups inputs with validation logic
|
|
- **Label** — Associated text for input
|
|
|
|
---
|
|
|
|
## 19. DDR REFERENCES
|
|
|
|
- **DDR-001:** Device Adaptive over Desktop First (affects input sizing)
|
|
- **DDR-002:** Information-level typography (affects label and helper text)
|
|
- **DDR-003:** Semantic color system (affects error and disabled states)
|
|
|
|
---
|
|
|
|
## 20. ACCEPTANCE CRITERIA
|
|
|
|
- [ ] All 12 Definition of Done criteria met
|
|
- [ ] Works with screen reader (NVDA, VoiceOver, JAWS)
|
|
- [ ] Keyboard navigation works (Tab, Shift+Tab, Enter, Escape)
|
|
- [ ] Touch target minimum 40px on mobile
|
|
- [ ] Error state visible without color alone
|
|
- [ ] Placeholder does not replace label
|
|
- [ ] Loading state prevents duplicate submission
|
|
- [ ] Disabled state clearly distinct from enabled
|
|
- [ ] Focus ring visible and logical
|
|
- [ ] Reduced motion respected
|
|
|
|
---
|
|
|
|
## ÄNDRINGSHISTORIA
|
|
|
|
| Version | Datum | Beskrivning |
|
|
|---------|-------|-------------|
|
|
| 1.0 | 2026-07-02 | Initial RFC-002 following RFC-001 structure |
|
|
|
|
---
|
|
|
|
## STATUS
|
|
|
|
**DRAFT — Awaiting review**
|