Repository navigation
Description
Theme previews and showcases need to render the real overlays inside a themed island. Today they cannot: a modal Dialog is moved to <body> and shown with showModal(), and menus, popovers and tooltips use popover="manual" + showPopover(). Both go to the browser top layer, so they leave the island and lose its data-preset / data-theme-scope tokens. The Theme Studio (#560) therefore previews overlays as static copies.
Ask
An opt-in inline mode: the overlay renders where it is declared, in normal flow or absolutely positioned inside a position: relative host, never in the top layer.
Dialog,Sheet,Drawer,AlertDialog:inlinerenders the panel as a non-modal<dialog open>(show()), with a faux scrim drawn by the host. No inert page, scroll lock or focus trap.FloatingLayer(soDropdownMenu,Popover,Tooltip,HoverCard,ContextMenu):inlineskipspopover/showPopover(), and positions against its anchor withposition: absoluteinside the host.Toaster:inlinepositionsabsolutein its container instead offixed.- Shared plumbing in
primitives/layer.ts: aninlinelayer option that does not push onto the global stack (no Escape or outside-press ownership), so an inline overlay can never steal input from a real one.
Acceptance
- Test first: a harness renders each overlay
inlineinside an element withdata-preset="violet"and asserts the overlay's computed--ca-brand-mainis the island's, not the page's. It fails on current code. - A real modal opened on the same page still owns Escape and inertness while inline overlays are present.
- Docs section on theme previews,
docs/css-api.mdupdated, axe clean in both modes.
Status
Blocks "tweakcn parity done". The Theme Studio (#560, PR #562) previews overlays as static copies, labelled as such in the UI. Real Dialog, Menu and Toast inside a themed island is the last gap against the owner's bar, so parity is not done until this lands.
Verification
This changes the shared layer engine (primitives/layer.ts: the stack, Escape and outside-press ownership, modal inertness, focus trap, scroll lock, positioning). It must pass the full overlay and layer suites (primitives/layer, Dialog, Sheet, Drawer, AlertDialog, Popover, DropdownMenu, Tooltip, HoverCard, ContextMenu, Toaster, nested layers) and the route sweep (routes.a11y, overlays.a11y, dialog-modal, scroll-lock), not only the studio tests.
Activity
mvilacad commentedon Oct 25, 2026
Working on this in #608 (draft). Branch
feat/563-feat-inline-non-modal-non-top. Regression test first, then the fix.feat: inline overlays render in place inside a themed island
feat: feat: inline (non-modal, non-top-layer) mode for overlays, for …