Exploratory issue — surfaced from the #952 plan-approval discussion. The plan-approval gate for the current feature picks one pattern for its own use; this issue's job is the broader question — should the whole extension converge on one toggle pattern?
Problem — two patterns coexist by accident
The VSCode extension has accumulated several view-state toggles, each currently implemented as a two-command swap: two distinct commands with two distinct icons, the when-clause on each entry chooses which is visible based on current state. The icon shows the target action (what clicking will do), not the current state.
Known instances of this pattern today (post-#952 shipping):
| Toggle |
Commands |
Icons (off → on target) |
Setting backing it |
| Backlog mine vs all |
codev.showBacklogMineOnly / codev.showBacklogAll |
$(eye) / $(eye-closed) |
codev.backlogShowAll |
| Builders file view list vs tree |
codev.enableBuildersFileTreeMode / codev.disableBuildersFileTreeMode |
$(list-tree) / $(list-flat) |
codev.buildersFileViewAsTree |
| Builders group-by area vs phase (landing in #952) |
codev.setBuildersGroupByArea / codev.setBuildersGroupByPhase |
$(tag) / $(milestone) |
codev.buildersGroupBy |
(There may be others — first task in any plan here is an audit.)
The alternative is VS Code's built-in toggled menu property: one fixed button at a fixed position, one fixed icon, with a pressed / highlighted visual state that reflects the current setting. Click flips the setting; the button's appearance updates to show "this is active." Native VSCode views use this pattern heavily (Source Control's "View as Tree/List", Outline's filter toggles, etc.).
The tradeoff (the design call)
Two-command swap (current pattern):
- ✅ Per-state icons — visually distinct icon for each side of the toggle, so the user sees what they'll get if they click
- ✅ Matches the convention already in use in this extension (familiarity for current users)
- ✅ Fits cases where the two states have intrinsically different semantics (e.g. mine vs all isn't "more / less" — it's two different filters)
- ❌ Two commands per toggle to maintain (titles, when-clauses, palette entries can drift)
- ❌ Button visually "moves" between two icons depending on state — a glance doesn't tell you which mode you're in without recognising both icons
Single-button toggled (the alternative):
- ✅ One command per toggle, simpler config
- ✅ Native VSCode pattern — engineers using other extensions / VSCode itself will recognise it
- ✅ The button position is fixed, which reduces "where did that go?" moments after a toggle
- ✅ Current state is visually obvious (pressed / unpressed)
- ❌ Only one icon — can't visually distinguish what the other state would look like
- ❌ Some toggles' two states aren't naturally "on / off" (mine-vs-all again — toggled-mine = "filtered to me" is a fine read, but toggled-all = "showing everything" is the off state which is semantically the more permissive mode, mildly confusing)
Questions the plan-gate should answer
- Audit first. What's the full list of toggles in
packages/vscode/? Three are known; an honest count may reveal more (status-bar toggles, dev-server start/stop is not one, but accordion-mode might be).
- One pattern, or mixed? Is the goal to converge to a single pattern across all toggles, OR is the answer "use swap when states are semantically distinct (mine vs all), use toggled when states are naturally on/off (auto-collapse enabled)"? A mixed answer is defensible but needs criteria, not just case-by-case.
- Which toggles, if any, are bad fits for the chosen pattern? Some toggles may be intrinsically swap-shaped (the per-state icon carries information the user needs); the conversion should respect that.
- Migration cost. Converting an existing toggle changes which setting key writes happen, which palette entries appear, and how custom keybindings resolve. Are any existing keybindings widely-bound in a way that the change would break user muscle memory?
- Discoverability tradeoff. Native
toggled pattern is more discoverable for VSCode-native users; swap pattern is more discoverable in the abstract (you can see both states' icons in the title bar... no wait, you can only see one at a time). The discoverability argument may favour toggled.
What this isn't
Acceptance (loose pending plan-gate)
Related
- #952 — the Builders group-by toggle that surfaced this question; ships as a swap to match today's convention.
Problem — two patterns coexist by accident
The VSCode extension has accumulated several view-state toggles, each currently implemented as a two-command swap: two distinct commands with two distinct icons, the
when-clause on each entry chooses which is visible based on current state. The icon shows the target action (what clicking will do), not the current state.Known instances of this pattern today (post-#952 shipping):
codev.showBacklogMineOnly/codev.showBacklogAll$(eye)/$(eye-closed)codev.backlogShowAllcodev.enableBuildersFileTreeMode/codev.disableBuildersFileTreeMode$(list-tree)/$(list-flat)codev.buildersFileViewAsTreecodev.setBuildersGroupByArea/codev.setBuildersGroupByPhase$(tag)/$(milestone)codev.buildersGroupBy(There may be others — first task in any plan here is an audit.)
The alternative is VS Code's built-in
toggledmenu property: one fixed button at a fixed position, one fixed icon, with apressed/ highlighted visual state that reflects the current setting. Click flips the setting; the button's appearance updates to show "this is active." Native VSCode views use this pattern heavily (Source Control's "View as Tree/List", Outline's filter toggles, etc.).The tradeoff (the design call)
Two-command swap (current pattern):
Single-button
toggled(the alternative):Questions the plan-gate should answer
packages/vscode/? Three are known; an honest count may reveal more (status-bar toggles, dev-server start/stop is not one, but accordion-mode might be).toggledpattern is more discoverable for VSCode-native users; swap pattern is more discoverable in the abstract (you can see both states' icons in the title bar... no wait, you can only see one at a time). The discoverability argument may favourtoggled.What this isn't
Acceptance (loose pending plan-gate)
toggled/ explicitly defers.codev/resources/arch.md(or a similar durable location) so future toggle additions follow it without re-litigating.Related