Nav hierarchy: scroll-aware title, calmer bar, one menu - #165
Conversation
The signed-in nav had no clear order of importance — Workspace, Feed, a search box, a settings gear, a notifications bell, the user's name, and sign-out all competed for the bar at once, and a plan's title scrolled away entirely (following a comment notification dropped you in with no "where am I?"). Restructure the bar into three legible zones — identity → context → tools: - Logo is the Workspace home; the redundant "Workspace" link is gone. - A scroll-aware document title fades into the bar (IntersectionObserver on #plan-header) once the plan's own header scrolls behind it, so wayfinding costs zero space until you need it. Drop the now-pointless "Contents" label from the outline sidebar too. - Feed, Profile, Settings, and Sign out fold into one ☰ menu (reuses the app's popover menu — native light-dismiss + Esc). - Notifications stays a first-class bar control whenever there's room: the bell keeps its inline peek panel. Below the phone breakpoint the whole control folds into the menu (Notifications links to the full page there) and the unread count reappears as a dot on ☰. Touch: the ☰, folded search icon, and menu rows are ≥44px hit areas on phones and any coarse pointer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50d69036cc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| this._observer.observe(anchor) | ||
| } | ||
|
|
There was a problem hiding this comment.
Reobserve the header after Turbo replacements
When any live plan update replaces #plan-header—for example PlansController#broadcast_plan_update at lines 684-685—the observer remains attached to the detached element. It then reports the old target as non-intersecting and leaves the nav title visible even while the replacement masthead is on screen, with subsequent scrolling no longer updating it; reconnect the observer whenever the broadcast replaces the anchor or observe a stable ancestor instead.
AGENTS.md reference: AGENTS.md:L87-L89
Useful? React with 👍 / 👎.
| <%= plan_type_icon(@plan, size: :sm) %> | ||
| <span class="site-nav__doc-title-text"><%= @plan.title %></span> |
There was a problem hiding this comment.
Update the sticky copy when a plan is renamed
When another user or an API agent renames this plan, the existing realtime broadcast replaces only #plan-header, while this independently rendered title remains at its initial value. A viewer who stays on the page therefore sees the old plan name in the sticky nav after scrolling even though the masthead already shows the new name; include this copy in the rename broadcast or derive it from the replaced header.
AGENTS.md reference: AGENTS.md:L61-L64
Useful? React with 👍 / 👎.
| <%= link_to coplan.notifications_path, class: "menu__item menu__item--notifications", role: "menuitem" do %> | ||
| <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg> | ||
| <span>Notifications</span> | ||
| <% if unread > 0 %><span class="menu__badge"><%= unread %></span><% end %> |
There was a problem hiding this comment.
Keep the mobile menu count synchronized
On phone widths this is the only visible numeric notification count, but Turbo broadcasts and the mark-read actions update only #inbox-badge; this separately rendered .menu__badge is never targeted. Notifications arriving after load leave it absent or too low, and marking notifications read leaves a stale positive count until navigation, so the menu row should render from or be updated alongside the live badge.
AGENTS.md reference: AGENTS.md:L76-L82
Useful? React with 👍 / 👎.
| icon + title mirror the masthead's #plan-header; coplan--nav-title fades | ||
| it in once that header scrolls behind the bar. %> | ||
| <% content_for :nav_title do %> | ||
| <a href="#plan-header" class="site-nav__doc-title" data-controller="coplan--nav-title" aria-hidden="true" tabindex="-1"> |
There was a problem hiding this comment.
Expose the visible title link to keyboard users
After scrolling, this element becomes a visible and clickable link, but the controller only toggles its CSS class, leaving aria-hidden="true" and tabindex="-1" permanently in place. Screen-reader and keyboard-only users therefore cannot discover or activate the same return-to-header control; toggle these attributes with the visible state or use a non-interactive element.
Useful? React with 👍 / 👎.
A bare #plan-header anchor jump landed the header under the sticky bar, so clicking the title looked like nothing moved (it just faded out). Intercept the click and smooth-scroll to the very top instead, bringing the full masthead back — the observer then hides the title on its own. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removing the "Contents" label left the lone collapse control sitting in its own right-aligned row, with dead space where the label used to be. Float the control into the top-right corner so the outline starts at the very top and the first item flows beside it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fa9a8-30e2-730b-a230-383b52c1bbb3 Co-authored-by: Amp <amp@ampcode.com>
Why
The signed-in nav had no clear order of importance — Workspace, Feed, a search box, a settings gear, a notifications bell, the user's name, and sign-out all competed for the bar at once. And a plan's title scrolled away entirely: following a comment notification dropped you into the doc with nothing telling you where am I?
What changed
The bar now reads as three legible zones — identity → context → tools:
#plan-header) once the plan's own header scrolls behind it — persistent wayfinding that costs zero space until you need it, which matters most on mobile and on comment deep links. The now-pointless "Contents" label leaves the outline sidebar too.#inbox-badgecount).Testing
VQA with the agent browser across light + dark, desktop + mobile:
Live notification updates preserved:
#inbox-badgeand itsturbo_stream_fromsubscription are intact.🤖 Generated with Claude Code