Modals and portals
Anchoring inside dialogs.
Why modals are hard
A step can point at a control inside a dialog, a popover, or a command palette. All of them render in their own portal, and each brings a problem:
- Stacking. A dialog at a high z-index paints over a scrim beneath it.
inertandaria-hidden. Dialog libraries mark everything outside the dialog as inert, which would make the tour’s own buttons unclickable.- Focus traps. A trap inside the dialog cannot reach a sibling portal, so Tab never lands on Next.
This is where most tour libraries break, and it is not a small edge case.
What Cairn does
When the target lives inside a dialog, the overlay portals into that dialog rather than onto document.body. It then inherits the dialog’s stacking context, its interactivity, and its focus scope — all three problems solved by placement.
Nothing to configure
Point a step at an anchor inside your dialog. Detection is automatic — it looks for [role="dialog"], [role="alertdialog"] and dialog[open], which covers Radix, Headless UI, MUI and native dialogs.
{ anchor: anchors.settings.difficulty, title: "Inside a modal" }Opening the modal mid-tour
Use a click step on the button that opens it. The user opens the dialog themselves, and the next step’s anchor is waited for until it mounts.
steps: [
{
anchor: anchors.page.settingsButton,
title: "Open settings",
body: "The next step is inside the dialog.",
advanceOn: { type: "click" },
},
{ anchor: anchors.settings.difficulty, title: "Inside a modal" },
]