From 4c7bbb6c3569924ea5ea4bbebd8e82c30e9193a4 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 19 May 2026 16:05:31 +0200 Subject: [PATCH] =?UTF-8?q?@wordpress/ui:=20Compat=20overlay=20slot=20?= =?UTF-8?q?=E2=80=94=20viewport-sized=20containing=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The body-level compat overlay slot was `position: fixed; top: 0; left: 0` with no width/height. With its only child being a `position: absolute` overlay positioner — which doesn't contribute to its parent's intrinsic size — the slot collapsed to 0×0. Absolutely-positioned children inside a zero-width containing block fall back to shrink-to-fit constrained by zero available width, which forces `width: auto` popups to their min-content width (the longest unbreakable word). The most visible symptom: long-text tooltips wrapped to one word per line. Stretch the slot to viewport size (`inset: 0`) so portaled overlay positioners get a sane containing block, and add `pointer-events: none` so the now-full-bleed slot doesn't intercept clicks across the page. Each opt-in component (Tooltip, Autocomplete, Select) re-enables `pointer-events: auto` on its own positioner so portaled content stays interactive. --- packages/ui/CHANGELOG.md | 1 + packages/ui/src/tooltip/style.module.css | 2 +- .../css/wp-compat-overlay-slot.module.css | 33 ++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 407b23e46fae5c..cf0da826307a42 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -17,6 +17,7 @@ ### Bug Fixes - Apply shared item popup typography to inline lists and empty states ([#78403](https://github.com/WordPress/gutenberg/pull/78403)). +- Stretch the compat overlay slot to viewport size so portaled popups stop collapsing to their min-content width — most visible on long-text tooltips, which wrapped to one word per line ([#78441](https://github.com/WordPress/gutenberg/pull/78441)). ## 0.13.0 (2026-05-14) diff --git a/packages/ui/src/tooltip/style.module.css b/packages/ui/src/tooltip/style.module.css index 4c000a95594a48..8c3927ea78681d 100644 --- a/packages/ui/src/tooltip/style.module.css +++ b/packages/ui/src/tooltip/style.module.css @@ -25,7 +25,7 @@ * positioner (via the shared `.box-sizing` reset utility), so * the 1px is absorbed and non-FC layout is unchanged. */ - @media (forced-colors: active) { + @media ( forced-colors: active ) { border: 1px solid CanvasText; } } diff --git a/packages/ui/src/utils/css/wp-compat-overlay-slot.module.css b/packages/ui/src/utils/css/wp-compat-overlay-slot.module.css index c3b919041a4066..17237b386a3792 100644 --- a/packages/ui/src/utils/css/wp-compat-overlay-slot.module.css +++ b/packages/ui/src/utils/css/wp-compat-overlay-slot.module.css @@ -1,24 +1,35 @@ +@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides; + /* * Compat overlay slot — body-level positioned container that hosts * `@wordpress/ui` overlays so they reliably stack in mixed-library * compositions. See `getWpCompatOverlaySlot()` for the runtime side. * - * Authored unlayered (outside `@layer wp-ui-*`) so the slot's z-index and - * positioning win against any `@layer`-scoped rule. + * The `.slot` rule is authored unlayered (outside `@layer wp-ui-*`) so the + * slot's z-index and positioning win against any `@layer`-scoped rule. */ .slot { - /* `position: fixed` is load-bearing: `z-index` is ignored on `static`, - * and the slot must be a containing block at viewport `(0, 0)` so - * floating-ui's viewport-relative `top`/`left` resolve correctly. */ + /* Viewport-sized so `position: absolute` overlay positioners inside + * the slot have a non-zero containing block — otherwise `width: auto` + * popups collapse to their min-content width. */ position: fixed; - top: 0; - /* Physical, not logical. `inset-inline-start: 0` would resolve to - * `right: 0` in RTL and offset every absolute child off-viewport. */ - /* stylelint-disable-next-line plugin/use-logical-properties-and-values -- See comment above. */ - left: 0; - /* Sits in a reserved billion-scale band above the legacy z-index map in + inset: 0; + /* Reserved band above the legacy z-index map in * `packages/base-styles/_z-index.scss`. */ z-index: 1000000003; isolation: isolate; + /* The slot itself doesn't capture clicks; portaled overlays opt back in + * via the `.slot > *` rule below. */ + pointer-events: none; +} + +/* + * Re-enable interaction for portaled overlays. Placed in the lowest layer + * so any consumer can override with a higher-layer (or unlayered) rule. + */ +@layer wp-ui-utilities { + .slot > * { + pointer-events: auto; + } }