Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changeset/page-header-z-index-below-drawers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@hyperdx/app': patch
---

fix(z-index): keep sticky header below drawers and drawers above the fullscreen tile modal

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.
34 changes: 23 additions & 11 deletions packages/app/src/components/FullscreenPanelModal.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -15,13 +17,21 @@ 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 (
<Modal
opened={opened}
onClose={onClose}
title={title}
fullScreen
transitionProps={{ transition: 'fade', duration: 200 }}
zIndex={modalZIndex}
styles={{
body: {
height: 'calc(100vh - 80px)',
Expand All @@ -42,17 +52,19 @@ export default function FullscreenPanelModal({
trapFocus={false}
lockScroll
>
<Box
h="100%"
w="100%"
p="md"
style={{
overflow: 'auto',
position: 'relative',
}}
>
{children}
</Box>
<ZIndexContext.Provider value={modalZIndex}>
<Box
h="100%"
w="100%"
p="md"
style={{
overflow: 'auto',
position: 'relative',
}}
>
{children}
</Box>
</ZIndexContext.Provider>
</Modal>
);
}
12 changes: 10 additions & 2 deletions packages/app/src/components/PageHeader.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading