Skip to content

Tour spotlight ​

A guided tour that cuts a hole in a dimmed page around each element it is talking about.

Open in demo
Open in demo

Usage ​

TourSpotlight takes no props and is mounted once near the root. A page defines its own tour with useTour({ id, steps }) and calls start().

Each step names a CSS selector. The overlay finds that element, scrolls it to the middle of the screen, and draws the cutout around it. If the selector matches nothing, it retries on the next frame, which covers an element that is still rendering; if it still matches nothing, that step shows no overlay rather than pointing at the wrong thing.

The cutout follows the element. A ResizeObserver, plus scroll and resize listeners, keep the hole on the target while the layout moves under it.

TourStep ​

KeyTypeDescription
targetstringA CSS selector for the element to highlight.
titlestringThe tooltip's heading.
descriptionstringThe tooltip's body.
position'top' | 'bottom' | 'left' | 'right'Where the tooltip sits. Defaults to bottom.

Completion ​

useTour remembers which tours have been finished, in localStorage under sa-tours, keyed by the tour's id.

CallWhat it does
start()Opens the tour at step one, whether or not it was finished before.
end()Tears the overlay down without marking it done.
reset()Forgets that this tour was finished.
isCompletedtrue once Skip or the last Finish has been pressed.

The split between end() and completion is deliberate. end() runs on unmount, so navigating away mid-tour cannot permanently suppress it. Only finishing it or skipping it counts.

Use isCompleted to decide whether to start a tour automatically for a first-time reader.

The overlay ​

The backdrop and the cutout are one positioned element with a very large box-shadow, rather than an SVG mask. It is cheap and it moves as one thing.

The overlay takes no pointer events, so the tour never blocks the page; only the tooltip captures clicks. It sits above dialogs, so a tour can point at something inside one.

API ​

Source: src/shared/components/common/TourSpotlight.vue, src/shared/composables/useTour.ts

Props ​

None.

Emits ​

None.

Slots ​

None.

Accessibility ​

  • The tooltip is real text in the page, not a title attribute, so it can be read and zoomed.
  • Skip, Back and Next are ordinary buttons in the tab order. The last step's button reads Finish, so the end is not a surprise.
  • Because the overlay takes no pointer events, a reader can still use the page while the tour is open rather than being trapped in it.
  • The tooltip is capped at the viewport width less a margin, so it never runs off the side of a phone.
  • The highlight is a ring in the primary color as well as a hole in the dimming, so the target is marked by more than brightness alone.