From 00a77d2ea3e5abd5f5b934199d328ed08663b7a3 Mon Sep 17 00:00:00 2001 From: Elizabet Oliveira Date: Mon, 1 Jun 2026 17:51:04 +0100 Subject: [PATCH 1/3] style(PageHeader): adjust z-index for sticky elements to ensure proper overlay behavior Updated the z-index for the PageHeader and stickyRow components to 2, allowing top-level drawers to overlay correctly while maintaining the header's visibility during scrolling. This change ensures that the header floats above normal content but below the drawer overlays, improving the overall user experience. --- packages/app/src/components/PageHeader.module.scss | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/app/src/components/PageHeader.module.scss b/packages/app/src/components/PageHeader.module.scss index 3408b57ead..1bde82d825 100644 --- a/packages/app/src/components/PageHeader.module.scss +++ b/packages/app/src/components/PageHeader.module.scss @@ -14,7 +14,12 @@ padding: 0 var(--mantine-spacing-sm); position: sticky; top: 0; - z-index: 100; + + /* Top-level drawers in this app are rendered at z-index 10 + (`contextZIndex + 10` from `ZIndexContext`, see e.g. `DBRowSidePanel`). + Sit 8 below that so the drawer overlay always covers the page chrome, + while the header still floats above normal scrolling content. */ + z-index: 2; } /* Applied automatically when a `stickyRow` is provided: the chrome scrolls @@ -40,7 +45,10 @@ padding: var(--mantine-spacing-sm); position: sticky; top: 0; - z-index: 100; + + /* Match `.header` — sit 8 below the top-level drawer z-index (10) so + drawer overlays always cover this row. */ + z-index: 2; } /* Applied when the sticky row sits directly under chrome AND is not From d2e09dfee8c977ed5267c4c3bc108fb2a42a9e5b Mon Sep 17 00:00:00 2001 From: Elizabet Oliveira Date: Mon, 1 Jun 2026 18:01:00 +0100 Subject: [PATCH 2/3] chore: add changeset for PageHeader z-index fix Co-authored-by: Cursor --- .changeset/page-header-z-index-below-drawers.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changeset/page-header-z-index-below-drawers.md diff --git a/.changeset/page-header-z-index-below-drawers.md b/.changeset/page-header-z-index-below-drawers.md new file mode 100644 index 0000000000..63b4c181c8 --- /dev/null +++ b/.changeset/page-header-z-index-below-drawers.md @@ -0,0 +1,11 @@ +--- +'@hyperdx/app': patch +--- + +fix(PageHeader): keep sticky header below drawer overlays + +The sticky page header sat at `z-index: 100`, which floated it above app +drawers (drawers opt into a lower stack via `ZIndexContext`, putting the +overlay at `z-index: 10`). The header now sits at `z-index: 2` — 8 below +the top-level drawer — so drawer overlays reliably cover the page chrome +while the header still wins against normal scrolling content. From 8662351fafb35d5f1c8a0db02057f1fae3388119 Mon Sep 17 00:00:00 2001 From: Elizabet Oliveira Date: Mon, 1 Jun 2026 18:33:45 +0100 Subject: [PATCH 3/3] fix(FullscreenPanelModal): stack drawers opened from inside the fullscreen tile above the modal Use the existing `ZIndexContext` pattern (`contextZIndex + 10`) for the modal itself and expose that value via `ZIndexContext.Provider`, so a DBRowSidePanel drawer opened by clicking a row inside the fullscreen search tile lands at `z-index: 20` (above the modal at `10`) instead of `z-index: 10` (hidden behind Mantine's default modal z-index of 200). Co-authored-by: Cursor --- .../page-header-z-index-below-drawers.md | 21 ++++++++---- .../src/components/FullscreenPanelModal.tsx | 34 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/.changeset/page-header-z-index-below-drawers.md b/.changeset/page-header-z-index-below-drawers.md index 63b4c181c8..31d4dd178e 100644 --- a/.changeset/page-header-z-index-below-drawers.md +++ b/.changeset/page-header-z-index-below-drawers.md @@ -2,10 +2,19 @@ '@hyperdx/app': patch --- -fix(PageHeader): keep sticky header below drawer overlays +fix(z-index): keep sticky header below drawers and drawers above the fullscreen tile modal -The sticky page header sat at `z-index: 100`, which floated it above app -drawers (drawers opt into a lower stack via `ZIndexContext`, putting the -overlay at `z-index: 10`). The header now sits at `z-index: 2` — 8 below -the top-level drawer — so drawer overlays reliably cover the page chrome -while the header still wins against normal scrolling content. +Two related z-index regressions: + +- `PageHeader` was pinned at `z-index: 100`, but app drawers opt into a + much lower stack via `ZIndexContext` (`contextZIndex + 10`, so a + top-level drawer renders at `z-index: 10`). The sticky header therefore + floated above the drawer overlay. The header now sits at `z-index: 2` so + drawer overlays reliably cover the page chrome while the header still + wins against normal scrolling content. +- `FullscreenPanelModal` used Mantine's default modal z-index (`200`) and + didn't propagate it through `ZIndexContext`. Clicking a row in a + fullscreen search tile opened a `DBRowSidePanel` drawer at `z-index: 10` + that was hidden behind the modal. The modal now follows the existing + `contextZIndex + 10` pattern and wraps its children in a + `ZIndexContext.Provider`, so child drawers stack on top of it. diff --git a/packages/app/src/components/FullscreenPanelModal.tsx b/packages/app/src/components/FullscreenPanelModal.tsx index e7f9c61c4a..1b3df9d793 100644 --- a/packages/app/src/components/FullscreenPanelModal.tsx +++ b/packages/app/src/components/FullscreenPanelModal.tsx @@ -1,6 +1,8 @@ import { Box, Modal } from '@mantine/core'; import { useHotkeys } from '@mantine/hooks'; +import { useZIndex, ZIndexContext } from '@/zIndex'; + export default function FullscreenPanelModal({ opened, onClose, @@ -15,6 +17,13 @@ export default function FullscreenPanelModal({ // YouTube-style 'f' key to toggle fullscreen useHotkeys([['f', () => opened && onClose()]]); + // Stack on top of any ancestor drawer/modal (`contextZIndex + 10`) and + // expose this value via `ZIndexContext` so any drawer/popover opened from + // inside the fullscreen view (e.g. clicking a row in a search tile) lands + // above the modal instead of being hidden behind it. + const contextZIndex = useZIndex(); + const modalZIndex = contextZIndex + 10; + return ( - - {children} - + + + {children} + + ); }