Skip to content

feat(wardrobe): silo the catalog kinds by tab (gh-#393) - #473

Merged
genwave-radio merged 2 commits into
mainfrom
feat/gh-393-wardrobe-tabs
Aug 12, 2026
Merged

feat(wardrobe): silo the catalog kinds by tab (gh-#393)#473
genwave-radio merged 2 commits into
mainfrom
feat/gh-393-wardrobe-tabs

Conversation

@genwave-radio

Copy link
Copy Markdown
Collaborator

Closes #393.

🎯 What

The Wardrobe grows from the font-packs-only listing into everything installed off the Community Catalog, siloed by kind: Personas | Themes | Fonts | Shows — one URL-driven tab each (?tab=, the CatalogTabs idiom), and every tab renders even when empty (per the issue: an empty kind gets its own empty state, never a hidden tab).

🧵 How

  • 🧩 components/ui/tab-strip.tsx — new shared TabStrip: CatalogTabs and BoothLogTabs were byte-identical modulo tab defs (each even says so in its docstring); both now wrap the one implementation, and the Wardrobe (and feat: Tabs for different catalog kinds #372's shelf tabs next) reuse it instead of minting a fourth copy. The gh-Theme catalog detail: no installed-state or provenance (parity with the font-pack polish) #375 Chip extraction precedent, applied to tabs.
  • 👖 Fonts tab — the original WardrobeClient cards, untouched (faces, licence line, uninstall). font-pack-wardrobe.spec.tsx passes unchanged.
  • 🎙️ Personas / 🎨 Themes / 📻 Shows tabs — a shared read-only InstalledEntriesList: name, optional secondary line (show tagline), and the kind's own provenance verb (Hired for personas per F90.7/T105, Imported for themes/shows). Only genuinely-imported rows (importedFrom != null) — the same two-provenance-class rule the catalog page's fetchers follow; authored personas/shows stay on their own pages. Deliberately action-free: retire/remove/delete flows live on each kind's own page.
  • 🔌 Data: personas/shows off their listings; themes derived from Station:Theme choices on the existing GET /api/settings read (the documented no-/api/themes posture), which also serves the catalog-enabled signal for the empty-state CTA swap. A failed source shows a load error on its own tab only — the strip stays navigable.

🧭 Choice worth flagging

Default tab (/wardrobe bare) is now Personas — shelf kind order. If muscle memory says fonts-first, it's a one-line flip in WardrobeTabs.

🧪 Tests

New wardrobe-tabs.spec.tsx (resolver, strip, listing, empty-state CTA swap). Full admin-ui: 100 suites / 971 tests ✅ · tsc --noEmit ✅ · next build

The Wardrobe grows from the font-packs-only listing into every kind
installed off the Community Catalog: Personas | Themes | Fonts | Shows,
one URL-driven tab each (?tab=), every tab present even when empty per
Dean's ruling on the issue. Fonts keep their original WardrobeClient
cards (faces, licence, uninstall); the other kinds render a shared
read-only InstalledEntriesList — name, optional secondary line, and the
kind's own provenance verb (Hired / Imported) — admitting only
genuinely-imported rows (importedFrom != null), never authored ones.

The tab strip itself is extracted to components/ui/tab-strip.tsx:
CatalogTabs and BoothLogTabs were byte-identical modulo tab defs and now
wrap the one shared TabStrip, so gh-#372's shelf tabs can reuse it too
instead of minting a fourth copy.
@genwave-radio
genwave-radio merged commit c41b92d into main Aug 12, 2026
11 checks passed
@genwave-radio
genwave-radio deleted the feat/gh-393-wardrobe-tabs branch August 12, 2026 10:07
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Tabs in Wardrobe for different kinds

1 participant