Files
openpylon/docs/plans/2026-02-15-custom-date-picker-design.md
2026-02-15 21:58:10 +02:00

3.5 KiB
Raw Blame History

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
  • "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)