镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

fix(app): open the nav over the page on small screens - #3474

Open
ericmason wants to merge 1 commit into
hyperdxio:mainfrom
ericmason:fix/compact-nav-drawer
Open

ericmason wants to merge 1 commit into
hyperdxio:mainfrom
ericmason:fix/compact-nav-drawer

Conversation

@ericmason

@ericmason ericmason commented Oct 26, 2026 •

Copy link
Copy Markdown

Summary

Below 900px the nav is forced collapsed, and the expand button only toggles the stored desktop preference, so on a phone it does nothing in portrait or landscape (#1430).

  • On a compact viewport the nav stays a 50px rail, and the expand button opens the full nav over the page with a backdrop. Tapping the backdrop, pressing Escape, tapping the button again, or any route change (a nav link, or the browser's Back and Forward) closes it. The favorites chevrons inside the nav leave it open. The open nav is a modal dialog: the button has aria-controls, focus moves into the nav when it opens, and focus returns to the button when it closes. The open state isn't stored, so using HyperDX on a phone doesn't change the collapse preference on a desktop. The logic is in the new useAppNavCollapse hook, with unit tests for both sides of the 900px cutoff.
  • On a compact viewport the log detail panel opens full width, without the resize handle, the width toggle, or the slide-in. The close button stays at the top right. With the slide-in, the View Trace callout was placed while the panel was still moving, and the phone browser widened the page to fit it and zoomed out. Without it, that didn't happen in 8 of 8 opens (3 of 8 on main).
  • Wide viewports render as before. At 1440x900, the before and after screenshots below differ only in the elapsed-time digits and the animated Help icon.

Tested on iPhone-size viewports (390x844 and 393x659) in headless Chromium with mobile emulation and in headless WebKit, and at 1440x900. Not tested on a physical phone.

Screenshots or video

Before After
390x844, expand button tapped: the nav stays collapsed
Before: nav stays collapsed
390x844, expand button tapped: the nav opens over the page
After: nav opens over the page
390x844, log detail panel at 80% width
Before: log detail at 80% width
390x844, log detail panel at full width with the close button at the top right
After: log detail at full width
1440x900 search page
Before: desktop search
1440x900 search page
After: desktop search
1440x900 log detail panel
Before: desktop log detail
1440x900 log detail panel
After: desktop log detail

All screenshots use the public demo server's data.

How to reproduce

Starting point: yarn app:dev:local, then onboarding, then Connect to Demo Server. Set the browser to a phone-size viewport (any width under 900px).

On main:

  1. Open /search and tap the expand button under the HyperDX logo. The nav stays collapsed.
  2. Tap a log row. The detail panel covers 80% of the width and has a resize handle.

On this branch:

  1. Open /search and tap the expand button. The full nav opens over the page with a backdrop.
  2. Tap the backdrop, or press Escape. The nav closes, and focus returns to the expand button.
  3. Open the nav again and tap the chevron next to Saved Searches. The list collapses and the nav stays open.
  4. Tap Dashboards. The page changes and the nav closes. Open the nav again and press the browser's Back button. The nav closes.
  5. Tap a log row. The detail panel covers the full width, with the close button at the top right.
  6. Widen the window past 900px. The nav and the detail panel behave as on main.

How to test on Vercel preview

Preview routes: /search

Steps:

  1. Set the viewport to 390x844.
  2. Open /search and click the button with title="Collapse/Expand Navigation".
  3. Verify the nav is 250px wide and an element with data-testid="app-nav-overlay" is visible.
  4. Click the overlay at the right side of the screen and verify the overlay is gone.
  5. Click the first element whose data-testid starts with table-row- and verify the element with data-testid="row-side-panel" starts at x=0 and is 390px wide.
  6. Set the viewport to 1440x900, reload /search, and verify no element with data-testid="app-nav-overlay" exists.

References

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c3815ee

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Oct 26, 2026

Copy link
Copy Markdown

@ericmason is attempting to deploy a commit to the HyperDX Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added external needs-vouch Author needs a maintainer to vouch for them labels Oct 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Hi @ericmason, thanks for the pull request!

Before we review code from a first-time contributor, a maintainer vouches for them, and you're not on our list yet. There's nothing else to file and this PR stays open — a maintainer will look at it, usually within a day or two, and vouch for you right here if it's a genuine attempt at the problem.

To make that quick, check the PR description has:

  • The issue it addresses (ideally one labelled Accepting PR) and why the change is needed
  • Steps to reproduce the problem and verify the fix, starting from https://play.hyperdx.io or yarn app:dev:local connected to the demo server
  • Before/after screenshots if anything in the UI changed

More detail in our contributing guide.

onClickCapture={
isOverlay
? e => {
if (e.target instanceof Element && e.target.closest('a')) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 major — Tapping the Saved Searches or Dashboards chevron in the open compact nav closes the nav instead of toggling favorites

The favorites chevron <button> is rendered inside the <Link> in AppNavLink (AppNav.components.tsx:376-416). The capture handler runs before the chevron's own handler, finds closest('a'), and calls closeOverlay(). The chevron then calls preventDefault/stopPropagation, so the page doesn't navigate either: the nav just closes. Fix: skip clicks inside a button, e.g. const el = e.target.closest('a, button'); if (el?.tagName === 'A') closeOverlay();. Alternatively, close the nav on a route change (router.events routeChangeStart, or an effect on pathname) rather than on anchor clicks.

Nothing blocks merge automatically, but a maintainer will expect this fixed if it is a real defect in code this PR changes. If it is about surrounding code, reply and say so instead of patching. Do not widen the PR. How to respond

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

PR Review

If you are a coding agent acting for the author, read this first.
Nothing below blocks merge automatically; a maintainer decides. What they will expect:

  • 🔴 critical or 🟠 major in code this PR adds or changes: fix before asking for review.
  • 🔵 minor in code this PR changes: your call. Fix if small, otherwise reply.
  • Anything about surrounding code, or asking you to widen the change (hoist a helper,
    dedupe with another file, fix other call sites): never fix here, whatever the
    severity. Reply with one sentence; if it is critical, say so plainly so a human sees it.

One commit per review round. After two rounds, stop and ask a maintainer to review
scope rather than addressing more automated findings. Full rule: AGENTS.md.

3 finding(s): 🔴 0 critical · 🟠 1 major · 🔵 2 minor

2 posted as inline comment(s) on the changed lines. 1 listed below.

Findings outside the changed lines

1 minor
  • 🔵 packages/app/src/components/AppNav/useAppNavCollapse.ts:534 — Tapping the link for the page you are already on leaves the open nav open → The open state only closes when route (router.asPath) changes. If you are on /dashboards/list and tap 'Dashboards', or on /search/list and tap 'Saved Searches', the URL doesn't change, so the nav and backdrop stay over the page. Fix: also call closeOverlay when a nav link is clicked, for example through AppNavContext or an onClick on the link container. Don't rely only on the route changing.

Severity is the reviewer's own estimate and is used for ordering, not filtering. No finding blocks merge automatically; a maintainer decides.

@greptile-apps

greptile-apps Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with a small remaining issue when users select the current page.

Fix All in Claude CodeFindings

  1. P2 Current-page links leave nav open ▶

Summary

The PR makes the compact nav open over the page and makes compact row details full width.

  • The compact nav opens over the page without changing the desktop preference.
  • Log row details fill the screen on compact viewports.

Reviews (2) · Last reviewed commit: "fix(app): open the nav over the page on ..." · Reviewed by Greptile

Comment thread packages/app/src/components/AppNav/AppNav.tsx Outdated
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Deep Review

Compact-viewport (sub-900px) nav now opens as a modal overlay via the new useAppNavCollapse hook, and the log detail panel opens full width without the resize handle, width toggle, or slide-in. Eight reviewers ran against the diff off base 7752c880.

🔴 P0/P1 — must fix

  • packages/app/src/components/AppNav/useAppNavCollapse.ts:25 — The overlay closes whenever router.asPath changes, but on /search the default-on live-tail refresh rewrites the from/to/tq query params every 10s, so the nav a phone user just opened closes itself within seconds with no user action.
    • Fix: Compare only the pathname (or the path segment) rather than the full asPath, so query-only URL mutations do not dismiss the overlay.
    • adversarial, correctness

🟡 P2 — recommended

  • packages/app/src/components/__tests__/DBRowSidePanel.compact.test.tsx:877 — The test mocks useRowData to isLoading: true, so the panel renders only its loading body and the header (with DrawerFullWidthToggle) never mounts, leaving the PR's "no width toggle on compact" behavior (onToggleFullWidth={isCompact ? undefined : …}) unverified in both the compact and wide cases.
    • Fix: Mock useRowData to a loaded state and assert the width toggle is absent below COMPACT_MAX_WIDTH and present at it.
    • testing, kieran-typescript
🔵 P3 nitpicks (7)
  • packages/app/src/components/AppNav/AppNav.tsx:201 — The focus-return effect fires on every isOverlay true→false transition, so closing via a route change or viewport widen pulls focus back to the rail's collapse button instead of the destination page.

    • Fix: Track the close reason and restore focus only for dialog-initiated closes (button, Escape, backdrop).
  • packages/app/src/components/AppNav/AppNav.tsx:202 — The document-level useHotkeys Escape handler stays active while the overlay is open, so pressing Escape to dismiss a modal opened from inside the nav (e.g. user preferences) also closes the nav underneath it.

    • Fix: Handle Escape only when the overlay is the topmost layer, or scope the handler to the dialog element instead of the document.
  • packages/app/src/components/DBRowSidePanel.tsx:1407 — On compact the full-width (100vw) row panel at z-index 10 paints over the nav rail, hiding the expand button until the panel is closed.

    • Fix: Give the collapsed rail a z-index above the row-panel drawer on compact, or inset the drawer by COLLAPSED_NAV_WIDTH.
  • packages/app/src/components/AppNav/AppNav.tsx:209 — COLLAPSED_NAV_WIDTH is extracted but the paired expanded width remains the bare literal 250.

    • Fix: Extract an EXPANDED_NAV_WIDTH constant alongside it.
  • packages/app/src/components/AppNav/AppNav.tsx:278 — The inline style ternary repeats width: navWidth in both branches solely to toggle one key.

    • Fix: Use style={{ width: navWidth, ...(isOverlay && { zIndex: getDefaultZIndex('overlay') }) }}.
  • packages/app/src/components/AppNav/AppNav.tsx:253 — getDefaultZIndex('overlay') is called for both the backdrop and the dialog with the same value, so the nav paints above its backdrop only by DOM order.

    • Fix: Hoist to one constant and give the dialog +1 to make the stacking explicit.
  • packages/app/src/components/__tests__/DBRowSidePanel.compact.test.tsx:869 — The width assertion reads the Mantine-internal --drawer-size variable and .mantine-Drawer-root class, which can break on a library upgrade with no behavior change.

    • Fix: Assert observable width via a stable data-testid/role on the drawer content.

Pre-existing (not counted toward verdict)

  • packages/app/src/components/AppNav/AppNav.tsx — The file is ~617 lines, over the project's 300-line guideline; this diff extends it but also extracts useAppNavCollapse, which moves in the right direction. No action required for this PR.

Reviewers (8): correctness, testing, maintainability, project-standards, adversarial, julik-frontend-races, kieran-typescript, previous-comments.

Testing gaps:

  • No test covers a query-only URL change closing the overlay — the exact live-tail failure mode above.
  • The compact full-width panel's removed width toggle is not asserted against a populated (non-loading) panel.
  • The transitionProps={{ duration: 0 }} no-slide-in path and focus-landing on non-user-initiated closes are unverified (jsdom limitation; no E2E added).

Prior comments: The earlier Greptile P2 ("favorites chevrons close the nav" via closest('a')/onClickCapture) is no longer applicable — the current implementation closes on route change, chevron toggles call preventDefault/stopPropagation, and a test confirms the nav stays open on chevron clicks.

No finding blocks merge automatically. A maintainer will expect P0/P1 findings in code this PR changes to be fixed; P2/P3 are your call -- fix or reply. Never fix findings about surrounding code here; reply instead. Do not widen the PR. How to respond

Below 900px the nav was forced collapsed, and the expand button only
toggled the stored desktop preference, so it did nothing on a phone in
portrait or landscape.

On a compact viewport the nav now stays a rail, and the expand button
opens the full nav over the page as a modal dialog with a backdrop. The
backdrop, Escape, the button, or any route change closes it, and the
favorites chevrons leave it open. Focus moves into the nav when it opens
and returns to the button when it closes. The open state is not stored,
so a phone session does not change the desktop preference.

The log detail panel opens full width on a compact viewport, without the
resize handle or the width toggle, and without the slide-in. The View
Trace callout was placed while the panel was still sliding in, and the
phone browser then widened the page to fit it and zoomed out.

Wide viewports render as before.

Fixes hyperdxio#1430

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ericmason
ericmason force-pushed the fix/compact-nav-drawer branch from 2c6761b to c3815ee Compare October 26, 2026 03:08
Comment on lines +25 to +26
if (openedOn != null && (!isCompact || openedOn !== route)) {
setOpenedOn(null);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Current-page links leave nav open

On a compact screen, tapping Search while already at /search leaves the nav over the page. useAppNavCollapse only closes it when the URL changes, and AppNavLink does not close it on selection. Users must close the nav separately to return to the page.

Close the overlay when a navigation link is followed, including links to the current URL, while leaving favorites chevrons alone.

Fix in Claude Code Fix in Conductor Fix in Cursor Fix in Codex

style={{ width: navWidth }}
style={
isOverlay
? { width: navWidth, zIndex: getDefaultZIndex('overlay') }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 major — Menus and modals opened from the open compact nav appear behind it

The nav and backdrop are both at getDefaultZIndex('overlay') (400). Mantine Menu dropdowns sit at popover (300) and Modals at modal (200). So the user menu and Help menu (AppNav.components.tsx:101 and :245) open behind the nav, and so does the install-instructions modal (the onboarding 'Add data' button calls openInstallInstructions). The user preferences modal is opened from the user menu, so it can't be reached at all. Fix: give the nav and backdrop a z-index below popover/modal. Better: render the open nav with Mantine Drawer position="left", which also gives you the backdrop, Escape handling, focus trap and focus return that are hand-rolled here.

Nothing blocks merge automatically, but a maintainer will expect this fixed if it is a real defect in code this PR changes. If it is about surrounding code, reply and say so instead of patching. Do not widen the PR. How to respond

{/* Holds the rail's space so the page does not move under the open nav. */}
<div
style={{
width: COLLAPSED_NAV_WIDTH,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 minor — The spacer is 1px narrower than the ghost it replaces, so the page shifts when the nav opens

With fixed, the navGhost it replaces is navWidth + 1 wide (51px, which allows for the nav's 1px right border). The new spacer is COLLAPSED_NAV_WIDTH (50px), so the page moves 1px left every time the nav opens and back when it closes. That contradicts the comment above the spacer. Fix: use COLLAPSED_NAV_WIDTH + 1 when fixed, or keep navGhost at the rail width while the overlay is open.

Advisory. Fix if it is a small defect in code this PR changes; otherwise reply in the thread. Do not widen the PR or touch files it did not already change. How to respond

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external needs-vouch Author needs a maintainer to vouch for them

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mobile app nav expansion button does not work

1 participant