diff --git a/docs/plans/2026-02-15-custom-date-picker-design.md b/docs/plans/2026-02-15-custom-date-picker-design.md new file mode 100644 index 0000000..376bf5f --- /dev/null +++ b/docs/plans/2026-02-15-custom-date-picker-design.md @@ -0,0 +1,87 @@ +# Custom Date Picker — Design Document + +**Date:** 2026-02-15 +**Status:** Approved + +## Problem + +The DueDatePicker uses a native `` 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 `` 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)