# Task Form Dialog — keyboard + header polish — Design **Date:** 2026-05-14 **Scope:** adiuvAI renderer (`src/renderer/components/tasks/TaskFormDialog.tsx`) + supporting libs **Status:** Approved by user (mockup at `docs/mockups/2026-05-14-task-form-dialog-mockup.html`), ready for implementation plan ## Goal Port three UX features shipped in the timeline batch-add `AddEventDialog` (`docs/2026-05-08-task-ux-evolution-design.md` § timeline batch) into `TaskFormDialog`: 1. **Header style** — `DialogTitle` + `DialogDescription` (no separator border), matching `AddEventDialog`. 2. **Full keyboard navigation** — Tab/Shift-Tab between fields & pills, arrow keys within pills row, Enter to open focused pill, arrow keys inside list popovers + calendar, Esc to close popover. 3. **Date + time via keyboard** — replace the Calendar + 2× hour/minute `Select` triplet with a typeable `DateField` that supports an optional `HH:MM` suffix and respects `FormatPrefs.dateFormat`. ## Non-goals - Migrating `TaskFormDialog` to a Sheet (deferred — see `docs/2026-05-08-task-ux-evolution-plan.md`). - Touching `NewTaskDialog` / `EditTaskDialog` wrappers (no behavior change). - Changes to other property popovers' rendering beyond keyboard handling. - Inline project creation flow (`InlineProjectForm`) — unchanged. ## 1. Header Replace the current minimal header: ```tsx {...} ``` with the `AddEventDialog` style: ```tsx {mode === 'create' ? t('tasks.newTask') : t('tasks.editTask')} {mode === 'create' ? t('tasks.newTaskDescription') : t('tasks.editTaskDescription')} ``` **No border-bottom** under the header — body flows directly under it. Keep the existing `bg-card/92 backdrop-blur-xl` overlay on `DialogContent`. New i18n keys (all 5 languages): `tasks.newTaskDescription`, `tasks.editTaskDescription`. ## 2. Keyboard navigation ### Pills row — roving focus + arrow movement The property pills (`Project · Priority · Status · Due · Assignees`) become a roving-tabindex group: - Only one pill at a time has `tabindex={0}`; the rest have `tabindex={-1}`. Default focused pill = first (Project). - `Tab` / `Shift+Tab` enters/exits the group as a single stop. Inside the group, `Tab` exits forward to the footer; on entry from the footer-side, focus restores to the last-focused pill. - `ArrowRight` / `ArrowDown` → next pill (clamped at end). - `ArrowLeft` / `ArrowUp` → previous pill (clamped at start). - `Home` / `End` → first / last pill. - `Enter` or `Space` on focused pill → open its popover. Implementation: a small hook `useRovingFocus(ref, count)` returning `(index) => { tabIndex, onKeyDown, onFocus }`. Pills consume it inside `PropertyPill` (kept presentational) via a wrapping `