6.7 KiB
status, system, requirements
| status | system | requirements | |
|---|---|---|---|
| draft | ui |
|
Sidebar Task Row Presentation System Design
Purpose and boundaries
The UI system owns this independent task-row presentation contract. Task and integration systems continue to own timestamps, task state, and change-request status.
This refinement changes only the compact trailing slot. It does not change saved view data, provider state, task navigation, or the full relative-time formatter used by other surfaces.
Requirement mapping
| Requirement | Design sections |
|---|---|
REQ-UI-SIDEBAR-TASK-ROW-PRESENTATION-001 |
Trailing layout, Compact elapsed time, Responsive behavior, Accessibility |
Components and responsibilities
TaskItemresolves the saved presentation and supplies the selected timestamp and trailing value.TaskItemTrailingowns the compact Git changes, relative time, change-request status, and menu layout.TaskMenuButtonkeeps the established context-menu dispatch and focus semantics.lib/i18n/formats.tsowns a sidebar-only elapsed-time formatter and its locale-aware unit tokens.app/globals.csskeeps the existing phone rule that exposes a 44 CSS pixel task action.
Trailing layout
The change-request branch uses one flex cluster. The status is the only width-bearing item while a fine-pointer row is idle. The menu wrapper has zero width and does not create a blank trailing gap.
Outer-row hover or focus expands the menu wrapper to the button width. The menu appears beside the status. The status stays mounted and keeps its pointer and keyboard disclosure behavior.
The branch omits the complete cluster when no status exists. The established menu-only fallback continues to expose task actions.
The relative-time branch keeps its overlay swap on desktop fine pointers. Replace both w-11
constraints in TaskItemTrailing with intrinsic time sizing and a 24 CSS pixel minimum matching
TaskMenuButton. Keep the time mounted and width-bearing at opacity zero during hover, focus,
and menu-open state. The absolute menu aligns to the right of the same column. This allocates
the maximum of the time width and button width without JavaScript measurement.
Keep right alignment, tabular numbers, and non-wrapping localized tokens. Different timestamps
may produce different widths; hover alone cannot. Do not restore w-full or add flex-1 to
TaskItemTitle: long titles already shrink into the available content width, while short titles
must keep their badges adjacent. Preserve the normal outer gap-2 spacing.
Compact elapsed time
The sidebar uses a dedicated formatter. It does not change formatRelativeTime, because plugins and
other product surfaces depend on full localized relative phrases.
The formatter calculates elapsed time from the selected timestamp. It clamps future clock skew to zero and floors each completed unit. It selects these buckets:
| Elapsed value | Display unit |
|---|---|
| Less than 60 seconds | seconds |
| Less than 60 minutes | minutes |
| Less than 24 hours | hours |
| Less than 7 days | days |
| Less than 365 days | weeks |
| 365 days or more | years |
The visual output contains one localized integer and one compact unit token. It never contains a
direction word or an idiomatic calendar phrase. Values above 99 years use a bounded 99+ magnitude
so the visual column remains stable.
Message-catalog keys define the six compact units for every shipped locale. This gives the UI a
stable width on system WebKit runtimes without a new Intl.DurationFormat compatibility boundary.
Invalid or empty input returns no display value. TaskItemTrailing then renders no time column and
does not reserve an empty gap.
Responsive behavior
Desktop and other fine-pointer layouts use hover and focus disclosure. The idle change-request status uses the far-right edge. The menu consumes width only while it is visible.
The phone task-switcher drawer remains the nearest shipped mobile exemplar. The row stays the primary action. The existing mobile CSS keeps the task menu visible with a 44 CSS pixel target, so touch users do not depend on hover. The change-request status remains passive on coarse pointers.
The sidebar task list remains the only scroll owner. The change does not add an overlay, safe-area boundary, or horizontal scroll region.
Below the existing 640px action breakpoint, retain the in-flow menu slot and visible 44px action. Phone and coarse-pointer time slots remain at least 44px wide and may grow for longer localized tokens, keeping the non-wrapping time separate from the action. At wider coarse-pointer widths, keep the time right-aligned within its slot and do not extend compact desktop button sizing. Scope the content-sized desktop slot to fine pointers. Test 639px, 640px, and 768px with pointer modes explicitly set.
Accessibility
The change-request status keeps its current focusable tooltip trigger. Keyboard focus can reach the status and the task menu without overlap.
The compact visual timestamp exposes the full localized formatRelativeTime result as its
accessible name. The visual token is not the only time description.
Failure behavior
A missing change-request status falls back to the menu-only branch. An invalid timestamp omits the time column. Neither case changes the saved view or reports a user-facing error.
Tests
Unit tests cover every time boundary, future clock skew, invalid input, the 99-year bound, and all shipped locales. Component tests cover idle width, hover/focus classes, status reachability, menu fallback, and accessible time semantics. Browser geometry establishes content sizing and hover stability.
Desktop Playwright coverage proves the idle status reaches the row edge and hover reveals the menu without covering the status. Mobile Playwright coverage proves the visible touch action, primary row navigation, touch-target containment, and absence of document horizontal overflow.
The sidebar title width plan owns the pending replacement of fixed desktop columns. Earlier completed plans remain historical delivery records.