# 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 `