Tour Experimental
A multi-step guided tour overlay that highlights target elements and displays positioned popover cards with navigation controls.
import { Tour } from 'phoundry-ui';
import type { TourStepDef } from 'phoundry-ui'; Basic Tour
Show code
let open = $state(false);
let ref1, ref2, ref3;
const steps: TourStepDef[] = [
{ target: () => ref1, title: 'Upload', description: 'Upload a file.' },
{ target: () => ref2, title: 'Save', description: 'Save changes.' },
{ target: () => ref3, title: 'More', description: 'Extra options.' },
];
<Button bind:element={ref1}>Upload</Button>
<Button bind:element={ref2}>Save</Button>
<Button bind:element={ref3}>More</Button>
<Button onclick={() => open = true}>Begin Tour</Button>
<Tour bind:open {steps} />Placement
Show code
<Tour steps={[{ target: () => el, placement: 'top' }]} />Non-modal (mask=false)
Show code
<Tour bind:open mask={false} type="primary" steps={steps} />Custom Gap
Show code
<Tour gap={{ offset: 12, radius: 8 }} steps={steps} />Controlled State
Step: 0
Show code
let open = $state(false);
let step = $state(0);
<Tour bind:open bind:current={step} steps={steps} />
<Button onclick={() => { step = 1; open = true; }}>Jump to Step 2</Button>Tour Props
| Prop | Type | Default | Description |
|---|---|---|---|
| steps required | TourStepDef[] | — | Array of step definitions. |
| open | boolean | false | Whether the tour is visible. Bindable. |
| current | number | 0 | Active step index. Bindable. |
| onClose | () => void | — | Called when the tour is dismissed. |
| onChange | (current: number) => void | — | Called when the step changes. |
| mask | boolean | true | Show dimmed mask overlay with target cutout. |
| type | 'default' | 'primary' | 'default' | Card color scheme. |
| gap | { offset?: number; radius?: number } | { offset: 6, radius: 4 } | Highlight area gap around the target element. |
| arrow | boolean | true | Show arrow pointing from card to target. |
| placement | TourPlacement | 'bottom' | Default placement for all steps. |
| zIndex | number | 350 | z-index of the tour overlay layer. |
| scrollIntoViewOptions | boolean | ScrollIntoViewOptions | true | Scroll targets into view before showing. |
| disabledInteraction | boolean | false | Block interaction with highlighted element. |
| indicatorsRender | Snippet<[current, total]> | — | Custom step indicator renderer. |
TourStepDef
| Prop | Type | Default | Description |
|---|---|---|---|
| target | () => HTMLElement | null | — | Element to highlight. Omit for center-screen placement. |
| title | string | — | Step title. |
| description | string | — | Step description text. |
| cover | Snippet | — | Cover content (image/video) above the title. |
| placement | TourPlacement | — | Override placement for this step. |
| mask | boolean | — | Override global mask setting for this step. |
| scrollIntoView | boolean | ScrollIntoViewOptions | — | Override scroll behavior for this step. |
| nextButtonText | string | — | Custom "Next" / "Finish" button label. |
| prevButtonText | string | — | Custom "Previous" button label. |
Usage tips
- Use
bind:openandbind:currentto control the tour externally. - Each step’s
targetis a function returning anHTMLElement— usebind:elementon buttons ordocument.getElementById. - Omitting
target(or returning null) centers the card on screen — useful for intro/welcome steps. - Set
mask=falsewithtype="primary"for a non-modal tour that doesn’t block interaction. - The
gapprop controls the highlight cutout padding (offset) and corner rounding (radius) around the target. - Keyboard:
Escapecloses,ArrowLeft/ArrowRightnavigate steps. - Set
disabledInteractionwhen you want the highlighted control read-only while still visually emphasizing it. - Turn off
arrowfor dense layouts where the pointer would collide with nearby UI; combine withtype="primary"for contrast. - Raise
zIndexif other overlays (command palette, modal) share the same stacking context and occlude the tour.