* fix(v3): promote Virtuoso to the first-class sidebar slot (was slopscale)
The bundled practice plugin was rebranded/re-homed from the SlopScale fork
(id: slopscale) to feedback-plugin-virtuoso (id: virtuoso); the desktop
bundle swap is feedBack-desktop#31. shell.js still promoted `slopscale`,
whose id no longer ships, so renderPromotedNav() (gated on the plugin
appearing in /api/plugins) would find no match: the dedicated sidebar slot
goes dark and Virtuoso drops to the generic Plugins gallery.
Swap the NAV entry + PROMOTED_PLUGINS slot slopscale -> virtuoso
(screen: plugin-virtuoso, label "Virtuoso - Practice", same FeedBarcade
anchor + target icon) so the practice plugin keeps its first-class entry.
Same pattern as the editor promotion (#546). Must land with the bundle swap
or the practice plugin regresses in the UI.
Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(v3): clear dead slopscale id from Plugins gallery + refresh docs
Review follow-up (topkoa) — same dead-id bug class on a second surface:
- static/v3/plugins-page.js: drop the now-dead `slopscale: 'game'` from the
CURATED category map and add `virtuoso: 'practice'`. The Virtuoso manifest
sets `category: "practice"` (authoritative in categoryOf), so it already
lands on the practice board; the curated entry is a defensive fallback so a
manifest without `category` wouldn't drop to 'other'.
- README.md: SlopScale row -> Virtuoso (new repo URL + description + clone).
- docs/plugin-capability-inventory.md: slopscale row -> virtuoso (Active).
No behavior change beyond gallery categorization for the dead id.
Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-authored-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The topbar search (#v3-search) rendered on every screen and, on the library
screen, was hidden behind the filter toolbar while scrolling (both were
sticky top-0 z-20 in the #v3-main scroller).
- shell.js: wrap the search in #v3-search-wrap (hidden by default) and toggle
it in syncActive() so it only shows on #v3-songs; bump the topbar to z-30 so
it always sits above the toolbar.
- songs.js: drop the toolbar's top-0 and pin it beneath the topbar by measuring
the topbar height (positionToolbar). A ResizeObserver on #v3-topbar keeps the
offset correct as the topbar height changes (viewport width, search show/hide)
and fixes the initial position regardless of render()/syncActive() ordering.
Fixes#559
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Arrangement Editor plugin was only reachable via the generic Plugins
gallery. Give it a dedicated sidebar entry (Library group, below Songs)
through the existing PROMOTED_PLUGINS mechanism in shell.js — a NAV entry,
a promoted slot anchored after "songs", and an edit icon.
renderPromotedNav already gates each promoted slot on the plugin being
present in /api/plugins, so the entry shows only when the editor is
installed. The displayed label comes from the plugin manifest's nav.label.
Signed-off-by: topkoa <topkoa@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Rename the user-visible label of the HOME-group nav entry (and the matching
"Open Shop →" button on the progress page) from "Shop" to "Unlockables".
Internal identifiers (nav key 'shop', screen id v3-shop, window.v3Shop) are
left unchanged so wiring/state are unaffected.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the per-plugin sidebar list down to the single "Plugins" entry
(the gallery is the one entry point for general plugins) and give two
bundled plugins their own first-class sidebar slots instead:
- SlopScale (manifest label "SlopScale - Practice"), directly under FeedBarcade
- Rig Builder, directly after the Library group
Both are driven by a PROMOTED_PLUGINS table: each slot is anchored after
a nav key and filled by renderPromotedNav() only when the plugin is
present in /api/plugins, so an absent bundle shows nothing rather than a
dead entry that bounces to the Plugins screen. The visible label uses the
plugin's own manifest nav.label (escaped), falling back to the static NAV
label.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>