Tour
A guided product tour that spotlights one element at a time and explains it in a panel beside it.
c2-tour
Guided product tour: walks a user through a page one element at a time, dimming everything else and explaining the highlighted element in a panel beside it. Use it for onboarding and for introducing a new feature in place.
Each step is a c2-tour-step child naming its target (a CSS selector), a heading and the explanation as its
content. Put a button in the trigger slot, set open or call start() to begin; the panel offers Back, Next (Done on the last step) and a close
button, and shows the progress as "2 of 5". The target is scrolled into view when it is off screen, and the panel is
placed beside it by floating-ui, flipping to the other side when there is no room. A step without a target, or
whose target is missing, shows centred over the dimmed page.
The tour is a non-modal dialog in the top layer: the page stays interactive, so a step can ask the user to try
the highlighted control. Opening moves focus to Next; Escape (wherever focus is) and the close button end the tour early, and the
arrow keys move between steps while focus is in the panel. When it closes, focus returns to where it was before.
With a storage-key, the tour remembers in localStorage whether the user finished it, skipped it or got part
way, on which step, and how many times it was skipped (progress). Add autostart to open it by itself on the
first visit: it then resumes on the step it was left on, opens again from the first step after a skip, and stays
closed once finished or skipped skip-limit times (once, by default). skip-delay makes a skipped tour wait, say
a week, before it opens again. start() and the trigger always open it;
reset() forgets the stored progress.
Every tour a user ends fires exactly one finish (Done on the last step) or skip (Skip, the close button or Escape).
Moving between steps with the buttons, the keys or the methods fires step-change; setting open or current
from code fires only show / hide.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
open | boolean | false | Visible state. Set it, or call start(), to begin the tour; setting it fires show / hide but no finish or skip. |
current | number | 0 | Index of the step shown, from 0. Setting it moves the tour without firing step-change. |
placement | Placement | bottom | Preferred side of the target for the panel; a step's own placement wins. Flips when there is no room. |
storage-key | string | — | localStorage key under which the tour remembers its progress ({ "status", "step", "skips" }). Empty, nothing is
stored.
Use one key per tour, and a new key when a tour changes enough to be worth showing again. |
autostart | boolean | false | Opens the tour by itself when it is connected, unless the progress under storage-key says it was finished or
skipped skip-limit times. It resumes on the stored step, or on the first after a skip. Without a storage-key
it opens on every page load. |
skip-limit | number | 1 | How many skips turn autostart off for good. Below it, a skipped tour opens again from its first step on the next
load. 0 never gives up: the tour keeps opening until it is finished. |
skip-delay | string | — | How long a skipped tour waits before autostart opens it again: a number and a unit, 30m, 12h, 7d or 2w
(a bare number is days). Empty, it opens on the next load. Only matters while skip-limit allows another skip. |
Slots
| Name | Description |
|---|---|
(default) | The c2-tour-step elements, in order. Only the current step is shown, inside the panel. |
trigger | Optional button that starts the tour from its first step when clicked. It stays where the tour is placed. |
Events
| Name | Type | Description |
|---|---|---|
step-change | CustomEvent<TourStepChangeDetail> | The user, or a method, moved to another step. detail.index is the new step, detail.previous the old one. |
finish | Event | The user completed the tour with Done on the last step. |
skip | CustomEvent<TourSkipDetail> | The user ended the tour early with Skip, the close button or Escape. detail.index is the step it was closed on. |
show | Event | The tour opened. |
hide | Event | The tour closed. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
panel | The dialog beside the target. |
arrow | The arrow pointing at the target. Hidden on a centred step. |
spotlight | The highlighted cut-out around the target; its shadow dims the rest of the page. |
header | The row holding the heading and the close button. |
heading | The current step's heading. |
close | The button that ends the tour early. |
body | The region wrapping the default slot: it shows the current c2-tour-step, assigned to it, and has no fallback content. |
footer | The row holding the progress and the navigation buttons. |
progress | The "2 of 5" progress text. |
skip | The Skip button, which ends the tour early. Hidden on the last step. |
previous | The Back button. Hidden on the first step. |
next | The Next button, which reads Done on the last step. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-tour--background-color | background-color | #ffffff | |
--c2-tour--color | color | #18181b | |
--c2-tour--border | border | 1px solid #e4e4e7 | |
--c2-tour--border-radius | border-radius | 8px | |
--c2-tour--box-shadow | box-shadow | 0 8px 24px rgba(24, 24, 27, 0.08) | |
--c2-tour--font-size | font-size | 14px | |
--c2-tour--font-family | font-family | — | |
--c2-tour--line-height | line-height | 1.5 | |
--c2-tour--padding | padding | 16px | |
--c2-tour--width | pixel | 320px | Width of the panel; it never grows past the viewport. |
--c2-tour--offset | pixel | 8px | Distance between the spotlight and the tip of the arrow. |
--c2-tour--transition-duration | time | 200ms | Fade of the panel and the spotlight's move between steps. |
--c2-tour--enter-transform | transform | scale(0.96) | Start of the panel's enter animation. |
--c2-tour__arrow--size | pixel | 10px | Side of the arrow square; 0px hides it. |
--c2-tour__backdrop--color | color | rgba(9, 9, 11, 0.45) | Colour that dims the page around the spotlight; transparent keeps the page undimmed. |
--c2-tour__spotlight--padding | pixel | 8px | Space between the target and the edge of the spotlight. |
--c2-tour__spotlight--border-radius | border-radius | 8px | |
--c2-tour__spotlight--outline | outline | 2px solid rgba(2, 101, 220, 0.4) | Ring drawn around the spotlight. |
--c2-tour__heading--color | color | — | Defaults to the panel text colour. |
--c2-tour__heading--font-size | font-size | 14px | |
--c2-tour__heading--font-weight | font-weight | 600 | |
--c2-tour__body--color | color | #71717a | |
--c2-tour__body--margin-top | pixel | 4px | |
--c2-tour__close--size | pixel | 24px | |
--c2-tour__close--color | color | #71717a | |
--c2-tour__close--border-radius | border-radius | 4px | |
--c2-tour__close__hover--background-color | background-color | #f4f4f5 | |
--c2-tour__footer--margin-top | pixel | 16px | |
--c2-tour__footer--gap | pixel | 8px | |
--c2-tour__progress--color | color | #71717a | |
--c2-tour__progress--font-size | font-size | 12px | |
--c2-tour__button--height | pixel | 32px | |
--c2-tour__button--padding-left | padding | 12px | |
--c2-tour__button--padding-right | padding | 12px | |
--c2-tour__button--border-radius | border-radius | 6px | |
--c2-tour__button--font-size | font-size | 14px | |
--c2-tour__button--font-weight | font-weight | 500 | |
--c2-tour__button__focus--outline | outline | 2px solid rgba(2, 101, 220, 0.4) | Also the close button's focus ring. |
--c2-tour__button__focus--outline-offset | pixel | 2px | |
--c2-tour__skip--display | display | inline-flex | none removes the Skip button; the close button still skips. |
--c2-tour__skip--color | color | #71717a | |
--c2-tour__skip__hover--background-color | background-color | #f4f4f5 | |
--c2-tour__previous--background-color | background-color | transparent | |
--c2-tour__previous--color | color | #18181b | |
--c2-tour__previous--border | border | 1px solid #bcbcc6 | |
--c2-tour__previous__hover--background-color | background-color | #f4f4f5 | |
--c2-tour__next--background-color | background-color | rgb(2, 101, 220) | |
--c2-tour__next--color | color | #ffffff | |
--c2-tour__next--border | border | 1px solid transparent | |
--c2-tour__next__hover--background-color | background-color | rgb(1, 84, 184) | |
Text and languages
The text the component shows, in English. It shows another language when the app adds one with addTranslations, under tour, and the nearest lang asks for it; any message not translated stays in English. {0}, {1}… stand for the values a message carries. Languages guide.
| Key | English | Values |
|---|---|---|
label | Tour | — |
next | Next | — |
previous | Back | — |
done | Done | — |
skip | Skip | — |
close | Close tour | — |
progress | {0} of {1} | {0} index {1} count |
c2-tour-step
One step of a c2-tour: the element it points at, a heading and the text that explains it. The step draws nothing
on its own; its tour shows the current step inside its panel, beside the highlighted target.
target is a CSS selector, looked up from the tour's root (the document, or the shadow root the tour sits in) when
the step is shown. A step without a target, or whose target is missing or not rendered, shows centred on a fully
dimmed page: use one for a welcome or closing step.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
target | string | — | CSS selector of the element this step highlights. Empty, or matching nothing visible, the step shows centred. |
heading | string | — | The step's title, shown at the top of the panel and used as its accessible name. |
placement | Placement | undefined | — | Preferred side of the target for the panel, overriding the tour's placement; flips when there is no room. |
Slots
| Name | Description |
|---|---|
(default) | The step's explanation: a sentence, a list, an image. It is the tour panel's accessible description. |