Problem
Hiding is implemented six different ways (hideNoGit, hideNoRemote, hideTitle/hideStatus, hideZero, hideWhenEmpty, hideIfDisabled), each with its own metadata key, keybind, and modifier text, while many comparable states have no hide option at all: speed widgets render — with no data, tokens/cost/clock render 0/$0.00/0m at session start, timers render 0hr 0m with no active window, output-style can't be hidden when it equals default, and ahead/behind's 0/0 auto-hide is hardcoded with no opt-out. Decorative items (custom-symbol, custom-text) can't hide at all, so icon prefixes merged into a widget orphan whenever that widget hides (e.g. git icon prefixes outside a repo).
Proposed design
- Widget-declared states. Extend the Widget interface with
getHideableStates(): { key: string; label: string }[]. Each widget declares which conditions it can detect, drawing from a shared vocabulary where applicable: no-git, no-upstream, no-remote, no-data, zero, empty, disabled, default-value, error.
- One metadata key.
metadata.hide holds a comma-separated list of enabled state keys (metadata values are strings), e.g. "hide": "no-git,zero". A shared isHidden(item, key) helper replaces the six bespoke accessors.
- One editor surface. A single
(h)ide… keybind opens a checklist of the widget's declared states; replaces the per-widget toggle keybinds. Modifier text renders as (hide: no-git, zero).
- Decorative items participate.
custom-symbol/custom-text declare one state: merge-target-hidden; when enabled and the item they merge into renders null, they render null too (propagating through chains of merged items, so [ + icon + widget + ] collapses as a unit). This generalizes the icon-prefix case to every widget, not just git.
- Back-compat. Legacy keys are read as aliases (
hideNoGit: "true" → hide: "no-git", etc.) and migrated on next settings save; existing configs keep working unchanged.
Implementation notes
The shared helpers in src/widgets/shared/git-no-git generalize into src/widgets/shared/hideable; per-widget work is declaring states and replacing the existing ad-hoc checks with isHidden() calls. The hardcoded 0/0 auto-hide on ahead/behind becomes a declared default-on zero state for opt-out symmetry.
Problem
Hiding is implemented six different ways (
hideNoGit,hideNoRemote,hideTitle/hideStatus,hideZero,hideWhenEmpty,hideIfDisabled), each with its own metadata key, keybind, and modifier text, while many comparable states have no hide option at all: speed widgets render—with no data, tokens/cost/clock render0/$0.00/0mat session start, timers render0hr 0mwith no active window, output-style can't be hidden when it equalsdefault, and ahead/behind's 0/0 auto-hide is hardcoded with no opt-out. Decorative items (custom-symbol,custom-text) can't hide at all, so icon prefixes merged into a widget orphan whenever that widget hides (e.g. git icon prefixes outside a repo).Proposed design
getHideableStates(): { key: string; label: string }[]. Each widget declares which conditions it can detect, drawing from a shared vocabulary where applicable:no-git,no-upstream,no-remote,no-data,zero,empty,disabled,default-value,error.metadata.hideholds a comma-separated list of enabled state keys (metadata values are strings), e.g."hide": "no-git,zero". A sharedisHidden(item, key)helper replaces the six bespoke accessors.(h)ide…keybind opens a checklist of the widget's declared states; replaces the per-widget toggle keybinds. Modifier text renders as(hide: no-git, zero).custom-symbol/custom-textdeclare one state:merge-target-hidden; when enabled and the item they merge into rendersnull, they rendernulltoo (propagating through chains of merged items, so[+ icon + widget +]collapses as a unit). This generalizes the icon-prefix case to every widget, not just git.hideNoGit: "true"→hide: "no-git", etc.) and migrated on next settings save; existing configs keep working unchanged.Implementation notes
The shared helpers in
src/widgets/shared/git-no-gitgeneralize intosrc/widgets/shared/hideable; per-widget work is declaring states and replacing the existing ad-hoc checks withisHidden()calls. The hardcoded 0/0 auto-hide on ahead/behind becomes a declared default-onzerostate for opt-out symmetry.