Skip to main content

Coachmark

A temporary message that guides a user through a new or unfamiliar experience.

Submit feedback
github
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.

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

NameTypeDefaultRequiredDescription
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

See CSS Prop Styling for more information
data-testid
string
--
Suffix used to create a unique ID used for automated testing

See Component Testing for more information
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.

Below are the link(s) to the relevant GitHub type files:

Abyss.d.ts

Coachmark Classes

Class NameDescription
.abyss-coachmark-anchorCoachmark anchor
.abyss-coachmark-portalThe portal container
.abyss-coachmark-rootThe root coachmark container
.abyss-coachmark-layout-wrapperWrapper for managing layout of title and close button
.abyss-coachmark-titleCoachmark title
.abyss-coachmark-close-buttonCoachmark close button
.abyss-coachmark-close-iconCoachmark close button icon
.abyss-coachmark-content-containerCoachmark body content
.abyss-coachmark-arrowCoachmark arrow notch
.abyss-coachmark-footerCoachmark footer container
.abyss-coachmark-step-countCoachmark step count indicator
.abyss-coachmark-button-containerCoachmark footer button container

Implementation

There is no explicit WAI-ARIA design pattern for this component.

  • Steps are updates to single modal dialog
    • aria-labelledby is set to <h2> (the title prop) and included off-screen step location
    • aria-describedby is set to contents (the description prop)
  • 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"
  • 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-live to dialog do not address issue

Component Tokens

Note: Click on the token row to copy the token to your clipboard.

Coachmark Tokens

Token NameValue
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)
Table of Contents