PR #176 opened: fix: date pickers unusable inside dialogs (mobile + desktop)
What was broken
QA flagged the booking dialog's date picker on desktop — clicking "Preferred date" produced no usable calendar. Reproduced on mobile too:
| Before — mobile (375px) | Before — desktop (1280px) |
|---|---|
| Calendar popover overflows left, month header off-screen, dates clipped | Popover clipped by dialog overflow, calendar barely visible |
Same root cause both viewports: the bespoke popover used absolute top-full right-0 left-0, which stretches it to the trigger's parent width. Inside the booking dialog the trigger lives in a 2-col Date × Time grid, so the parent is ~140px. The calendar grid is 7×44px = 308px (and 640px for the range picker's two-month layout). That overflowed the popover container in every direction.
Fix
Same responsive pattern Stu asked for ("Airbnb-style mobile component"), applied to both DatePicker and DateRangePicker:
- Mobile (
useIsMobile(), <768px): renders inside a<Sheet side="bottom">(already in the project via Radix Dialog). Calendar fills the sheet, month nav clearly visible, no clipping possible. - Desktop: keeps a popover but at fixed
w-[20rem](320px) anchored to the trigger's left edge instead of stretching to parent. No more overflow regardless of which column the trigger sits in.
DateRangePicker also drops from 2 months to 1 — two months at ~640px overflowed even the 512px booking dialog on desktop. Users navigate between months to pick a multi-month range (same UX Airbnb / booking.com use on narrow viewports).
Verified locally with Playwright
npm run build against Herd, ran each scenario at both viewports:
| Scenario | 375×667 | 1280×800 |
|---|---|---|
| Single-day booking, click "Preferred date" | ✓ Sheet slides up, full calendar | ✓ Popover, full calendar |
| Multi-day booking, click "Date range" | ✓ Sheet slides up, 1 month, range selectable | ✓ Popover, 1 month, range selectable |
| Pick a date → sheet/popover closes, form reflects selection | ✓ | ✓ |
Navigate months via < > | ✓ | ✓ |
Screenshots: scratch/datepicker-fixed-*.png, scratch/datepicker-range-*.png.
Blast radius
Both files are leaf UI components. Every consumer auto-inherits the fix:
components/cleaners/booking-dialog.tsx(the urgent bug surface)pages/Client/post-job/step-four.tsxpages/Client/Jobs/Edit.tsxpages/Cleaner/Verification/Index.tsxpages/Cleaner/Onboarding/StepOne.tsxpages/Cleaner/components/manage-certificates-dialog.tsx
No backend changes, no DB changes.
Test plan
- Local Playwright on both viewports for both pickers
- Selection writes back to form correctly, sheet closes
- Month navigation works in both modes
- Lint + typecheck clean
- Deploy to staging, manual smoke from a real mobile device