5.4.8 `MultiSelectPicker` primitive + Labels & Components rail cards (chips, create-row, caps; the Epic-6-reusable control)
Estimate: 35m · Depends on: 5.4.2, 5.4.3, 5.4.6
The issue-view assignment UI. Two pieces, per the 5.4.6 design:
components/ui/MultiSelectPicker — the generic chip-input primitive the design specifies (value chips + remove ×, type-to-filter input, anchored aria-multiselectable listbox on the OptionRow vocabulary, full keyboard model incl. Backspace-removes-last, optional create-row via an onCreate prop, optional per-value cap, optional per-value tint — chip colour + the option-row swatch dot). PURE + typed-generic (options in, selection out — no fetching), component-tested in isolation, documented for Epic-6 facet reuse. This is the ONE new primitive the story earns (rung-2: nothing multi-select exists; designed in 5.4.6 — not improvised).
Rail cards (in CoreFieldsPanel/siblings, the FieldCard grammar): Labels — the picker with onCreate wired to the folksonomy (typed no-spaces/cap errors inline), options from the bounded searchLabels autocomplete (debounced), chips from the detail read, tinted by the deterministic name-hash (FNV-1a over nameLower mod 6 → the six --el-tint-* pastels, --el-text-strong text — the Story 5.4 label-colour deviation; the pure helper lives beside the picker for Epic-6 reuse); Components — the picker without create (options = listComponents, the empty-project state with the admin link). Both persist via server actions → the 5.4.2/5.4.3 services → router.refresh() (the rail pattern); viewer renders read-only chips. Strings via next-intl.
Acceptance criteria
MultiSelectPickermatches the 5.4.6 design (every keyboard/visual state), is axe-clean standalone, pure, and component-tested (toggle/create/cap/Backspace paths); no fetching inside.- The Labels card round-trips create/add/remove with the inline 422s; autocomplete is debounced + bounded; case-insensitive match surfaces the existing casing; the same label renders the same hash tint everywhere (deterministic — unit-tested).
- The Components card assigns/unassigns from the project taxonomy; empty-project + read-only states match the design.
- Token tiers only; the detail-route axe sweep stays clean; integration tests over both cards; coverage ≥90%.
Context refs
design/work-items/labels-components-watch.mock.html+ notes (5.4.6) — THE authority- 5.4.2/5.4.3 services + routes;
CoreFieldsPanelFieldCard+ the rail action pattern IssueFilterBarOptionRow +Comboboxinternals (the listbox/a11y vocabulary to reuse)- The i18n threading pattern (en byte-identical)