Skip to content

refactor(widgets): consolidate the progress-bar widgets' duplicated code - #810

Merged
sirmalloc merged 1 commit into
sirmalloc:mainfrom
eric-engberg:refactor/progress-bar-widgets
Nov 6, 2026
Merged

sirmalloc merged 1 commit into
sirmalloc:mainfrom
eric-engberg:refactor/progress-bar-widgets

Conversation

@eric-engberg

Copy link
Copy Markdown
Contributor

What

The progress-bar widgets carry a lot of copied code. This consolidates it, with no change in behavior: every widget renders byte for byte what it renders on main, in every display mode, including #794's line bar.

Why

The same bar code lives in up to a dozen places, so a change to how bars render has to be made in each of them. #794's line mode, for example, touched the bar blocks of Block Timer, Block Reset Timer, Weekly Reset Timer, Extra Usage Utilization and the usage-percent widgets one by one.

  • Block Timer, Block Reset Timer, Weekly Reset Timer, Extra Usage Utilization and the usage-percent widgets each build their bars with the same two blocks: the bracketed or line bar plus percentage, and the slider with or without it. Extra Usage Utilization has them twice, and Block Timer three times.
  • Block, Weekly, Weekly Sonnet, Weekly Opus and Fable Weekly Usage are five identical classes apart from the kind they pass to the shared functions from refactor(usage): extract the usage-percent widgets onto a shared module #545. Spend Limit Usage (feat(usage): add Spend Limit Usage and Spend Limit Amount widgets #695) is a sixth copy, apart from its color, the time cursor it can't offer and the usage API error it never shows.
  • Context % and Context % (usable) are the same class apart from their name, color, description, label prefix, preview sample and how they measure the used share of the window.

How

  • Shared bar rendering. formatUsageBar in widgets/shared/usage-display.ts builds every bar mode's text (block, line and slider, with or without the percentage) and returns null outside them, so each widget only adds its label. The time cursor is still resolved only in bar modes.
  • One class for the usage-percent widgets. UsagePercentWidget in widgets/shared/usage-percent-widget.ts holds the class once, and each widget names its kind. Spend Limit Usage extends it and keeps only its color. The class takes the other two differences from the kind: no usage window means no cursor key, and a kind that ignores API errors has no "unavailable" state to hide.
  • A shared base for the Context % widgets. ContextPercentageWidgetBase holds what the two share; each supplies only what differs, including Context % (usable)'s compaction-aware usable window from fix: use env override and settings for usable context ratio calculation #407.

17 files, 284 lines added and 594 removed.

Demo

In the line editor, p cycles the display modes of Block Usage, Block Timer, Context % and Extra Usage Utilization, which between them use all three pieces of shared code. These were recorded before #794 added the line mode; the render check under Testing covers it.

Powerline

Progress-bar widgets cycling their display modes in Powerline mode

Plain

Progress-bar widgets cycling their display modes in plain mode

Testing

  • On main as of fix(powerline): keep the Custom theme when Powerline is enabled again #793 (a0bedc0), one commit: bun run lint is clean, and bun test gives 4151 pass, 0 fail (4147 on main). The existing tests pass unchanged, which is the main check that behavior didn't change. New: widgets/shared/__tests__/usage-bar.test.ts covers formatUsageBar in each bar mode, null outside them without resolving the cursor, and the time cursor; SpendLimitUsage.test.ts checks the color Spend Limit Usage keeps and that it offers no state to hide.
  • Before/after render check: all 12 affected widgets rendered on main and on this branch in every state their own keys reach, up to six presses deep, so every display mode including the line bar: display modes, used or remaining, time cursor, compact, date and so on (72 states per usage-percent widget, up to 400 for the Weekly Reset Timer). Each state renders raw and labeled, at all three color levels, in the TUI preview, plus sample live usage and context data for the usage and Context % widgets. All 9,273 cases are byte-identical, as are each state's editor label and keys.
  • The built CLI under Bun 1.4.4 and Node 26.13.0 agrees across runtimes and matches main in plain and Powerline mode, on a line of these widgets in bar modes. The TUI opens and exits cleanly under both.
  • It adds no JavaScript or Node API newer than Node 14, the build's target.

- Shared bar rendering: Block Timer, Block Reset Timer, Weekly Reset Timer,
  Extra Usage Utilization and the usage-percent widgets each built their bars
  with the same blocks. formatUsageBar in usage-display.ts now builds every
  bar mode (block, line and slider, with or without the percentage) in one
  place and returns null outside them, so each widget only adds its label.
  The time cursor is still resolved only in bar modes.
- One class for the usage-percent widgets: Block, Weekly, Weekly Sonnet,
  Weekly Opus and Fable Weekly Usage were identical apart from their kind.
  UsagePercentWidget holds the class once and each widget names its kind.
  Spend Limit Usage extends it too and keeps only its color; the class takes
  the time cursor and the API-error state from the kind.
- A shared base for the Context % widgets: Context % and Context % (usable)
  differed only in name, color, description, label prefix, preview sample
  and how they measure the used share. ContextPercentageWidgetBase holds the
  rest.

No change in behavior.
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.

2 participants