9.6 KiB
| phase | slug | status | shadcn_initialized | preset | created |
|---|---|---|---|---|---|
| 09 | etapes | approved | false | none | 2026-05-15 |
Phase 09 - UI Design Contract
Visual and interaction contract for Phase 9. This phase adds etape controls to the existing Go/HTMX Tasks tab without redesigning the kanban.
Design System
| Property | Value |
|---|---|
| Tool | none |
| Preset | not applicable |
| Component library | local backend/internal/web/ui helpers plus Tailwind utility classes |
| Icon library | none currently used in this backend UI; do not introduce an icon package for this phase |
| Font | inherited app/system sans-serif |
Product Intent
Phase 9 should feel like an extension of the current working kanban, not a new task product. The user asked for a first functional UI now and a beautiful UI later. Keep the surface quiet, compact, and explicit.
Locked decisions from 09-CONTEXT.md:
- Etapes live in a compact top strip above the existing kanban.
- Etapes render as chips with task counts.
- Include an
Unassignedchip. - Selecting an etape filters the existing kanban.
- Status columns and task drag/drop behavior remain the primary task interaction.
- Task assignment happens in task create/edit forms.
Layout Contract
Tasks Tab Structure
TasksTabFragment must render in this order:
- Etape strip zone.
- Existing kanban board.
Use a whole-fragment swap for etape filtering so active chip state, chip counts, add-task forms, and kanban contents stay in sync.
Required outer ids/classes:
#tab-contentremains the tab switch target.#tasks-tabshould wrap the full Tasks tab fragment after Phase 9.#etape-stripshould wrap the chip strip and etape management controls.#kanban-boardremains the kanban board id.- Existing
.sortable-column,.task-card-zone, and.task-cardsemantics must remain stable.
Etape Strip
The etape strip sits directly above #kanban-board.
Visual contract:
- Horizontal flex row with wrapping:
flex flex-wrap items-center gap-2. - Bottom spacing before kanban:
mb-4. - No surrounding card, no nested card, no panel border around the whole strip.
- Chips are compact inline buttons or links, not large cards.
- Chips should not resize the kanban columns.
- Long etape titles must truncate inside the chip with
max-w-*,truncate, and visible count.
Minimum chip set:
Allchip: shows all tasks.Unassignedchip: filters tasks with no etape.- One chip per etape.
The All chip is allowed even though the user only explicitly requested Unassigned; it is the necessary return path from a filtered view.
Kanban Board
Keep the existing four horizontal columns and fixed column width.
Do not:
- split columns into etape groups,
- turn etapes into lanes,
- move status labels under etapes,
- change
TaskColumns, - place the kanban inside a decorative card.
When a filter has no tasks in a status, keep the existing empty copy style: No tasks yet.
Interaction Contract
Filtering
Chip behavior:
Allchip requests/tablos/{id}/taskswith no etape filter.Unassignedchip requests/tablos/{id}/tasks?etape=unassigned.- Etape chips request
/tablos/{id}/tasks?etape={etape_id}. - HTMX target should be
#tab-contentor#tasks-tab, not only#kanban-board, because active chip state and counts must update with the board. hx-push-urlshould keep the current filter URL shareable and refresh-safe when practical.
Active chip state:
- Active chip uses a stronger border/text/background than inactive chips.
- Active chip must be visible without relying on color alone: use both border weight/color and text weight.
Etape Create/Edit/Delete
Management controls should remain close to the strip.
Recommended first shape:
- A compact
New etapebutton at the end of the strip. - Inline create form swaps into a small strip-adjacent zone, not into the kanban columns.
- Edit/delete controls may be exposed from the active etape chip or an inline edit state; the plan may choose the simplest HTMX pattern that stays compact.
- Delete confirmation copy must make clear that tasks are kept and unassigned.
Etape reorder:
- Reordering can be implemented with explicit up/down controls or Sortable.js over the chip strip.
- If using Sortable.js, do not interfere with
.sortable-columntask drag/drop. - Reorder controls must preserve chip dimensions and avoid layout shift.
Task Assignment
Task create/edit forms must include an etape selector.
Selector contract:
- Label:
Etape. - Options include
No etape. - Existing etapes are listed by title.
- If the current board filter is a specific etape, new task forms may preselect that etape.
- If the current filter is
Unassigned, forms should default toNo etape. - If the current filter is
All, forms should default toNo etapeunless editing an assigned task.
Selector styling should match existing inputs:
- text size
text-sm, - border
border-slate-300, - rounded border,
px-2 py-1inside compact task cards orpx-3 py-2in larger forms.
Deletion
Etape delete confirmation copy:
- Heading:
Delete etape? - Body:
Tasks in this etape will stay in the tablo and move to Unassigned. - Primary destructive action:
Delete etape - Secondary action:
Keep etape
Deleting an etape must not visually remove task cards permanently from the tablo. After deletion, affected tasks should appear under Unassigned or All depending on the active filter.
Spacing Scale
Declared values are multiples of 4 and align with existing Tailwind usage.
| Token | Value | Usage |
|---|---|---|
| xs | 4px | Icon-free inline gaps, chip inner count spacing |
| sm | 8px | Chip gaps, compact form field gaps |
| md | 16px | Strip-to-board spacing, card padding, column gaps |
| lg | 24px | Existing tab content rhythm |
| xl | 32px | Not required for this compact feature |
| 2xl | 48px | Not required |
| 3xl | 64px | Not required |
Exceptions: none.
Typography
Use current app typography; do not introduce viewport-scaled text.
| Role | Size | Weight | Line Height |
|---|---|---|---|
| Body | 14px (text-sm) |
400 | default Tailwind normal |
| Label | 14px (text-sm) |
500 | default Tailwind normal |
| Compact meta/count | 12px (text-xs) |
500 | default Tailwind normal |
| Section heading | 16px (text-base) |
600 | default Tailwind normal |
| Page heading | unchanged existing page heading | unchanged | unchanged |
Chip titles should use text-sm. Counts should use text-xs or local badge styling.
Color
Use the existing slate-forward palette. Do not add a new brand accent for etapes.
| Role | Value | Usage |
|---|---|---|
| Dominant (60%) | #ffffff / bg-white |
Task cards, form surfaces |
| Secondary (30%) | #f1f5f9 / bg-slate-100; #e2e8f0 / border-slate-200 |
Column headers, chip backgrounds, borders |
| Accent (10%) | #1e293b / text-slate-800, border-slate-800 |
Active chip, active tab-like state |
| Destructive | existing danger button styles | Etape delete confirmation only |
Accent reserved for:
- active etape chip,
- selected tab/filter state,
- primary create/save actions through existing
ui.Buttondefault styling.
Do not use gradients, decorative colored strips, or a one-off etape color palette.
Copywriting Contract
| Element | Copy |
|---|---|
| Primary CTA | New etape |
| Etape title label | Title |
| Etape description label | Description (optional) |
| Empty etape strip body | No etapes yet |
| Empty etape strip action | New etape |
| Filter chip for all tasks | All |
| Filter chip for tasks without etape | Unassigned |
| Task assignment label | Etape |
| Task assignment empty option | No etape |
| Etape title validation | Title is required |
| Etape delete heading | Delete etape? |
| Etape delete body | Tasks in this etape will stay in the tablo and move to Unassigned. |
| Etape delete action | Delete etape |
| Etape delete cancel | Keep etape |
| Generic server error | Something went wrong. Please try again. |
Avoid explanatory UI text about keyboard shortcuts, implementation, or how filtering works. The chip labels and active state should carry the interaction.
Accessibility Contract
- Chips must be real links or buttons.
- Active chip must include
aria-current="true"when rendered as a link. - Delete/edit controls must have task- or etape-specific
aria-labelvalues when the visible label is short. - Form labels must be associated with inputs via
for/idor an equivalent explicit label pattern. - Count badges must remain readable as text, not only visual badges.
- Focus styles must remain visible through existing browser/Tailwind focus treatment.
HTMX Swap Contract
Preferred fragment boundaries:
- Filtering: swap
#tasks-tabor#tab-content. - Etape create/edit/delete: swap a dedicated etape strip/form zone and include out-of-band updates if counts or board contents change.
- Task create/update: preserve current
.task-card-zoneand add-task slot behavior. - Reorder: preserve
#kanban-boardas the task reorder response target.
Any response that changes etape assignment or etape deletion should update chip counts. Whole Tasks-tab swap is acceptable for the first version.
Registry Safety
| Registry | Blocks Used | Safety Gate |
|---|---|---|
| shadcn official | none | not required |
| third-party registry | none | do not use |
Checker Sign-Off
- Dimension 1 Copywriting: PASS
- Dimension 2 Visuals: PASS
- Dimension 3 Color: PASS
- Dimension 4 Typography: PASS
- Dimension 5 Spacing: PASS
- Dimension 6 Registry Safety: PASS
Approval: approved 2026-05-15