feat: Add guided tour component library using react-joyride v3#1226
feat: Add guided tour component library using react-joyride v3#1226YoavLev wants to merge 3 commits intocadence-workflow:masterfrom
Conversation
| <Button | ||
| size="mini" | ||
| kind="tertiary" | ||
| shape="square" | ||
| aria-label="Close tour" | ||
| onClick={() => controls.skip()} | ||
| overrides={overrides.closeButton} | ||
| > | ||
| <MdClose size={14} /> | ||
| </Button> |
There was a problem hiding this comment.
⚠️ Quality: Tooltip buttons don't spread joyride's built-in a11y props
The custom tooltip calls controls.skip(), controls.next(), controls.prev() directly on click handlers instead of spreading backProps, primaryProps, closeProps, and skipProps from TooltipRenderProps. The react-joyride reference docs explicitly state: "Always spread button props on their respective buttons. This ensures correct accessibility attributes and action handling."
By bypassing these props, the buttons lose aria-label, data-action, role, and title attributes that joyride provides for accessibility and internal event tracking. This also means joyride's internal event flow (which triggers step:after hooks, analytics, etc.) may not fire correctly for button interactions.
Suggested fix:
<Button
{...closeProps}
size="mini"
kind="tertiary"
shape="square"
overrides={overrides.closeButton}
>
<MdClose size={14} />
</Button>
...
<Button {...backProps} size="compact" kind="secondary">Back</Button>
<Button {...primaryProps} size="compact" kind="primary">
{isLastStep ? 'Done' : 'Next'}
</Button>
Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion
There was a problem hiding this comment.
Does this applicable to te react-joyride version 3?
There was a problem hiding this comment.
Yes, this is still applicable in react-joyride v3. The TooltipRenderProps type in v3 includes the same backProps, primaryProps, closeProps, and skipProps — each carrying aria-label, data-action, onClick, role, and title attributes.
Details
Looking at the code, guided-tour-tooltip.types.ts already sets Props = TooltipRenderProps, so those props are available. However, the component only destructures controls, index, isLastStep, size, step, and tooltipProps — and calls controls.skip(), controls.next(), controls.prev() directly on the button click handlers.
Using controls.* bypasses joyride's own button props, which means:
- The buttons miss the
aria-label,data-action,role, andtitleattributes joyride sets onbackProps/primaryProps/skipProps/closeProps - Joyride's internal event tracking (e.g.
step:afterhooks) may not fire as expected
The fix would be to destructure and use the onClick from those props (e.g. backProps.onClick, primaryProps.onClick, skipProps.onClick) instead of controls.prev(), controls.next(), controls.skip() — or spread the full prop objects onto the respective buttons.
| export const GuidedTourContext = createContext<GuidedTourContextType>( | ||
| {} as GuidedTourContextType | ||
| ); |
There was a problem hiding this comment.
💡 Edge Case: Context default value will crash if used outside provider
The context is initialized with {} as GuidedTourContextType, so any component calling useContext(GuidedTourContext) outside a GuidedTourProvider will get an empty object. Accessing controls.start() will throw TypeError: Cannot read properties of undefined. Consider either providing a meaningful error or creating a useGuidedTour() hook that throws a descriptive error when the provider is missing.
Suggested fix:
export function useGuidedTour() {
const ctx = useContext(GuidedTourContext);
if (!ctx.controls) {
throw new Error('useGuidedTour must be used within a GuidedTourProvider');
}
return ctx;
}
Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion
| ```tsx | ||
| <GuidedTourProvider tourId="my-page-overview" steps={overviewSteps}> | ||
| <GuidedTourProvider tourId="my-page-new-feature" steps={featureSteps}> | ||
| {children} | ||
| </GuidedTourProvider> | ||
| </GuidedTourProvider> |
There was a problem hiding this comment.
💡 Edge Case: Nesting providers shadows outer tour's context
GUIDED_TOUR.md documents nesting multiple GuidedTourProvider components for multiple tours on one page, but they all use the same GuidedTourContext. The inner provider will shadow the outer one's controls, making it impossible for children to access the outer tour's controls via useContext. This is fine if children only need the innermost tour, but the docs don't mention this limitation. Consider documenting it or using per-tour context instances.
Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion
Add reusable guided tour components for creating product tours with BaseUI-styled tooltips and localStorage-based completion tracking. Components: - GuidedTourProvider: wraps useJoyride hook, manages auto-start on first visit, tracks completion per tourId in localStorage - GuidedTourTooltip: custom tooltip with BaseUI styling (Header, Body, Footer with progress and navigation) Includes GUIDED_TOUR.md with usage docs and code examples. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Yoav Levy <yoavlev2@gmail.com>
d6929c3 to
4c16853
Compare
Add reusable guided tour components for creating product tours with BaseUI-styled tooltips and localStorage-based completion tracking. Components: - GuidedTourProvider: wraps useJoyride hook, manages auto-start on first visit, tracks completion per tourId in localStorage - GuidedTourTooltip: custom tooltip with BaseUI styling (Header, Body, Footer with progress and navigation) Includes GUIDED_TOUR.md with usage docs and code examples. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Yoav Levy <yoavlev2@gmail.com>
275d571 to
01b07ee
Compare
Code Review
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
Summary
GuidedTourProvider,GuidedTourTooltip) built on react-joyride v3 with BaseUI stylingGUIDED_TOUR.mdwith usage docs, code examples, and targeting strategiesComponents
GuidedTourProvideruseJoyridehook, manages auto-start on first visit, tracks completion pertourIdin localStorageGuidedTourTooltipTest plan
npm run typecheck— no type errorsnpm run lint— no lint errors🤖 Generated with Claude Code
Screen.Recording.2026-03-24.at.11.42.01.mov