MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-110

2.4.12 `components/ui/DatePicker` primitive + wire into the issue date fields

Done
Description

Estimate: 18m · Depends on: 2.4.11

Build a presentational, accessible DatePicker in components/ui/ per 2.4.11, and replace the native <input type="date"> (currently Input-wrapped) in ALL THREE issue date surfaces — the create modal (2.3.3), the edit form (2.3.6), and the detail core-fields rail (2.4.2). A shared primitive, no per-surface re-implementation (the same way Combobox / TreeTable are shared).

Shape. An Input-styled trigger (selected date or placeholder + a Clear control) opening a Popover month grid. Value crosses as an ISO date string (YYYY-MM-DD) — exactly what the forms already hold — so the swap is drop-in: value + onChange(next: string | null) + disabled. Pure presentation: no queries, no Server-Action imports; the forms keep their existing commit paths (the edit form's submit, the detail rail's commit-on-close). Date math is UTC-safe (no off-by-one from local-tz parsing — the bug the ISO-string shape already guards).

A11y (load-bearing). The WAI-ARIA dialog + grid date-picker pattern (hand-rolled like Combobox / TreeTable): a labelled trigger button with aria-haspopup; a labelled dialog containing a grid of day buttons with roving focus + the 2.4.11 keyboard model; the selected day carries aria-current="date". Themed via --el-* only.

Scope guard. Single-date selection only. Date RANGES, relative presets ("in 3 days"), and time-of-day stay out of scope — no use case yet (no complexity for nothing).

Acceptance criteria

  • components/ui/DatePicker matches datepicker.mock.html (2.4.11): Input-styled trigger + Popover month grid, prev/next-month nav, selected/today states, a Clear control; value in/out is an ISO YYYY-MM-DD string (or null).
  • Replaces the native date input in the create modal, edit form, AND detail core-fields rail — one shared primitive; the forms' existing commit / validation paths are unchanged.
  • Full date-picker a11y: labelled trigger + dialog, a day grid with roving focus, arrows / PageUp-Down / Home-End / Enter / Esc keyboard; the selected day exposes aria-current="date"; a /tokens/date-picker specimen joins the STRICT shell-a11y sweep (axe-clean).
  • Colours via --el-* only; UTC-safe date math (no local-tz off-by-one).
  • Component test (happy-dom): open → navigate months → select a day → clear; keyboard day-move + select; the specimen in the strict a11y sweep.

Context refs

  • design/work-items/datepicker.mock.html + design-notes.md (2.4.11) — the layout authority
  • components/ui/Popover.tsx (anchored popover) + Input.tsx (trigger chrome) + Combobox.tsx / TreeTable.tsx (hand-rolled WAI-ARIA + roving-focus references)
  • The native date inputs to replace — CreateIssueModal (2.3.3), EditIssueForm (2.3.6), CoreFieldsPanel (2.4.2): all hold an ISO YYYY-MM-DD string today; lib/utils/datetime.ts formatDate
  • tests/e2e/shell-a11y.spec.ts + the /tokens route convention; motir-core/CLAUDE.md--el-* tokens
Status
Done
Type
Sub-task