Skip to content

topbar: pick nav tier by measuring overflow instead of breakpoints - #106

Open
ali616csayed wants to merge 1 commit into
mainfrom
devin/1787001235-topbar-measured-nav-tiers
Open

topbar: pick nav tier by measuring overflow instead of breakpoints#106
ali616csayed wants to merge 1 commit into
mainfrom
devin/1787001235-topbar-measured-nav-tiers

Conversation

@ali616csayed

@ali616csayed ali616csayed commented Aug 17, 2026

Copy link
Copy Markdown
Member

Summary

The topbar picked its nav tier (full labels → icons only → hamburger) from fixed container-query breakpoints at 1150px/900px, and the row was wrap="wrap". The room left for the nav depends on the breadcrumb, which varies per page and per org, not on the container width — so on pages with a long breadcrumb the nav still didn't fit at a width the breakpoints considered roomy, and instead of degrading, the row wrapped: breadcrumb on line 1, nav links on line 2, avatar on line 3.

The tier is now chosen by measuring actual overflow, and the row never wraps:

const NAV_TIERS = ['full', 'icons', 'menu'] as const;

// one synchronous pass, in a layout effect + a ResizeObserver
for (const tier of NAV_TIERS) {
  element.dataset.navTier = tier;                    // CSS keys off data-nav-tier
  if (max(overflow(topbar), overflow(contentRow)) <= 1) break;  // widest tier that fits
}

Notes on the non-obvious parts:

  • The tier is written straight to the DOM instead of held in state: the decision needs one measurement per candidate tier, so a state round-trip would mean a render (and a paint) per step, and setState in a layout effect is a lint error here anyway. navMenuOpen stays in state — it drives the Radix dropdown — and is closed whenever a wider tier wins, since the hamburger trigger only exists at menu.
  • Overflow is measured on the left row as well as on the topbar. That row is flexGrow="1" minWidth="0", so it shrinks to whatever the row leaves it and lets its own content spill; the topbar itself then reports scrollWidth === clientWidth and would never see the overflow.
  • Measuring after every render (not only on resize) is what makes it route-aware: navigating changes breadcrumb width without resizing anything, so a ResizeObserver alone would leave the nav collapsed on a page that now has room.

.topbar gets overflow: hidden so a row that overflows even at menu is clipped rather than reflowed, and at menu the breadcrumb becomes shrinkable. Labels are still visually hidden (not removed) at the icons tier, so links keep their accessible name, and each anchor keeps its title.

Verified in the web app, which consumes this via the submodule (deeptrust-ai/web#801), with a viewport sweep from 360px to 1440px across the main routes and every Settings tab: topbar height constant, all controls on one row, no clipped nav, tier transitions where the content actually stops fitting (e.g. Desktop Downloads, with the longest breadcrumb, drops to icons ~100px earlier than Configurations).

Before (long org breadcrumb, ~1200px — the reported break) and after:

before

after

Prettier reformatted a few unrelated blocks in Topbar.tsx that were not previously formatted; those hunks are formatting only.

Link to Devin session: https://app.devin.ai/sessions/79734bf9b62b4b7a93efb9578595d14d
Requested by: @ali616csayed

@ali616csayed ali616csayed self-assigned this Aug 17, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor
Original prompt from Ali

SYSTEM:
<latest_message>
Ali Al-Sayed (U071Z77PKV0) [ts=1786999762.744689]: @Devin pls address and look for other areas where this is an issue
</latest_message>

=== BEGIN THREAD HISTORY (in #devin-chat) ===
Ali Al-Sayed (U071Z77PKV0) [ts=1786999762.744689]: @Devin pls address and look for other areas where this is an issue

[Slack unfurl — this is an automatic link preview, not a user message]
Quote of conversation (https://deeptrust-ai.slack.com/archives/C09612P2UTW/p1786999591108329):
> From Noah Kjos
> Web app header breaks on all subtabs of "settings" except "MCP" when the window is a very specific size.

> ATTACHMENT:"https://app.devin.ai/attachments/7c990680-4c83-4dfd-a8a1-7959787f0c1b/Screenshot%202026-08-17%20at%201.44.49%3FPM.png"
> Posted on August 17, 2026 at 08:46 PM

=== END THREAD HISTORY ===
Channel ID: C0996NYCENL
Thread URL: https://deeptrust-ai.slack.com/archives/C0996NYCENL/p1786999762744689?thread_ts=1786999762.744689&amp;cid=C0996NYCENL

The <latest_message> is the message that you should use to guide your goals + task for this session, and you should use the rest of the slack thread as context.
A [ts=...] marker on a Slack message is that message's timestamp. To act on a specific message with the slack tool (e.g. adding an emoji reaction via the reaction command), pass that value as timestamp along with the Channel ID — no extra lookup call is needed.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

Co-Authored-By: ali@deeptrust.ai <alialsayed616c@gmail.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787001235-topbar-measured-nav-tiers branch from b3073f3 to 3a95709 Compare August 27, 2026 21:24
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