From b8e1fd9ffac80e59857dcb0b723547cde3aa4935 Mon Sep 17 00:00:00 2001 From: Kenny Lin Date: Fri, 31 Jul 2026 11:05:54 -0400 Subject: [PATCH 1/3] update z-indexes to temp values --- packages/gamut/src/Popover/elements.tsx | 6 ++++-- packages/gamut/src/PopoverContainer/PopoverContainer.tsx | 3 ++- packages/gamut/src/Toaster/index.tsx | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/gamut/src/Popover/elements.tsx b/packages/gamut/src/Popover/elements.tsx index 04908315050..073e1bd1144 100644 --- a/packages/gamut/src/Popover/elements.tsx +++ b/packages/gamut/src/Popover/elements.tsx @@ -66,7 +66,8 @@ export const PopoverPortal: React.FC< animation ? ( {isOpen && ( - + // TEMPORARY: zIndex override to stay above Overlay's default of 3 until GM-624 lands a shared z-index scale + ) : ( - + // TEMPORARY: zIndex override to stay above Overlay's default of 3 until GM-624 lands a shared z-index scale + ); export type PopoverContainerProps = Pick; diff --git a/packages/gamut/src/PopoverContainer/PopoverContainer.tsx b/packages/gamut/src/PopoverContainer/PopoverContainer.tsx index c93f1965bc8..4314b3d8764 100644 --- a/packages/gamut/src/PopoverContainer/PopoverContainer.tsx +++ b/packages/gamut/src/PopoverContainer/PopoverContainer.tsx @@ -282,5 +282,6 @@ export const PopoverContainer: React.FC = ({ if (inline) return content; - return {content}; + // TEMPORARY: zIndex override to stay above Overlay's default of 3 until GM-624 lands a shared z-index scale + return {content}; }; diff --git a/packages/gamut/src/Toaster/index.tsx b/packages/gamut/src/Toaster/index.tsx index 809d08aade6..c3a78b6fb35 100644 --- a/packages/gamut/src/Toaster/index.tsx +++ b/packages/gamut/src/Toaster/index.tsx @@ -26,7 +26,8 @@ export const Toaster: React.FC = ({ colorMode = 'light', }) => { return ( - + // TEMPORARY: zIndex override to stay above Overlay's default of 3 until GM-624 lands a shared z-index scale + From 2b3d1856218c2ca3085a5610692787fbcd6274cc Mon Sep 17 00:00:00 2001 From: Kenny Lin Date: Tue, 4 Aug 2026 16:23:44 -0400 Subject: [PATCH 2/3] add release plan --- .nx/version-plans/version-plan-1785874968484.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .nx/version-plans/version-plan-1785874968484.md diff --git a/.nx/version-plans/version-plan-1785874968484.md b/.nx/version-plans/version-plan-1785874968484.md new file mode 100644 index 00000000000..cbb5cd8f54f --- /dev/null +++ b/.nx/version-plans/version-plan-1785874968484.md @@ -0,0 +1,5 @@ +--- +gamut: patch +--- + +Set temporary zindex values for Popover related components From 7dc0b9f3af46e47cb0d52899689fefba9448071f Mon Sep 17 00:00:00 2001 From: Kenny Lin Date: Fri, 7 Aug 2026 11:29:44 -0400 Subject: [PATCH 3/3] docs(gamut-z-index): add skill covering the temporary z-index overrides Cherry-picked content from 11d942792 on kl-gmt-1676-gamut-skills, which had the same edit committed to the wrong branch. Co-Authored-By: Claude Sonnet 5 --- .../gamut/agent-tools/skills/gamut-z-index/SKILL.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/gamut/agent-tools/skills/gamut-z-index/SKILL.md b/packages/gamut/agent-tools/skills/gamut-z-index/SKILL.md index 1561a5c6d80..b29d2c30277 100644 --- a/packages/gamut/agent-tools/skills/gamut-z-index/SKILL.md +++ b/packages/gamut/agent-tools/skills/gamut-z-index/SKILL.md @@ -7,7 +7,7 @@ description: Use this skill when something needs to float, stick, or portal abov There is no single documented z-index scale. `DESIGN.md` names exactly one token — `headerZ`. Everything else that floats, sticks, or portals is a small ad hoc integer (0–5) baked into component internals, split across two isolated stacking tiers by `AppWrapper` and `BodyPortal`. Read this before reaching for a bigger number. -Source: `packages/gamut-styles/src/variables/elements.ts` · `packages/gamut/src/AppWrapper/index.tsx` · `packages/gamut/src/BodyPortal/index.tsx` · `packages/gamut/src/Overlay/index.tsx` +Source: `packages/gamut-styles/src/variables/elements.ts` · `packages/gamut/src/AppWrapper/index.tsx` · `packages/gamut/src/BodyPortal/index.tsx` · `packages/gamut/src/Overlay/index.tsx` · `packages/gamut/src/Popover/elements.tsx` · `packages/gamut/src/PopoverContainer/PopoverContainer.tsx` · `packages/gamut/src/Toaster/index.tsx` See also: [`gamut-modal`](../gamut-modal/SKILL.md) — Modal/Dialog composition (this skill covers what happens when something else floats above or inside one). [`gamut-menu`](../gamut-menu/SKILL.md) — floating menus via `PopoverContainer`. [`gamut-datalist`](../gamut-datalist/SKILL.md) / [`gamut-datatable`](../gamut-datatable/SKILL.md) — sticky headers, `EmptyRows`, row-menu-opens-Modal pattern. @@ -29,9 +29,15 @@ Everything below this line is **not** a token — it's a component default you c **Tier 1 — in-page**, inside `AppWrapper`. `AppWrapper` (`packages/gamut/src/AppWrapper/index.tsx`) wraps the app root in `position: relative; z-index: 1` specifically to "safely reset the stacking context" — its own comment warns: **do not change its `position`/`z-index` or extend it with overrides to those properties.** Every non-portalled component (sticky List headers, inline Tips, Tabs, inline Popovers, SelectDropdown menus, …) only has to out-rank its _local_ siblings inside this one context. `headerZ` (15) sits comfortably above all of them (the highest non-portalled value in the table below is 5). -**Tier 2 — body portals**, via `BodyPortal` (`ReactDOM.createPortal(..., document.body)`). `Overlay` (used by `Modal`/`Dialog`) and any non-`inline` `PopoverContainer` (floating menus, `DatePicker` calendar, portalling `SelectDropdown` usage) render as a **sibling of `AppWrapper`**, not a descendant of it. Their z-index only has to out-rank _other portals_ — it never has to clear `headerZ`, which is why a plain `Modal` reliably covers a sticky global header without needing `zIndex > 15`. +**Tier 2 — body portals**, via `BodyPortal` (`ReactDOM.createPortal(..., document.body)`). `Overlay` (used by `Modal`/`Dialog`), floating `Tip` (`ToolTip`/`InfoTip`/`PreviewTip` with `placement="floating"`, via `Popover`), any non-`inline` `PopoverContainer` (floating menus, `DatePicker` calendar, portalling `SelectDropdown` usage), and `Toaster` all render as a **sibling of `AppWrapper`**, not a descendant of it. Their z-index only has to out-rank _other portals_ — it never has to clear `headerZ`, which is why a plain `Modal` reliably covers a sticky global header without needing `zIndex > 15`. -`BodyPortal`'s default (`1`) is called out in its own source comment as **"a TEMPORARY stopgap solution to avoid zIndex conflicts... will be reworked with GM-624"** — treat every Tier 2 number here as fragile plumbing, not settled design intent. +`BodyPortal`'s default (`1`) is called out in its own source comment as **"a TEMPORARY stopgap solution to avoid zIndex conflicts... will be reworked with GM-624"** — treat every Tier 2 number here as fragile plumbing, not settled design intent. As of this writing, the current Tier 2 ordering is: + +``` +Overlay (3) < Toaster (4) < Popover / PopoverContainer, portalled (5, tied) +``` + +This isn't derived from any scale — it's a hand-picked, hardcoded stopgap (each override is marked `// TEMPORARY: ... until GM-624 lands a shared z-index scale`) chosen to satisfy exactly the constraints known at patch time: `Toaster` must clear `Overlay` (a toast should never be hidden by a modal/flyout behind it), and `Popover`/`PopoverContainer` must clear `Toaster` (a tooltip or menu — including a toast's own close-button tooltip — must never render behind the toast it belongs to) while staying **tied with each other**, not just above it, because a `Popover`-based tip and a `PopoverContainer`-based menu can be open and overlapping at the same time, and their relative order needs to fall back to DOM mount order (whichever opened later paints on top) rather than a fixed winner. Any new Tier 2 consumer needs a deliberate, explicit `zIndex` fit into this chain — the plain `BodyPortal` default of `1` is now strictly _below_ everything in active use, so silently relying on the default (as `Popover`, `PopoverContainer`, and `Toaster` used to) will render behind an open `Overlay`. ---