git:20260722.612d761 to git:20260805.54c32e5

1 added, 1 removed. Audit A to A.

# DOX โ€” packages/client/src/components/tags
Session tag chip primitives + selectors. Shared across session card, detail header, sidebar filter. See change: add-session-tags.
| File | Purpose |
|------|---------|
- | `TagChip.tsx` | Shared chip primitive. Exports `TagChip`, `TagChipVariant`, `TagChipTone`. Variants: `user` (colorized via `tagColor`, optional remove โœ• button), `exec` (dashed/muted read-only phase chip + ๐Ÿ”’), `filter` (selectable, `tone` picks user-colorized vs dashed, `aria-pressed`, `sel` ring). `filter`+`tone=user`+`onRemove` wraps the toggle `<button>` + a sibling destructive โœ• `<button>` (`aria-label` `Remove tag <t> from all sessions`, โ‰ฅ24px hit area, ring re-homed onto wrapper; sibling โ†’ no `stopPropagation`); `exec` tone never renders the โœ•. Interactive controls are real `<button>` (keyboard + ARIA). See change: sidebar-tag-collapse-and-delete. |
+ | `TagChip.tsx` | Shared chip primitive. Exports `TagChip`, `TagChipVariant`, `TagChipTone`. Variants: `user` (colorized via `tagColor`, optional remove โœ• button), `exec` (dashed/muted read-only phase chip + ๐Ÿ”’), `filter` (selectable, `tone` picks user-colorized vs dashed, `aria-pressed`, `sel` ring). `filter`+`tone=user`+`onRemove` wraps the toggle `<button>` + a sibling destructive โœ• `<button>` (`aria-label` `Remove tag <t> from all sessions`, โ‰ฅ24px hit area; sibling โ†’ no `stopPropagation`); `exec` tone never renders the โœ•. Interactive controls are real `<button>` (keyboard + ARIA). Selected ring built by `selectionRing(on, colorized, label)` โ€” ALWAYS hosted on the toggle so it hugs the chip, wrapper draws nothing, โœ• falls outside the ring (destructive action, not selection state): 1px `outline outline-1 outline-offset-1`, color inline from `tagColor(label).text` for colorized chips (Tailwind can't class a runtime hash color); `exec` keeps `outline-current`. Wrapper-hosting was REVERTED โ€” measured 67.9ร—24 ring around a 41.9ร—19.8 chip (+28px wide, +6.2px tall; the โœ•'s โ‰ฅ24px hit area sets wrapper height) = bloated box floating off the chip. See change: sidebar-tag-collapse-and-delete, fix-selected-tag-chip-ring. |
| `TagDeleteConfirmDialog.tsx` | Confirm dialog for a destructive global tag delete. Exports `TagDeleteConfirmDialog`. Names the tag, states the cross-folder carrying-session count, warns not-undoable + reappears-if-re-added; danger action dispatches `remove_tag_globally`. testId `tag-delete-confirm`. See change: sidebar-tag-collapse-and-delete. |
| `TagEditor.tsx` | Editable strip: colorized user chips (removable) + `+ tag` popover with free-form input autocompleting over `allTags` union (new tags allowed, Enter/click commit, Esc close). Emits full new `normalizeTags`-ed array via `onChange`. Exports `TagEditor`. |
| `TagFilterGroup.tsx` | Labeled selectable filter-chip row. Exports `TagFilterGroup`. Presentational โ€” parent owns selection `Set`. Reused for sidebar "Your tags" (`tone=user`) + "Phase (read-only)" (`tone=exec`). Renders null when empty. Plain sub-label (no chevron โ€” master collapse owned by `SessionList`). `cap?` shows first N chips + `+N more`/`show less` inline expander (`tag-overflow-toggle`); `onRemove?` wires the per-chip destructive โœ• (user tone). See change: sidebar-tag-collapse-and-delete. |
| `TagStrip.tsx` | Compact read-only card strip: first `max`(3) user chips + `+N` overflow + optional read-only phase chip (openspecPhase). Exports `TagStrip`. Renders null when no tags + no phase. |
| `all-tags.ts` | Exports `allTagsInUse(sessions)` โ€” flattens every session's `tags` into a deduped sorted union. Pure; callers `useMemo` over session list. Feeds TagEditor autocomplete + sidebar filter group. |