Rendering and accessibility
Define the host, dialog behavior, interaction modes, and styling boundary.
Rendering and accessibility
One host
An application renders one <TourHost />. The host renders the overlay, card,
arrow, and Vue content. A second host produces a development error instead of a
second control plane.
The default card must be good enough to ship. The #actions and #progress
slots replace individual sections. The #card slot replaces the complete card
body and takes precedence over both section slots. Stable
data-tour-part attributes and a small set of CSS custom properties support
visual theming without freezing internal DOM structure.
The package does not accept raw HTML strings. Rich content uses Vue components.
The package does not accept configured button arrays. The default card owns the
normal actions. The final step shows Finish without Skip, because Finish and the close control
already end the tour. It also shows Previous when an earlier step exists. An actions slot or full-card slot owns custom actions.
Section slots receive TourSectionSlotProps: the existing card context plus
the resolved labels. Custom actions must respect pending and handle rejected
command promises. The host retains the default content and close button when
only a section is replaced.
Interaction modes
An interactive tour card is a dialog, not an ARIA tooltip.
modalprevents background interaction, traps focus, and usesaria-modal="true".targetkeeps the card and the current target interactive. The dialog is not modal.pagekeeps the page generally interactive. The dialog is not modal.
The package must not use aria-modal="true" only because an overlay is visible.
Keyboard and focus
The default keyboard contract is Tab, Shift+Tab, Escape, and visible buttons. Safari follows the operating system's full-keyboard-access preference, so its Tab order can omit buttons when that preference is disabled. Nuxt Tour respects the browser's order and still keeps any focusable tour target inside the active focus scope. Left and right arrows are not global shortcuts because they conflict with editors, sliders, menus, grids, and text controls.
When a modal step opens, focus moves to a useful heading or card control. A maintained focus engine keeps focus inside the card. Target mode treats the card and highlighted target as one focus scope and makes unrelated subtrees inert. Nested widgets receive Escape before the tour. When the tour ends, focus returns to the invoking element when that element still exists.
Positioning and motion
Floating UI is the intended positioning dependency. Nuxt Tour exposes common placement and spacing concepts, not the full middleware configuration. The dependency is added only with the positioning implementation.
Overlay geometry and card positioning are separate internal systems. Version 1 supports one spotlight hole: the current target. Multiple highlighted targets wait until a real journey proves the extra SVG geometry and browser test cost.
The backdrop stays mounted while the tour changes steps. Nearby, fully visible targets share one opening that moves and resizes over 160–280 ms, based on distance. Redirection preserves position and velocity. When the page scrolls or its layout changes during travel, the whole path moves with the page. The opening does not jump to its destination and does not start again. The private frame routine writes only the spotlight element; it does not rerender Vue content per frame. The card and arrow translate and fade on one shared surface at the destination. Target interaction becomes available when the opening is aligned. Pointer blocking uses actual target geometry, never the opening's intermediate position.
On start, the opening is closed and the card hidden before the first reveal.
Route changes and scrolling keep a covered geometry handoff. Smooth scrolling starts
immediately while the old opening closes. An instant scroll, which includes
reduced motion, starts only after the old card is hidden. scroll: false permits travel without
scrolling. With scroll: { block: 'nearest', inline: 'nearest' }, a target already
inside its scroll containers needs no scroll or covered handoff. Default centered alignment is preserved. When that alignment already needs
no movement, the runtime can use continuous travel without an unnecessary cover.
The command completes when the destination is positioned and usable. Decorative
opacity can finish afterward. Escape, host removal, reduced-motion changes, and
hidden documents must not leave stale frames or unresolved visual waits.
The backdrop starts as soon as the tour starts. A destination spotlight opens
when its target is close and slow enough. Native smooth scrolling keeps the
travel distance adaptive without a second scrolling engine.
prefers-reduced-motion removes movement while preserving state and focus
behavior. The default theme follows the operating-system color scheme and also
recognizes .light, .dark, and matching data-theme application themes.
The arrow has a rounded tip and shares the card's background and border. Its
clearance follows the card radius and --tour-arrow-size. Default spacing leaves
12 CSS pixels beyond the spotlight padding and arrow reach. A step gap
changes this clear space. An explicit step
offset retains its target-to-card meaning. An arrow that cannot
point accurately is hidden. Centered steps have no arrow.
Cards fit the available positioning space and scroll internally when needed. Interactive targets remain clear of the card. A modal card can overlap a large highlighted region when no external side has enough room; its arrow is hidden when that overlap makes pointing misleading. After a modal card appears, it stays on its side when scrolling or resizing changes the available room. It moves to another side only when that side has enough room. Centered cards follow the visual viewport, including its offset during zoom or keyboard use. A wait for the application that lasts more than 400 ms shows visible loading text and a cancel control. The tour's own scrolling is visible progress and does not count as a wait. The loading text announces itself as a status. It receives focus only when no card exists yet. Escape also works before the first card is rendered.
The visual spotlight includes --tour-spotlight-padding so the target's focus
ring is not dimmed. Pointer isolation still uses the target's real rectangle.
Accessibility evidence
Automated release tests cover dialog naming, focus containment, nested Escape,
focus restoration, inert, target interaction, reduced motion, dark mode, and
Chromium, Firefox, WebKit, mobile Chromium, and mobile WebKit projects. These
checks do not replace assistive-technology testing. A release must not claim a
manual NVDA, VoiceOver, or mobile screen-reader pass until that dated check is
recorded by a human.
Reference standard
Implementation follows the WAI-ARIA dialog pattern. Tooltip semantics are not valid for a card that contains buttons or other focusable content.
Cancellation and motion ownership
Modal pointer and focus isolation starts with the first covered frame, before preparation or the loading message. The geometry and hit areas remain separate. Cancelling stops every scroll container owned by the current tour operation at its current position. Early reveal does not release scroll ownership; cancellation and reduced-motion changes remain active until actual container movement settles.
The cover handshake observes owned opacity transitions, ignores unrelated
animations, and has a bounded wait. A paused consumer animation cannot stall a
controller command. Tour cancellation and finish end the tour immediately:
focus returns and the page receives input at once. The departing backdrop and
card are inert and hidden from assistive technology while they fade out over
100 ms. Reduced motion and motion: 'none' remove them without a fade.
The default backdrop and delayed loading feedback use a brief opacity entrance.
The backdrop and card leave with a shorter opacity exit.
Reduced motion removes spatial effects, including button press transforms. An
application can select motion: 'none' to remove all tour-owned effects. Native
scroll and resize tracking remain direct; targets never trail behind user scrolling.