import { CoachmarkTour } from '@uhg-abyss/web/ui/Coachmark';Running a tour
CoachmarkTour is a provider component that wraps the content of your page and provides the context for the Coachmarks within the tour. The tour's active state is controlled by the startTour prop, which is a boolean. If startTour is true, the tour will begin. To end the tour, set startTour to false. Typically, this only needs to occur in the onSkip and onFinish callbacks.
Global callbacks
The CoachmarkTour provider accepts three callbacks that are triggered at various points in the tour:
onStart: Called when the tour starts.onSkip: Called when the user skips the tour by clicking the close button. The 1-indexed current step number is passed as an argument.onFinish: Called when the user finishes the tour.
These can be used to provide extra functionality at these points, such as logging or analytics tracking.
Note: Each step also has its own callbacks for when the user clicks the "Next" or "Previous" buttons, which can be used to provide extra functionality at those points as well. See the Callbacks section below for more details.
Default variant
The variant prop controls the appearance of all Coachmarks in the tour. The valid values are 'gray' and 'white'. The default is 'white'.
Note: Individual steps can override this default by setting their own variant prop.
Footer
The footer of a Coachmark contains the step count and the "Next" and "Previous" buttons. This footer will always be visible if there are multiple steps in the tour and will be removed if there is only a single step.
Overlay
Use the overlay prop to add an overlay with a cutout highlighting the target elements in the tour. The default value is false.
Steps
Use the steps prop to provide an array of steps for the tour. Each step is an object that contains the following required properties:
target: A CSS selector that identifies the element to highlight during the tour.title: The title of the Coachmark.description: The description of the Coachmark.
These and the other optional properties are described in more detail below.
The order of the elements in the steps array determines the order in which the Coachmarks will be displayed during the tour, regardless of the order of the elements in the DOM, giving you full control over the flow of the tour.
Target and content
The target value is a CSS selector that identifies the element to highlight during the tour. It can be any valid query selector that uniquely identifies an element on the page. If the selector does not match any elements on the page, the Coachmark will not be displayed for that step.
Note: The examples on this page use the useAbyssId hook to generate unique IDs for the elements. You are free to use any method you'd like to generate the selectors.
The title and description properties are used to set the content of the Coachmark. description is always required, but title is optional.
Use the extraContent prop to add any extra content you'd like below the description.
Variant
The variant prop controls the appearance of the Coachmark. The valid values are 'gray' and 'white'. The default is 'white'.
Note: The variant prop in the step definition overrides the default variant set by the CoachmarkTour provider.
Position
Use the position prop to change the position of the Coachmark relative to its target. The valid options are 'top', 'right', 'bottom', and 'left'. The default value is 'top'.
Note: The Coachmark will automatically reposition itself to stay within the viewport. This may result in the Coachmark not appearing on the side defined by the position prop and/or not being center-aligned with the target element. Additionally, the use of 'right' and 'left' on mobile screens is highly discouraged; prefer using 'top' and 'bottom' instead. The example below shows one method of achieving this.
Callbacks
Use the onNext and onPrevious props to provide extra functionality when the user navigates through the tour. These callbacks are called when the user clicks the "Next" or "Previous" buttons in the Coachmark, respectively.
Note: Additional callbacks are handled by the CoachmarkTour provider.
Full example
CoachmarkTour Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
children | React.ReactNode | - | The children of the CoachmarkTour | |
className | string | - | - | CSS class name to apply to each element within the component |
css | Abyss.CSSProperties | Partial<Record<`abyss-${T}`, Abyss.CSSProperties>> | - | - | Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation |
data-testid | string | - | - | Suffix used to create a unique ID used for automated testing |
disableDefaultProviderProps | boolean | false | - | If set to true, the component will not use the DefaultPropsProvider values. If you aren’t using the DefaultPropsProvider, this prop can be ignored. |
onFinish | () => void | - | - | Callback executed when the tour is finished |
onSkip | (currentStep?: number | undefined) => void | - | - | Callback executed when the tour is skipped |
onStart | () => void | - | - | Callback executed when the tour is started |
overlay | boolean | false | - | If true, the target elements will be highlighted with an overlay |
startTour | boolean | false | - | If true, the tour will start |
steps | Step[] | - | The steps in the tour | |
variant | "white" | "gray" | 'white' | - | The color variant of the Coachmark components in the tour. This value can be overridden by individual steps. |
Coachmark Classes
| Class Name | Description |
|---|---|
| .abyss-coachmark-anchor | Coachmark anchor |
| .abyss-coachmark-portal | The portal container |
| .abyss-coachmark-root | The root coachmark container |
| .abyss-coachmark-layout-wrapper | Wrapper for managing layout of title and close button |
| .abyss-coachmark-title | Coachmark title |
| .abyss-coachmark-close-button | Coachmark close button |
| .abyss-coachmark-close-icon | Coachmark close button icon |
| .abyss-coachmark-content-container | Coachmark body content |
| .abyss-coachmark-arrow | Coachmark arrow notch |
| .abyss-coachmark-footer | Coachmark footer container |
| .abyss-coachmark-step-count | Coachmark step count indicator |
| .abyss-coachmark-button-container | Coachmark footer button container |
Implementation
There is no explicit WAI-ARIA design pattern for this component.
- Steps are updates to single modal dialog
aria-labelledbyis set to<h2>(thetitleprop) and included off-screen step locationaria-describedbyis set to contents (thedescriptionprop)
- Step (dialog) announcement is triggered by setting focus to close button to announce:
- Heading content
- Description Content
- Close button
- Navigation between steps
- Blurs dialog
- Updates dialog content
- Resets focus on close button
- UX design: Keyboard focus operation is not same as ModalDialog
- By design, tours do not return keyboard focus to starting point, such as "start tour" button below
- Exiting the tour sets keyboard focus on the last item highlighted whether using the close button, finishing the tour, or pressing the Escape key
- Includes normally non-focusable content
- Example: The large icons below are not in tab order but receive focus on exit
Known screen reader issues
Though dialog implementation is standard, announcement and operation is inconsistent across different screen readers and browsers (BrATs).
Testing as of 7/16/2025
- JAWS + Chrome: Works as designed
- NVDA + Chrome: Works "mostly" as designed, with extra announcements
- First step announced twice
- Second time is full dialog content including footer content
- Subsequent steps announce as intended but include trigger element
- Example: The above example includes "Start Tour button expanded"
- First step announced twice
- NVDA + Edge: In Forms (pass-through) mode (only) - Works as designed
- Non-responsive to keyboard in browser mode
- VO + Safari: Functional, but announcement is poor
- Keyboard operation is correct but only "Close button" is announced
- User must manually explore contents
- Works with keyboard but content updates (
aria-labelledby,aria-describedby) never announced - Failed F12 experiments included: Adding
aria-liveto dialog do not address issue
Component Tokens
Note: Click on the token row to copy the token to your clipboard.
Coachmark Tokens
| Token Name | Value | |
|---|---|---|
| coachmark.color.border.light | #CBCCCD | |
| coachmark.color.icon.dark.active | #E5E5E6 | |
| coachmark.color.icon.dark.hover | #F3F3F3 | |
| coachmark.color.icon.dark.rest | #FFFFFF | |
| coachmark.color.icon.light.active | #000000 | |
| coachmark.color.icon.light.hover | #323334 | |
| coachmark.color.icon.light.rest | #4B4D4F | |
| coachmark.color.surface.dark | #4B4D4F | |
| coachmark.color.surface.light | #FFFFFF | |
| coachmark.color.surface.overlay | rgba(0,0,0,0.4) | |
| coachmark.color.text.heading.dark | #FFFFFF | |
| coachmark.color.text.heading.light | #323334 | |
| coachmark.color.text.paragraph.dark | #FFFFFF | |
| coachmark.color.text.paragraph.light | #4B4D4F | |
| coachmark.color.text.step-count.dark | #FFFFFF | |
| coachmark.color.text.step-count.light | #4B4D4F | |
| coachmark.border-radius.all.container | 8px | |
| coachmark.border-radius.all.overlay-cutout | 4px | |
| coachmark.border-width.all.container | 1px | |
| coachmark.sizing.all.icon | 24px | |
| coachmark.spacing.gap.horizontal.footer | 8px | |
| coachmark.spacing.gap.horizontal.header | 16px | |
| coachmark.spacing.gap.vertical.container | 16px | |
| coachmark.spacing.gap.vertical.text | 2px | |
| coachmark.spacing.padding.all.container | 16px | |
| coachmark.spacing.padding.all.overlay-cutout | 4px | |
| coachmark.spacing.padding.notch-to-edge | 8px | |
| coachmark.spacing.padding.notch-to-target | 4px | |
| coachmark.elevation | 0px 6px 8px -2px rgba(0,0,0,0.16) |