Skip to content

Tour ​

Step-by-step feature onboarding with a fullscreen overlay and target highlighting. Supports 12-direction placement with overflow flipping, scroll-following repositioning, mask/form customization, keyboard navigation, async steps, hints beacons and a "Don't show again" memory.

Basic usage ​

Start the tour

Start tour
Highlighted area 1
Highlighted area 2

Tour events ​

oas-step carries detail: { index, current, total, next, prev }; closing events (cancel/finish/close/skip/destroy) carry detail: { index, total } (oas-cancel additionally carries a source identifying the cancel origin).

Step events

Start tourNot started
Highlighted area 1
Highlighted area 2

Controlled step and visibility ​

Both open and current are controlled attributes: an external button / JS sets open to start the tour, and sets current to jump directly to a given step (no need to click through).

Controlled open / current

Start tour (set open)Jump to step 2 (current=1)Jump to step 3 (current=2)Finish (remove open)
Controlled highlight area 1
Controlled highlight area 2
Controlled highlight area 3

Placement and arrow ​

placement supports 12 directions (top/bottom/left/right × start/end/center) plus center; it auto-flips along the main axis when space is insufficient. arrow="false" hides the arrow.

12 directions and auto-flip

Right placement (placement=right)Auto-flip at bottomNo arrow (arrow=false)
Right placement target
Multi-direction target
Bottom target (viewport edge)

Scroll to target and repositioning ​

