docs: add custom date picker design document
This commit is contained in:
87
docs/plans/2026-02-15-custom-date-picker-design.md
Normal file
87
docs/plans/2026-02-15-custom-date-picker-design.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Custom Date Picker — Design Document
|
||||||
|
|
||||||
|
**Date:** 2026-02-15
|
||||||
|
**Status:** Approved
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
The DueDatePicker uses a native `<input type="date">` which looks out of place in the app's custom dark theme with OKLCH colors. Need a fully custom calendar widget that matches the design language.
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
| Question | Answer |
|
||||||
|
|----------|--------|
|
||||||
|
| Trigger | Click the entire due date grid cell |
|
||||||
|
| Calendar position | Popover floating below the cell |
|
||||||
|
| Navigation | Month + year dropdown selectors |
|
||||||
|
| Today button | Yes, at bottom of calendar |
|
||||||
|
| Past dates | Selectable but dimmed |
|
||||||
|
| Clear action | Both: x on cell display AND Clear button in calendar footer |
|
||||||
|
| Approach | Fully custom (date-fns + Radix Popover, no new deps) |
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ Due Date Grid Cell ──────────────────────┐
|
||||||
|
│ DUE DATE [×] │
|
||||||
|
│ Feb 20, 2026 · in 5 days │
|
||||||
|
└───────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼ popover (280px wide)
|
||||||
|
┌───────────────────────────────────────┐
|
||||||
|
│ ◀ [February ▾] [2026 ▾] ▶ │
|
||||||
|
├───────────────────────────────────────┤
|
||||||
|
│ Mo Tu We Th Fr Sa Su │
|
||||||
|
│ ·· ·· ·· ·· ·· 1 2 │
|
||||||
|
│ 3 4 5 6 7 8 9 │
|
||||||
|
│ 10 11 12 13 14 ⬤15 16 │
|
||||||
|
│ 17 18 19 ■20 21 22 23 │
|
||||||
|
│ 24 25 26 27 28 ·· ·· │
|
||||||
|
├───────────────────────────────────────┤
|
||||||
|
│ [Today] [Clear] │
|
||||||
|
└───────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### DueDatePicker (modified)
|
||||||
|
- Remove `<input type="date">` entirely
|
||||||
|
- Cell display: formatted date + relative time, or placeholder
|
||||||
|
- × clear button in section header (visible when date is set)
|
||||||
|
- Clicking cell body opens CalendarPopover
|
||||||
|
- Overdue dates in `text-pylon-danger`
|
||||||
|
|
||||||
|
### CalendarPopover (new)
|
||||||
|
- Radix Popover anchored below the cell
|
||||||
|
- 280px wide, `bg-pylon-surface rounded-xl shadow-2xl`
|
||||||
|
|
||||||
|
#### Header
|
||||||
|
- Left/right arrow buttons for prev/next month
|
||||||
|
- Clickable month name → month selector (3×4 grid of month names)
|
||||||
|
- Clickable year → year selector (grid of years, current ±5)
|
||||||
|
|
||||||
|
#### Day Grid
|
||||||
|
- 7 columns (Mo-Su), 6 rows max
|
||||||
|
- Day cells: `size-9 text-sm rounded-lg`
|
||||||
|
- Selected: `bg-pylon-accent text-white`
|
||||||
|
- Today: `ring-1 ring-pylon-accent`
|
||||||
|
- Past: `opacity-50`
|
||||||
|
- Other month days: hidden (empty cells)
|
||||||
|
- Hover: `bg-pylon-column`
|
||||||
|
|
||||||
|
#### Footer
|
||||||
|
- "Today" button (left) — jumps to and selects today
|
||||||
|
- "Clear" button (right) — removes due date
|
||||||
|
|
||||||
|
### Animation
|
||||||
|
- Popover: `scaleIn` + `springs.snappy`
|
||||||
|
- Month/year selector: `AnimatePresence mode="wait"` crossfade
|
||||||
|
|
||||||
|
## Files
|
||||||
|
- Create: `src/components/card-detail/CalendarPopover.tsx`
|
||||||
|
- Modify: `src/components/card-detail/DueDatePicker.tsx`
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- date-fns v4 (already installed): `startOfMonth`, `endOfMonth`, `startOfWeek`, `endOfWeek`, `eachDayOfInterval`, `format`, `isSameDay`, `isSameMonth`, `isToday`, `isPast`, `addMonths`, `subMonths`, `setMonth`, `setYear`, `getYear`
|
||||||
|
- Radix Popover (already installed via `src/components/ui/popover.tsx`)
|
||||||
|
- Framer Motion (already installed)
|
||||||
Reference in New Issue
Block a user