docs: plan color changes for multi-selected tasks (#3829)

This commit is contained in:
José Almeida
2026-09-23 16:26:35 +01:00
committed by GitHub
parent cb9a93c574
commit 25633de627
4 changed files with 453 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
---
status: draft
---
# Bulk task colors
## Outcome and scope
Add personal Color actions to the sidebar bulk menu and board selection toolbar.
Reuse existing palette, persistence, and automatic-rule precedence. Phone users
perform the same operation from board selection. This package stops at design;
implementation requires a later explicit request. No production code changed.
## Sources
- [Requirements](../../specs/ui/requirements/bulk-task-colors.md): REQ-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006, draft extension.
- [System design](../../specs/ui/system-design/bulk-task-colors.md#bulk-manual-color-editing): draft bulk design extending the current personal-color contract.
- [ADR 0041](../../decisions/0041-backend-owned-portable-user-settings.md): reuse portable personal settings ownership; no new ADR needed.
## Work package
| Order | Work order | Status | Dependencies |
| --- | --- | --- | --- |
| 1 | [Task 01: Bulk color editing](task-01-bulk-color-editing.md) | pending | None |
One vertical slice, sequential execution. No subagents are authorized.
Estimated implementation and targeted checks: 3-5 hours, subject to E2E setup.
## ASCII UI preview
UI-01: Desktop sidebar selected-row menu and board toolbar, idle state.
```text
Sidebar: 3 selected Board: 3 selected
+--------------------+ [Move to] [Color v] [Archive] [Delete] [Clear]
| Pin 3 tasks | +----------------------+
| Color > | | Color for 3 tasks |
+--------------------+ | Red |
| Orange |
| Yellow |
| Green |
| Blue |
| Purple |
| Pink |
| None |
+----------------------+
```
UI-02: Phone board selection and expanded color picker.
```text
Before selection, above the board:
[Select tasks]
In selection mode: [Cancel selection]
Fixed selection bar, above safe area:
[3 selected] [Color] [Actions] [Clear]
Inset picker:
+--------------------------------+
| Color for 3 tasks [Close] | <- fixed title
| Automatic rules may override |
| the visible color. |
|--------------------------------|
| Red | <- one scrolling list
| Orange |
| Yellow |
| Green |
| Blue |
| Purple |
| Pink |
| None |
+--------------------------------+
```
UI-03: Save states (same targeting across viewports).
```text
Saving: [Color: Saving...] (disabled)
Failure: Could not save colors. Try again.
Partial: Colors saved for 500 of 501 tasks. Try again for the rest.
```
Required structure: a visible color entry, named options, mixed-state accuracy,
selection retained after dismissal/save, and a contained touch surface. A common
value has a check; mixed values have no checked color. Phone Actions contains
existing move/archive/delete actions. Empty selection hides the toolbar.
Spacing and English labels are illustrative; implementation uses shared tokens
and localized copy. Map UI-01/02 to AC-006.1 through .4 and .6; UI-03 to .5/.7,
where AC-006 abbreviates AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.
## Verification strategy
Task 01 defines exact unit, component, desktop/mobile E2E, localization, and
specification commands. Existing backend multi-key patch behavior is reused.
Test actual persisted colors and unaffected tasks, not just menu visibility.
Validate phone geometry at 393px and toolbar composition on either side of
768px. Capture a phone screenshot during the focused E2E run.
## Risks and exclusions
- Concurrent optimistic writes must preserve newer and unrelated changes.
- Large selections require sequential bounded patches and explicit partial failure.
- Board colors reuse personal sidebar markers; no new board card styling.
- No new mobile task-switcher multi-selection, automatic-rule changes, custom
palette, task API, database migration, or live cross-browser guarantee.
## Documentation
/docs-maintainer assessment: this turn changes design only, so public docs stay
unchanged. Implementation adds a short how-to section to the existing task guide
chosen from docs/public after searching current task navigation documentation.
## Results
Review remediation: add an explicit phone selection trigger and move the new
contract into draft artifacts, preserving the shipped personal-color specs.
Document catalog validation, all 36 specification-linter tests, full specification
lint, and diff whitespace validation passed after these corrections.
Implementation and rendered verification remain pending.
@@ -0,0 +1,192 @@
---
id: "01-bulk-color-editing"
title: "Apply personal colors to multi-selected tasks"
status: pending
wave: 1
depends_on: []
plan: "plan.md"
requirements:
- REQ-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006
acceptance_criteria:
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.1
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.2
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.3
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.4
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.5
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.6
- AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.7
system_design:
- ../../specs/ui/system-design/bulk-task-colors.md
---
# Task 01: Bulk color editing
## Summary
Deliver bulk manual-color editing end to end using the current personal settings
patch API. Extend the existing single-task color path and both selection surfaces.
## In scope
- Batch mutation, optimistic reconciliation, bounded chunks, pending/error state.
- Shared palette for sidebar bulk menu and board toolbar, with mobile picker
and an explicit phone Select tasks / Cancel selection entry point.
- Localization, focused regression tests, and public task-guide instructions.
## Out of scope
New shared task fields, automatic-color priority changes, new board markers,
mobile sidebar selection mode, or unrelated selection refactoring.
## Acceptance
1. All seven linked criteria pass on the intended desktop/phone surfaces, with
existing single-task and bulk destructive actions preserved.
2. Bulk requests use one patch per 500 IDs or fewer; selected IDs are captured,
unselected settings survive, and stale/failed responses preserve newer edits.
3. Focused tests prove persistence, clearing, mixed state, automatic precedence,
retry, and touch geometry; the public how-to explains the entry points.
## ASCII UI preview
UI-01: Desktop sidebar selected-row menu and board toolbar, idle state.
```text
Sidebar: 3 selected Board: 3 selected
+--------------------+ [Move to] [Color v] [Archive] [Delete] [Clear]
| Pin 3 tasks | +----------------------+
| Color > | | Color for 3 tasks |
+--------------------+ | Red |
| Orange |
| Yellow |
| Green |
| Blue |
| Purple |
| Pink |
| None |
+----------------------+
```
UI-02: Phone board selection and expanded color picker.
```text
Before selection, above the board:
[Select tasks]
In selection mode: [Cancel selection]
Fixed selection bar, above safe area:
[3 selected] [Color] [Actions] [Clear]
Inset picker:
+--------------------------------+
| Color for 3 tasks [Close] | <- fixed title
| Automatic rules may override |
| the visible color. |
|--------------------------------|
| Red | <- one scrolling list
| Orange |
| Yellow |
| Green |
| Blue |
| Purple |
| Pink |
| None |
+--------------------------------+
```
UI-03: Save states (same targeting across viewports).
```text
Saving: [Color: Saving...] (disabled)
Failure: Could not save colors. Try again.
Partial: Colors saved for 500 of 501 tasks. Try again for the rest.
```
Required structure: a visible color entry, named options, mixed-state accuracy,
selection retained after dismissal/save, and a contained touch surface. A common
value has a check; mixed values have no checked color. Phone Actions contains
existing move/archive/delete actions. Empty selection hides the toolbar.
Spacing and English labels are illustrative; implementation uses shared tokens
and localized copy. Map UI-01/02 to AC-006.1 through .4 and .6; UI-03 to .5/.7,
where AC-006 abbreviates AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.
Full combined preview: [plan](plan.md#ascii-ui-preview).
## Implementation sequence and tests
Use /tdd: first reproduce absent bulk Color behavior and write failing tests.
Extend use-task-color tests for one/many IDs, duplicates, empty input, null,
500/501 IDs, partial failure, unrelated settings, separate hook instances,
overlapping single and bulk edits, newer settings events, and stale responses.
Component tests cover selected versus unselected context targets, mixed values,
None enablement, preserving selection, pending state, and palette labels.
Add task/bulk-task-colors.spec.ts for sidebar and board entry points, persistence
across reload, clearing, unselected controls, and automatic-rule precedence.
Add kanban/mobile-bulk-task-colors.spec.ts starting with zero selection. Tap the
new Select tasks control, select cards without modifiers, cancel and re-enter,
then choose and clear a color, verify stored values and sidebar markers on reload,
44px targets, focus return, contained drawer, and no horizontal overflow.
Exercise phone Actions to preserve existing bulk actions; verify just below and
above 768px without rewriting saved desktop preferences. Use causal waits.
## Verification
From repo root; install dependencies first if this checkout lacks apps/node_modules.
The E2E runner builds artifacts by default; do not pass --no-build.
New test paths below are outputs of this work order.
```bash
(cd apps && pnpm install --frozen-lockfile)
(cd apps/web && pnpm exec vitest run hooks/use-task-color.test.tsx hooks/use-task-color-migration.test.tsx components/task/task-switcher-context-menu.test.tsx components/task/task-switcher-color-menu.test.tsx components/kanban/task-multi-select-toolbar.test.tsx)
(cd apps/web && pnpm run typecheck)
(cd apps/web && pnpm exec eslint hooks/use-task-color.ts components/task/task-switcher-color-menu.tsx components/task/task-switcher-context-menu-items.tsx components/kanban/task-multi-select-toolbar.tsx components/kanban-board.tsx)
(cd apps/web && pnpm run i18n:check)
(cd apps/web && pnpm e2e:run --project chromium -- tests/task/bulk-task-colors.spec.ts tests/task/sidebar-multi-select.spec.ts tests/task/sidebar-task-color-sync.spec.ts tests/kanban/task-multi-select.spec.ts)
(cd apps/web && pnpm e2e:run --project mobile-chrome -- tests/kanban/mobile-bulk-task-colors.spec.ts tests/task/mobile-sidebar-task-color-sync.spec.ts)
python3 scripts/list-docs.py validate
python3 scripts/lint-spec-files.test.py
python3 scripts/lint-spec-files.py --all
git diff --check
```
Use the existing i18n:zh-hant generator for the Traditional Chinese pair when
new locale keys are required. Lint every additional implementation file introduced
by extraction. Run E2E projects sequentially; do not override worker budgets.
## Files likely touched
- apps/web/hooks/use-task-color.ts and use-task-color.test.tsx
- apps/web/components/task/task-switcher-color-menu.tsx and new companion test
- apps/web/components/task/task-switcher-context-menu-items.tsx and existing task-switcher-context-menu.test.tsx
- apps/web/components/kanban-board.tsx (phone selection entry point)
- apps/web/components/kanban/task-multi-select-toolbar.tsx and new companion test
- apps/web/components/task/mobile/mobile-picker-sheet.tsx (reuse; modify only if required)
- apps/web/src/locales/{en,pt-pt,zh-cn,zh-hk,zh-tw}/ task and kanban catalogs as needed
- apps/web/e2e/tests/task/bulk-task-colors.spec.ts (new)
- apps/web/e2e/tests/kanban/mobile-bulk-task-colors.spec.ts (new)
- docs/public/ task guide selected during implementation
## Dependencies
None. Reuse existing personal settings API and automatic-color requirements.
## Risks
Cross-instance optimistic mutation races, settings capacity rejection, portaled
menu focus, and mobile toolbar overflow. Do not solve concurrency by overwriting
the whole settings map or changing automatic-color precedence.
## Parallelism
sequential
## Inputs
Owning requirement/design links in frontmatter, AGENTS.md and apps/web/AGENTS.md,
existing use-task-color tests, sidebar-multi-select E2E, task-multi-select E2E,
and mobile-sidebar-task-color-sync E2E.
## Results
Pending. Record each command result and rendered phone comparison after execution.
@@ -0,0 +1,37 @@
---
status: draft
system: ui
created: 2026-09-19
owners:
- kandev
---
# Bulk task colors requirements
## Overview
Apply one personal manual color to multiple selected tasks. UI owns this
presentation preference; shared task records remain unchanged. This draft
extends [personal task colors](sidebar-automatic-task-colors.md), whose
palette, persistence, and automatic-rule precedence remain authoritative.
## Requirements
### REQ-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006: Multi-selected manual colors
**Intent:** Apply one personal manual color to selected tasks without repeating the action for each task.
#### Acceptance criteria
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.1:** The sidebar multi-selection actions and board selection toolbar shall offer Color for the selected task set, including selections spanning workflows. Opening a sidebar menu on an unselected task shall retain its single-task targeting behavior.
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.2:** Choosing one of the existing seven manual colors shall apply it to exactly the selected tasks captured when the choice is made. Choosing None shall clear their manual colors. Unselected tasks and automatic rules shall remain unchanged.
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.3:** The picker shall identify a common manual value only when every selected task has that value. Mixed values shall show no checked color. None shall be enabled when any selected task has a manual color. Empty selection shall offer no actionable color control.
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.4:** Applying or cancelling a color choice shall preserve task selection and the active task. A successful change shall remain after reload. Automatic colors shall retain their existing precedence, explained in the picker.
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.5:** During saving, the initiating color control shall prevent duplicate submission and expose saving state. Failure shall show a localized error and restore failed changes to the latest confirmed values without reverting newer edits or unrelated settings. Selection shall remain available for retry.
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.6:** Phone users shall have a visible Select tasks control, available before any task is selected, to enter selection mode and select multiple board tasks and apply or clear a color through a visible touch control and a viewport-contained picker. Color options shall have text labels, keyboard support, dismissal with focus return, and touch targets of at least 44 CSS pixels. The document shall not scroll horizontally.
- **AC-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006.7:** Selections larger than one persistence request shall be processed without silent truncation. If saving stops partway, confirmed changes shall remain, unsaved changes shall be restored, and the user shall see how many tasks were saved and that retry is available.
## Out of scope
New task color fields, automatic-rule precedence changes, custom palettes,
board-card markers, and mobile task-switcher multi-selection.
@@ -0,0 +1,104 @@
---
status: draft
system: ui
requirements:
- REQ-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006
---
# Bulk task colors system design
## Requirement mapping
| Requirement | Design section |
| --- | --- |
| `REQ-UI-SIDEBAR-AUTOMATIC-TASK-COLORS-006` | [Bulk manual color editing](#bulk-manual-color-editing) |
## Bulk manual color editing
This draft extends the [current personal-color design](sidebar-automatic-task-colors.md).
Delivery is tracked in the
[bulk color plan](../../../plans/bulk-task-colors/plan.md). UI remains the owner
because colors are personal presentation preferences, not shared task metadata.
### Selection and surfaces
`BulkSelectionMenuItems` in `task-switcher-context-menu-items.tsx` adds Color
beside Pin in its mark group, using the existing `actingIds` targeting rule.
The mark group must remain visible when pin callbacks are absent. Single-task
menus retain their existing targeting and automatic-source explanation.
`TaskMultiSelectToolbar` adds Color for its `selectedIds`; mixed workflows do
not disable it. No new task color markers are introduced on board cards.
Generalize the palette in `task-switcher-color-menu.tsx` to accept a task-ID
set and share its selection/value derivation with a toolbar picker. Deduplicate
IDs and capture an immutable set at option activation. Do not derive targets
from the active task or reuse workflow-move eligibility. A personal color does
not require a workflow or mutate task lifecycle. Existing selection cleanup
removes stale rows; an empty target set is a no-op. No descendant expansion.
Read manual values from `sidebarTaskColors`, treating absent and null as None.
Check a color only for a unanimous non-null value. Mixed state checks nothing;
None is disabled only when all values are empty. Keep selection after submit.
### Mutation and recovery
Extend the existing `useSetTaskColor` mutation implementation with a batch entry
point; keep the single-task API delegating to the same mutation path. Do not
call the single-task setter once per ID. For up to 500 unique IDs send one
`sidebar_task_color_patch` with `if_missing: false`; clearing uses null entries.
For larger sets, send sequential chunks of at most 500 IDs. The existing backend
validation, CAS merge, settings response, and personal authorization apply.
No new endpoint, task mutation, migration, or settings key is needed.
Expose pending state and a completion result to the picker. Apply optimistic
colors for the captured IDs. Serialize this operation's chunks, track confirmed
chunks, and stop after the first error. Reconcile responses through the existing
settings mapper and revision guards. Restore only this operation's outstanding
optimistic entries, preserving later per-ID changes and unrelated settings;
a whole-map rollback must not overwrite concurrent edits. Tests must cover
separate hook instances, late responses, a settings event during saving, and
single-task edits overlapping a batch. Keep a confirmed baseline per affected
ID rather than assuming a local optimistic value is confirmed.
After partial failure, retain successful chunks, restore failed/unattempted
entries, report saved and remaining counts, and allow the same selection to
retry. Reapplying a color is idempotent. Existing total settings capacity errors
use this failure path. Pending state prevents duplicate submission from the
initiating picker; it does not globally lock unrelated settings controls.
### Phone composition and accessibility
Add a phone-visible Select tasks button in `kanban-board.tsx`, immediately
above `KanbanSwimlanes`, independently of the hidden `SwimlaneHeader`. Wire it
to the existing `multiSelect.toggleMultiSelect` action. It remains reachable
with zero selected tasks and changes to Cancel selection while selection mode
is active. Cancel exits through the existing selection reset; tapping task
cards in selection mode uses the existing toggle behavior, without navigating.
The button has a localized label, an accessible pressed state, and a 44px touch
target. Cover entering, cancelling, and re-entering with zero selected tasks in
phone E2E before testing any color action. No modifier key or long press is
required. The board toolbar below
768px becomes a safe-area-aware compact row with selected count, Color, Actions,
and Clear. Existing move/archive/delete actions remain reachable inside Actions;
desktop keeps its inline actions. This prevents the added control widening the
phone viewport. Preserve desktop preferences across breakpoint changes.
Color opens a short inset `MobilePickerSheet`, the nearest shipped picker
exemplar. Its fixed title gives the selected count and its single scrolling
body contains the seven labeled colors and None. Reuse its dynamic-height bound
and bottom safe-area padding. Desktop uses an anchored menu. Tablet/coarse
pointer controls retain 44px targets and contained menus; desktop ordinary
buttons retain 28px sizing. Dismissal performs no write and returns focus.
Do not add multi-selection to the separate mobile task-switcher drawer in this
package: the phone board is the equivalent multi-task entry point.
Show localized guidance that automatic rules can override the visible manual
color. Reuse existing palette translations; new count, mixed, saving, and error
copy must cover all five locales, with proper plural forms. Tests exercise
keyboard choice, touch choice, persistence, and actual rendered geometry.
## Dependencies
Reuse the existing personal-color backend settings patch, revision guards,
validation limits, and authorization documented in the linked current design.
[ADR 0041](../../../decisions/0041-backend-owned-portable-user-settings.md)
continues to own portable settings persistence. No new backend API is proposed.