Skip to content

The topbar fits itself by measuring, not by width breakpoints - #239

Open
bouzidanas wants to merge 2 commits into
nyblnet:mainfrom
bouzidanas:fix-topbar-overflow
Open

The topbar fits itself by measuring, not by width breakpoints #239
bouzidanas wants to merge 2 commits into
nyblnet:mainfrom
bouzidanas:fix-topbar-overflow

Conversation

@bouzidanas

Copy link
Copy Markdown

Px breakpoints clipped the end of the bar whenever the same buttons needed more room at the same viewport width (browser zoom, OS text scaling, wider translations, the update chip or avatars appearing). fitTopbar() now measures the bar and steps down a tier while it still overflows: ed-bar-compact hides labels, ed-bar-tight drops the wordmark, ed-bar-fold moves buttons into menus via applyPhoneChrome. Driven by a ResizeObserver on the bar plus a MutationObserver for content changes; the 700px media query keeps only the viewport-scoped phone chrome (drawer panels, touch targets).

What & why

The editor topbar used to collapse at fixed pixel breakpoints (1200 for labels, 760 for the wordmark, 700 for the phone fold). The problem is that the room the same buttons need at the same viewport width isn't constant. Browser zoom, OS text scaling, wider translations, and live content like the update chip or the avatar strip all change it, and every one of those cases could clip buttons off the end of the bar. CSS can't see any of this because media queries and container queries measure the container, never whether the content actually fits in it.

So the tiers are now classes instead of breakpoints. A new fitTopbar() in editor.ts starts from the widest layout and steps down while the bar still overflows its own box (scrollWidth against clientWidth, plus a check for the title input getting crushed, since it's the only shrinkable thing in the bar and absorbs all the pressure first). ed-bar-compact hides button labels, ed-bar-tight drops the wordmark, and ed-bar-fold moves buttons into menus through the existing applyPhoneChrome reparenting. A ResizeObserver on the bar catches width changes and a MutationObserver catches content changes. The 700px media query stays, but only for the genuinely viewport-scoped phone chrome (overlay drawer panels and 44px touch targets), and phones always fold like before.

A few things worth knowing about how this behaves. The mutation observer watches child changes, text, and the style and hidden attributes, so if future bar content changes its width purely through a class toggle it won't trigger a re-fit until the next resize (easy one-line filter tweak when that comes up). Re-fits are also skipped while a dropdown is open, because re-fitting would slam it shut; in the rare case content grows during that window the bar can sit slightly overflowed until the next event, and then fixes itself. And debugging the bar's state now means looking at which ed-bar classes were applied rather than reading the stylesheet.

How I verified it

Verified in the browser at 1500, 1100, 750, and 640px, and with CSS zoom at a fixed viewport (the exact case the old breakpoints couldn't see). tsc, build:single, shell-gate, i18n coverage, and the preview, autosave, validate, clipboard, layouts, and savepurpose rigs all pass.

Checklist

  • Read the relevant parts of CLAUDE.md / docs before changing them
  • npm run build:single succeeds (from slides/)
  • Ran node scripts/test-sync.ts if I touched slides/src/sync/
  • New UI strings added to every catalog in slides/src/i18n/
  • Document format changes are additive and backward-compatible
  • Did not bump the version or cut a release (maintainers sign releases)

Px breakpoints clipped the end of the bar whenever the same buttons
needed more room at the same viewport width (browser zoom, OS text
scaling, wider translations, the update chip or avatars appearing).
fitTopbar() now measures the bar and steps down a tier while it still
overflows: ed-bar-compact hides labels, ed-bar-tight drops the
wordmark, ed-bar-fold moves buttons into menus via applyPhoneChrome.
Driven by a ResizeObserver on the bar plus a MutationObserver for
content changes; the 700px media query keeps only the viewport-scoped
phone chrome (drawer panels, touch targets).
@bouzidanas

Copy link
Copy Markdown
Author

I should add that while this fix will add some complexity to maintaining/reviewing code (because layout change logic will be in js), it is more scalable. Don't need to redo breakpoints if anything is added/changed/removed from the top bar.

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