Add Input, Checkbox, Radio, and Switch form components with semantic token layer
Build four form primitives from Figma references with brand-aligned creative decisions: restrained press states (scale-95 instead of highlight splashes), clean iconless Switch, and consistent error states with inline warning icons. Introduce form-control semantic tokens (--color-control-*) in tokens.css so all form components share a single source for borders, checked states, focus rings, labels, and errors. Retrofit Input to use these tokens instead of direct palette references. Update CLAUDE.md and ARCHITECTURE.md with token layer documentation, token discipline rule (no palette references in components), and component tier decision criteria. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
55
plans/input.md
Normal file
55
plans/input.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Input Component Plan
|
||||
|
||||
## Figma Reference
|
||||
https://www.figma.com/design/mrabO6AtxN3ektGiTk0I9c/ResearchInsights?node-id=22-3845
|
||||
|
||||
## Design Style (from Figma)
|
||||
- Outlined text field with label overlapping top border (Material-style notch)
|
||||
- Label: 14px bold blue-01, sits on top of border with white background
|
||||
- Input: 16px regular grey-01, placeholder at 50% opacity
|
||||
- Border radius: 4px (rounded-sm)
|
||||
- Optional left/right icon slots (24px)
|
||||
- Supportive text below: hint (left) + character count (right), 14px grey-02
|
||||
|
||||
## Sizes
|
||||
| Size | Input height | Text | Maps to |
|
||||
|------|-------------|------|---------|
|
||||
| default | 48px (h-12) | text-body (16px) | Figma "Comfortable" |
|
||||
| compact | 40px (h-10) | text-small (14px) | Figma "Compact" |
|
||||
|
||||
## States (best practice, not 1:1 Figma)
|
||||
| State | Border | Label | Hint |
|
||||
|-------|--------|-------|------|
|
||||
| Default | grey-03 (1px) | blue-01 | grey-02 |
|
||||
| Hover | grey-01 (1px) | blue-01 | grey-02 |
|
||||
| Focus | blue-01 (2px) | blue-01 | grey-02 |
|
||||
| Error | red-02 (1px) | red-02 | red-02 (shows error message) |
|
||||
| Error+Focus | red-02 (2px) | red-02 | red-02 |
|
||||
| Disabled | grey-03 at 50% opacity | grey-02 | grey-02 at 50% opacity |
|
||||
|
||||
## Props
|
||||
```ts
|
||||
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
||||
label: string
|
||||
hint?: string
|
||||
error?: string
|
||||
size?: 'default' | 'compact'
|
||||
leftIcon?: React.ReactNode
|
||||
rightIcon?: React.ReactNode
|
||||
}
|
||||
```
|
||||
- `error` takes precedence over `hint` — when set, replaces hint text and turns red
|
||||
- `maxLength` (native attribute) triggers character counter display
|
||||
- `disabled` and `readOnly` use native attributes, styled accordingly
|
||||
|
||||
## Accessibility
|
||||
- `<label>` bound to `<input>` via `useId()` fallback
|
||||
- `aria-describedby` links hint/error text to the input
|
||||
- `aria-invalid="true"` when error is set
|
||||
- Keyboard fully native (no custom handling needed)
|
||||
|
||||
## Figma issues mitigated
|
||||
1. Default border 38% opacity too faint → using grey-03
|
||||
2. 10 redundant state variants → CSS pseudo-classes
|
||||
3. Dark mode variants → skipped
|
||||
4. Chips/file input states → separate components
|
||||
Reference in New Issue
Block a user