When the target is off-screen the tour scrolls to it (scroll-into-view-options is passed through; scroll-padding sets the target's scroll-margin). During the tour the highlight and popup follow scroll/resize automatically (auto-reposition, enabled by default).

Scroll to target and scroll-follow

Start tour (target below the fold)
Below-the-fold target 1 (scrolled to)
Below-the-fold target 2

Overlay and form ​

mask="false" disables the overlay (non-modal; the rest of the page stays interactive during the tour); mask='{"color":"..."}' customizes the overlay color; type="primary" uses a primary-colored popup for emphasis; gap controls the highlight padding and radius (a number or {padding, radius}).

Non-modal + primary popup

Non-modal + primary popupCustom overlay color
Non-modal highlight 1
Non-modal highlight 2

Keyboard navigation and indicators ​

keyboard (enabled by default) advances steps with ←/→; show-bullets renders clickable dot indicators; show-progress shows a top progress bar; progress-text is a template (placeholders current/total, each wrapped in double curly braces) for custom counter text; indicators="number" shows a numeric counter.

Keyboard + dots + progress bar

Start tour (keyboard + dots + progress)Disable keyboard navigation
Keyboard target 1
Keyboard target 2
Keyboard target 3

Button visibility and pass-through props ​

hide-prev / hide-skip / hide-next / hide-counter control button/counter visibility; next-button-props / prev-button-props / skip-button-props pass arbitrary attributes to their buttons (JSON object). The last step's Finish is the next button (its label switches); on that step finish-button-props is layered on top of next-button-props (step-level wins).

Button visibility and props

Visibility + propsHide all actions
Button customization target 1
Button customization target 2

Close button customization ​

show-close="false" hides the close button; close-icon replaces its content with arbitrary HTML.

Close button customization

Custom close iconNo close button
Close button target

Overlay click and highlight interaction ​

mask-click-behavior: close (default) / next (advance on overlay click) / none (ignore); target-area-clickable makes the highlight area interactive (clicks pass through); disabled-interaction blocks interaction with the highlighted area; advance-on-click advances when the highlight area is clicked ("try it here" interactive tours).

Overlay click behavior + highlight interaction

Overlay click advancesOverlay click ignoredHighlight interactiveHighlight blockedClick highlight to advanceButton inside target not clicked yet
Highlight interaction target 1 Click me to verify interaction
Highlight interaction target 2

Async steps ​

wait-for-element (ms) waits for the target to appear (e.g. "the previous step opened a dialog, wait for its inner element to render"); skip-missing-element skips the step when the target is missing / the wait times out.

Wait for async targets and skip

Wait for async targetSkip missing target
Regular target

Dialog mode ​

mode="dialog" (or step-level mode: "dialog") renders a centered dialog step without a target as a first-class step type.

Dialog mode

Start tour

Lifecycle events ​

oas-highlight-start fires as soon as the step index changes (before any async target wait), while oas-highlight-end fires once the highlight has been positioned (positioning only happens after the async target wait resolves); oas-destroy fires when the tour closes (including external removal of open).

Lifecycle events

Start tourNo events yet
Lifecycle target 1
Lifecycle target 2

Don't show again and multi-page tours ​

With dont-show-again, checking "Don't show this again" on close remembers the choice via storage-key; the next start is blocked and oas-dismiss fires. persist persists open/current state so a remount after route changes resumes the tour (multi-page tours).

Don't show again

Open tour (blocked once remembered)Clear memory
Memory target

Multi-page tour (persist)

Start tourSimulate route change (remount)
Multi-page target 1
Multi-page target 2

Typewriter and scroll lock ​

typewriter (opt-in, off unless set) + typewriter-speed reveal the description character by character; lock-scroll locks page scrolling during the tour; close-on-press-escape="false" disables Esc.

Typewriter animation + scroll lock

Start tour
Typewriter target 1 (with cover image)
Typewriter target 2

Hints beacon mode ​

hints renders persistent pulsing beacons (no open needed); clicking a beacon opens a bubble. Hints with dismissable + id are remembered in localStorage (oas-tour-hint-${id}) and hidden afterwards.

Hints beacon mode

Beacon target 1 (dismissable)
Beacon target 2 (persistent)

Mount point and z-index ​

append-to="body" (or a selector) mounts the whole overlay into the given container; z-index customizes the stacking level.

Mount point and z-index

append-to body + high z-index
Mount target

Advanced customization (dual-axis gap / arrow aiming / no auto-reposition) ​

gap supports a dual-axis offset (number for all sides / [horizontal, vertical] array, orthogonal to padding); arrow-point-at-center keeps the arrow pointing at the target center after viewport avoidance shifts the popup; auto-reposition="false" disables overflow flipping and viewport avoidance (keeps the declared placement).

Dual-axis gap + arrow at center + no auto-reposition

Dual-axis gap offsetArrow at centerNo auto-reposition
Dual-axis gap target
Left-edge target
Bottom target (viewport edge)

Custom indicators and actions (slots) ​

slot="indicators" replaces the built-in dots/number indicator (render with the current/total from the oas-step event); slot="actions" replaces the whole built-in button area with your own controls.

Custom indicators and actions

Start tour1 / 2
PreviousNext
Custom slot target 1
Custom slot target 2

API ​

oas-tour ​

Attributes ​

AttributeDescriptionTypeDefault
advance-on-clickClick the highlighted area to advance to the next step (interactive tour)boolean—
append-toMount point: body or a CSS selector (moves the whole overlay into the target container)string—
arrowWhether to show the arrow (boolean, default true; false hides)stringtrue
arrow-point-at-centerArrow points to the target center projection (stays accurate after viewport avoidance shifts the popup; by default the arrow sticks to the placement edge)boolean—
auto-repositionAuto reposition on scroll/resize + overflow flip/viewport avoidance (default true; false keeps the declared placement without flipping or avoidance)stringtrue
close-iconCustom close button content (HTML string)string—
close-on-press-escapeClose on Esc (default true)stringtrue
currentCurrent step indexstring0
disabled-interactionDisable interaction on the highlighted area (interceptor covers target)——
dont-show-againDon't show again switch (boolean; if checked on close, remembered in localStorage)boolean—
finish-button-propsPass-through props for the last-step Finish button (JSON): on the last step the next button is the Finish button, so finish-button-props is layered on top of next-button-props (step-level wins)——
gapHighlight padding: number (padding px) or {"padding","radius","offset"}; offset expands the highlight outward (number for all sides / [horizontal, vertical] dual-axis, orthogonal to padding); default padding 4string—
hide-counterHide the step counterboolean—
hide-nextHide the next button——
hide-prevHide the previous button——
hide-skipHide the skip button——
hintsHints beacon mode: JSON [{id,selector,title,description,placement,dismissable}]; persistent pulsing beacons, click to open a bubble, dismissable is remembered after closestring[]
indicatorsCounter style: dots (default) / number / nonestringdots
keyboardKeyboard ←/→ to advance steps (default true; false disables)stringtrue
lock-scrollLock page scrolling during the tour (restored on close)boolean—
maskOverlay switch/customization: false to disable (non-modal) or {"color","style"} to customize (default true); step-level overridestringtrue
mask-click-behaviorOverlay click behavior: close (default) / next (advance) / none (ignore)stringclose
modePopup mode: popup (default) / dialog (centered dialog without target); step-level overridestringpopup
next-button-propsProps passed through to the next button (JSON object, e.g. {"data-x":"1"})——
openStart the tour (boolean attribute; starts when present)boolean—
persistMulti-page tour: open/current state persisted to localStorage and restored on reconnectboolean—
placementPopup placement: 12 directions (top/bottom/left/right × start/end/center) + center (centered when no target); default bottom; auto-flips when space is insufficient; step-level overrideTourPlacementbottom
prev-button-propsProps passed through to the previous button (JSON object)——
progress-textProgress text template: current/total placeholders each wrapped in double curly braces; when set, the counter area uses the templatestring—
scroll-into-view-optionsscrollIntoView options for scrolling to the target (JSON; default {"behavior":"smooth","block":"center"})string—
scroll-paddingPadding when scrolling to the target (px; applied as target scroll-margin)——
show-bulletsDot indicators (click a dot to jump)boolean—
show-closeShow the close button (default true; false hides)stringtrue
show-progressProgress bar at the top of the popup (width advances with steps)boolean—
skip-button-propsProps passed through to the skip button (JSON object)——
skip-missing-elementSkip the step when the target is missing / wait times out (default stays on the current step)boolean—
stepsSteps JSON (TourStep[] | string); property assignment supports function/element targetsTourStep[] | string[]
storage-keylocalStorage key (shared by dont-show-again / persist / hint dismiss)stringoas-tour-dismiss
target-area-clickableHighlight area is interactive (opt-in): off unless set (the interceptor covers the target so it is not clickable); when set the interceptor is hidden and clicks pass through to the targetstring—
typePopup type: default / primary (primary-colored popup for non-modal emphasis)stringdefault
typewriterTypewriter animation (opt-in): off unless set; when set, the description is revealed character by character (typewriter="false" disables)string—
typewriter-speedTypewriter speed (ms per character, default 20)string20
wait-for-elementWait for the target to appear (ms, async steps; global default, step-level waitForElement wins)——
z-indexOverlay z-index (default --oas-z-modal)——

Events ​

EventDescription
oas-cancelSkipped / Esc / overlay click, detail: { index, total, source } (source: skip/esc/close/mask)
oas-closeClose button clicked, detail: { index, total }
oas-destroyTour closed (including external removal of open), detail: { index, total }
oas-dismissDon't show again matched; tour start was blocked, detail: {}
oas-finishFinish was clicked on the last step, detail: { index, total }
oas-highlight-endStep highlight completed, detail: { index, total }
oas-highlight-startStep highlight started (after async wait resolves), detail: { index, total }
oas-skipSkip button clicked, detail: { index, total }
oas-stepStep changed, detail: { index, current, total, next, prev }

Slots ​

NameDescription
actionsCustom action area (replaces the whole built-in button area; hides the built-in prev/skip/next buttons when present)
coverStep cover rich content (slot takes precedence over the step.cover image)
indicatorsCustom indicator area (render with the oas-step current/total; hides the built-in dots/number indicator when present)

CSS Variables ​

CSS VariableDefault
--oas-glass-blurnone
--oas-glass-ringtransparent
--oas-tour-arrow-align-offset16px
--oas-tour-arrow-height12px
--oas-tour-arrow-radius0
--oas-tour-arrow-width12px
--oas-tour-mask-colorvar(--oas-color-overlay)
--oas-tour-popup-bgvar(--oas-color-bg)

The overlay highlights the target, role="dialog" + aria-modal="true" (downgraded to aria-modal="false" in non-modal form when mask="false"); supports "Previous / Next / Skip", keyboard ←/→ and Esc.

Released under the MIT OR Apache-2.0 License.