Skip to content

feat(widgets): compact label presets with global and per-widget toggles - #10

Merged
axisrow merged 4 commits into
mainfrom
feat/compact-labels
Sep 26, 2026
Merged

axisrow merged 4 commits into
mainfrom
feat/compact-labels

Conversation

@axisrow

@axisrow axisrow commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Summary

Compact display modes for labeled widgets — a settings-driven way to shorten the standard Model: / Context: / Cost: prefixes and cap wide widgets, without touching defaults for existing configurations.

What landed

  • Compact label presets for labeled widgets: Model: → M:, Context: → Ctx:, Cost: → renders the bare value with its own dollar glyph (a naive $-prefixed preset produced $$2.46 — caught by the acceptance render and fixed).
  • Two toggles, composable: global Settings.compactLabels (key (j) in Global Overrides) and per-widget metadata.compactLabel (key (j) in the item editor, probe-gated); per-widget wins over global in both directions.
  • Settings schema: additive compactLabels key (default false), no version bump; migration tests assert v1→v4 and bare-v4 parses leave old configs rendering identically.
  • Width caps (w) added to Current Working Dir and Session Name, following the existing Git Branch / Git Root Dir pattern.
  • Overhead audit of default padding/separator cost per widget documented in docs/USAGE.md; rendering defaults unchanged.
  • Model / Session Cost / Context Bar moved to a shared compact-label helper (the extension point for future labels); coexists with upstream PR feat(widgets): add editable label prefix to text-label widgets sirmalloc/ccstatusline#601 via separate metadata keys.

Before / after (piped render)

BEFORE: Model: Opus 4.6 | Context: [bar] 30k/200k (15%) | Cost: 2.46usd
AFTER:  M: Opus 4.6 | Ctx:   [bar] 30k/200k (15%) | 2.46usd

Per-widget override off → Context: keeps its full label while the rest stays compact.

Tests

  • bun test: 2400 pass / 0 fail (single final run, this exact tree); migration + key-reservation tests included
  • bun run lint: clean, no suppressions
  • No new dependencies; dual-runtime Bun + Node untouched

Known risks / notes

🤖 Generated with Claude Code

Add abbreviated label presets for labeled widgets, complementary to the
free-form label editing proposed upstream (sirmalloc#601):

- New `compactLabels` settings flag (default off). Additive v4 key: old
  configs parse unchanged and render identically, no version bump needed.
- Presets live in one map (`Model:` -> `M:`, `Context:` -> `Ctx:`,
  `Cost:` -> `` — the value's own `$` is the glyph) inside
  `formatRawOrLabeledValue`, so every widget routed through the helper
  picks them up with no per-widget changes. Model, Session Cost, and
  Context Bar moved onto the helper.
- One-click global toggle in Global Overrides `(j)`; per-widget override
  via `(j) compact label` in the items editor (metadata `compactLabel`),
  which wins over the global setting in both directions. Capability for
  the editor keybind is derived from a cached preview probe of the
  widget registry.
- Extend the Git Branch width-cap pattern to Current Working Dir and
  Session Name (`w` max-width keybind).
- Document per-widget padding/separator/label width overhead in
  docs/USAGE.md; defaults unchanged.

Tests: preset resolution, toggle metadata, global injection precedence,
migration parity (v1->v4 and schema-less v4 parse), registry-wide `j`
keybind reservation, capable-type probe sanity, Global Overrides `(j)`
keystroke test. bun test 2400 pass; bun run lint clean.

Co-Authored-By: Claude Code <noreply@anthropic.com>

@axisrow axisrow left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вердикт: requesting changes — одно функциональное расхождение с задокументированным поведением + док-нитка, остальное чисто.

Главное — пер-виджетный (j) не даёт форсить метки ВЫКЛ при включённом глобальном Compact Labels. toggleCompactLabel переключает только undefined ↔ true; значение false не пишется никогда. Доки этого же PR обещают «force it on/off regardless of the global setting», и модель данных opt-out поддерживает (тест рендерера с compactLabel: false проходит), но из TUI это состояние недостижимо: при compactLabels: true виджет уже рендерится компактно (withGlobalCompactLabels инжектит true на рендере), поэтому (j) пишет true — без видимых изменений, а второй раз нажатие удаляет ключ — глобальный флаг возвращается. Кейбинд превращается в визуальный no-op, причём в списке виджетов нет маркера: getCompactLabelModifierText смотрит только на сохранённые метаданные. Фикс: трёхстадийный цикл по эффективному состоянию (рендерится компактно → false; false → убрать ключ/наследовать; иначе → true) плюс эффективное состояние в тексте модификатора.

Нитка — docs/USAGE.md:122: Model: (7 колонок) → M: (3) = −4, а не −5; Context: (9) → Ctx: (5) = −4, а не −3 (Cost: → −6 верно).

Что хорошо: аддитивный ключ compactLabels с дефолтом false без бампа версии схемы — старые конфиги рендерятся идентично (покрыто тестами parse v4 и миграции v1); кешированный probe getCompactLabelCapableTypes с try/catch безопасен — виджеты без isPreview-гарда (SessionUsage и т.п.) не запускают сабпроцессов на preview; тест резервации клавиши (j) по всем виджетам; внятный приоритет rawValue > пер-виджет > глобальный в formatRawOrLabeledValue.

Comment thread src/widgets/shared/raw-or-labeled.ts Outdated
Comment thread docs/USAGE.md Outdated
axisrow and others added 2 commits September 26, 2026 09:51
The per-widget (j) toggle only wrote/removed 'true', so with the global
Compact Labels setting on it became a visual no-op: the render-time
injection re-compactified the widget after the key was removed, and no
row marker showed the effective state.

- toggleCompactLabel now takes the settings and cycles the EFFECTIVE
  state: compact (saved 'true' or inherited global on) -> write 'false';
  forced off -> drop the key and inherit; otherwise -> write 'true'.
- getCompactLabelModifierText reports the effective state:
  '(compact label)' / '(compact label: on)' / '(compact label: off)'.
- ItemsEditor/input-handlers pass settings through to both.
- docs/USAGE.md: fix preset savings arithmetic (Model -4, Context -4).

Co-Authored-By: Claude Code <noreply@anthropic.com>
…act is on

Co-Authored-By: Claude Code <noreply@anthropic.com>

@axisrow axisrow left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вердикт: approve. Фиксы f41c8d3 + 87a21ca закрывают оба пункта ревью 5324047980, перепроверено по диффу: toggleCompactLabel(item, settings) циклит по эффективному состоянию (inherit → on → forced-off → inherit; при глобали on стартует с inherited-compact → forced-off), getCompactLabelModifierText показывает on/off/явный on, settings прокинуты из ItemsEditor в оба продакшн-коллера, рендер-тест доказывает сценарий «(j) при глобали on выключает метку» end-to-end (Model: Opus 4.6 | $2.46), арифметика в docs/USAGE.md исправлена (−4/−4/−6). Обратная совместимость сохранена: settings? optional, старые коллеры получают прежнее поведение. Замечаний нет.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@axisrow
axisrow merged commit 89be667 into main Sep 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant