Repository navigation
feat(header): resizable toolbar divider that collapses the usage readings as it narrows - #689
Conversation
…ings as it narrows
|
Thanks @opticon454, this is a nice idea and a tidy implementation: the line between the tabs and the toolbar becomes a handle, and the usage readings shed detail as the toolbar narrows so the tabs get the room back. Typecheck, lint, format, the frontend checks and both of your test files pass here. I ran the controller against the real
Smaller things, fine in the same round:
Once the numbered items are in I will take another look and merge. Thanks again for the contribution. |
… the header layout, restore the chosen width
|
Thanks @Ark0N, all four numbered items and the smaller ones are in
Smaller things:
Typecheck, frontend syntax, prettier, the unit tests and the Chromium suite (divider, tab rail and sidebar files) pass here. |
|
Thanks @opticon454 for the second round. The divider between the tabs and the toolbar now holds up in every case I raised: late readings stay inside it, nothing changes in the sidebar, rail or a solo window, the narrow viewport is left alone, and the tiles and classic styles follow the density steps. All checks, both of your test files and the full suite pass here and in CI. Probing the edges turned up one bug, which I will fix on top when I merge:
// apply()
wanted = width === null ? null : Math.max(MIN_WIDTH, Math.round(width));
// keydown: step from the width on screen
apply(current() + (event.key === 'ArrowLeft' ? KEY_STEP : -KEY_STEP));Small things I will also touch at merge:
Not blocking, noted as follow-ups:
Thanks again, this is a nice addition to the header. |
Clamp the stored toolbar width to MIN_WIDTH in apply() and step the arrow keys from the width on screen, so a drag to the window edge or a held ArrowRight no longer stores a negative width or leaves an ArrowLeft dead zone (browser test added) Drop Escape as a reset key on the handle: the global capture-phase Escape handler already closes every panel on it (static pin added) Say in the changeset, the wiki and the densityFor comment that the percentages go at the narrowest step in the Compact style only, and drop Escape from the changeset Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… collapses the usage readings as it narrows
…ss ones at Compact tiny (release review) #689's density steps hide every `.header-system-stats .stat-label` once the toolbar is narrowed, and #692's readings (GPU, VRAM, GPU MHz, CPU MHz) have nothing else naming them: at tight, dense and tiny the header showed "40%" beside CPU's "12%", "3.2G" beside MEM's "7.9G", and two bare "1800 MHz" / "4200 MHz" with no way to tell the GPU clock from the CPU one. At Compact + tiny, where values are hidden too, the two clocks (no ring) were left as 0-px items that still took an 8 px flex gap each. Neither PR shows it alone. - The four host items carry `stat-item--host`, excluded from the density label hide, so they keep their labels at every step. - `stat-item--ringless` (static on the two clocks, toggled by `_updateHostSensors` on VRAM while its total, and so its ring, is unknown) is hidden at Compact + tiny instead of staying an empty item. Tests: the browser test drives every density in all three styles against the real markup and styles.css (it fails on the previous files), and the unit test pins the VRAM ringless toggle. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Merged, thanks! This ships in 1.45.0. At merge the stored width is clamped to The release review then found an interaction with #692. Under your density steps the GPU, VRAM and clock readings lost their only label, so "40%" sat next to CPU's "12%" and the two clocks read as bare MHz values. Those items now carry |
What
The line between the session tabs and the header toolbar is now a handle you can drag. Dragging it right narrows the toolbar, which wraps onto a second line, and the usage readings shed detail as it narrows, so the tabs get the room back.
Why
With the default compact header style the toolbar (WS, CPU, MEM, the Claude, Codex and Copilot plan-usage pills, then the buttons) takes a large share of the top bar, and the tabs get whatever is left. There was no way to trade one for the other short of hiding things in Settings.
How
src/web/public/header-divider.js(new, self-contained): an absolutely positioned handle on the left edge of#headerRight, so it takes no layout room and the existing border stays the visible line. Pointer drag, arrow keys (Left widens, Right narrows), double-click or Home or Escape to reset. The width is a device-local convenience inlocalStorage(try/catch, so a blocked store only costs the memory), not a setting.data-header-densityon<html>): below 560px the window and CPU/MEM labels go, below 400px the provider names shorten to CL, CX and CP (data-shorton.pu-provider), below 280px only the rings are left. The chip's tooltip keeps the numbers. The rules do not depend on the header-stats style.index.html,scripts/build.mjs(minify and hashed file list) and a changeset.Screenshots
Full width (nothing changed):
Narrowed: labels gone, percentages kept:
Narrowest: rings only:
Tests
test/header-divider.test.ts: the width clamp, the density steps, wiring into the page and build, device-local storage.test/header-divider.browser.test.ts(real Chromium, listed inBROWSER_TEST_GLOBS, run withnpm run test:browser): a drag right narrows the toolbar and wraps it to two rows, the tabs keep their room, double-click and keyboard reset it, the labels, names and percentages drop in turn, it stops at the widest reading (this one fails without the measurement), and it is hidden in the sidebar layout.npm run lint,tsc --noEmit,check:frontend-syntax, prettier and the related plan-usage and tab-rail tests pass.