3.5 KiB
3.5 KiB
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)