Skip to content

feat: Guided Tours Custom Navigation#2340

Draft
camielvs wants to merge 1 commit into
06-02-feat_guided_tours_foundationfrom
05-29-feat_guided_tours_navigation_dots_track_progress
Draft

feat: Guided Tours Custom Navigation#2340
camielvs wants to merge 1 commit into
06-02-feat_guided_tours_foundationfrom
05-29-feat_guided_tours_navigation_dots_track_progress

Conversation

@camielvs

@camielvs camielvs commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Description

Replaces reactour's default Prev/Next with a custom tour navigation and the interactive-step UX layer that sits on top of it: progress dots, a completion-gated "Next", an action checklist in the popover, and auto-progress. Visible behavior becomes observable once the registry has tours (#2306 onwards).

What's in it

Custom navigation

  • Progress dots between Prev and Next, one per step, colored by visit state (current / visited / unvisited). Non-clickable — bouncing between arbitrary steps would leave reactour inconsistent on tours with interaction gates.
  • The furthest-reached step is tracked at module level so the indicator survives popover remounts and stays accurate on tours that swap step content via setSteps.
  • Visit-aware Next: a "Next" text label on the furthest-reached step, a chevron-only button on revisits.

Step completion + gated "Next"

  • TourProgressContext tracks per-step completion (a Set of completed step indices), reset whenever a tour opens.
  • On an interactive step, "Next" is disabled until the step's interaction is reported complete (the editor bridge in feat: Guided Tours Framework (Navigating the Editor) #2299 reports completion). On non-interactive steps, and on already-complete/revisited steps, it's enabled.

Action checklist

Auto-progress

  • TourAutoAdvance advances ~800ms after a fresh completion — long enough to see the tick register. Steps already complete on arrival (e.g. revisited via Back) stay on a manual click; clicking "Next" advances immediately and cancels the pending auto-advance.

File layout

  • Navigation components live in TourNavigation.tsx (TourNavigation, NavButton, GatedNextButton/renderNextButton, TourStepChecklist, TourAutoAdvance, and the module-level visit-tracking helpers).
  • TourPopover.tsx keeps popover styling/positioning, the viewport clamp bridge, and the completion actions.
  • TourProgressContext.tsx holds the completion state + useTourProgress hook. Tests: TourNavigation.test.tsx and TourProgressContext.test.tsx.

Popover polish

  • The navigation row fills the popover width, and the checklist is spaced from the step content above it.

Related Issue and Pull requests

Progresses https://github.com/Shopify/oasis-frontend/issues/583

Depends on #2348 (foundation). The interaction detection that drives completion lands in #2299; interaction-specific checklist labels are authored in #2299 / #2347 / #2365.

Type of Change

  • New feature

Checklist

  • I have tested this does not break current pipelines / runs functionality
  • I have tested the changes on staging

Test Instructions

With a tour registered (use this branch with #2306 on top):

Dots

  • Step through the tour. Each dot fills in as you reach it — current is enlarged + saturated, visited is lighter blue, unvisited is zinc-gray. Clicking a dot does nothing (intentionally disabled).

Checklist + gated Next

  • On an interactive step (e.g. step 7's "click the Greet task"), a checklist row shows the required action and "Next" is disabled.
  • Complete the action — the row ticks (check animation + strike-through) and, after ~800ms, the tour auto-advances. Clicking "Next" while it's enabled advances immediately.
  • A step whose action is already satisfied on arrival shows pre-checked with "Next" enabled.

Visit-aware Next + revisits

  • On the furthest step reached, "Next" shows a text label; stepping back via Prev collapses it to a chevron. Revisited (already-complete) steps do not auto-advance — they wait for a manual click.

Reset between tours

  • Finish a tour, return to /learn/tours, start a different one. Completion + visited-max reset for the new tour.

@github-actions

github-actions Bot commented May 29, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: 05-29-feat_guided_tours_navigation_dots_track_progress/0090034

camielvs commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

@camielvs camielvs mentioned this pull request May 29, 2026
3 tasks
@camielvs camielvs added the #gsd:50583 Learning Hub label May 29, 2026 — with Graphite App
@camielvs camielvs changed the title feat: Guided Tours Navigation Dots Track Progress feat: Guided Tours Custom Navigation May 29, 2026
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch 2 times, most recently from 7f83eb8 to 9899ee2 Compare May 29, 2026 19:18
@camielvs camielvs force-pushed the 05-20-feat_learning_hub_tour_framework_and_first_tour branch from 84f39e0 to d6d13ae Compare May 29, 2026 19:24
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from 9899ee2 to a773cce Compare May 29, 2026 19:24
@camielvs camielvs force-pushed the 05-20-feat_learning_hub_tour_framework_and_first_tour branch from d6d13ae to e97b036 Compare May 29, 2026 21:22
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from a773cce to b9acf61 Compare May 29, 2026 21:22
@camielvs camielvs mentioned this pull request May 29, 2026
3 tasks
@camielvs camielvs force-pushed the 05-20-feat_learning_hub_tour_framework_and_first_tour branch from e97b036 to d308ae7 Compare May 29, 2026 21:29
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch 2 times, most recently from 9b16f8f to fadf84a Compare May 29, 2026 22:33
@camielvs camielvs force-pushed the 05-20-feat_learning_hub_tour_framework_and_first_tour branch 2 times, most recently from 95b9b2a to 01da4c7 Compare May 29, 2026 23:19
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from fadf84a to 5cd15ef Compare May 29, 2026 23:19
@camielvs camielvs force-pushed the 05-20-feat_learning_hub_tour_framework_and_first_tour branch from 01da4c7 to d9c0e95 Compare May 29, 2026 23:34
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch 2 times, most recently from 9e7059e to 7753fca Compare June 3, 2026 19:30
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from 07b002a to 2262436 Compare June 3, 2026 19:35
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from 7753fca to 89a72fe Compare June 3, 2026 19:36
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from 2262436 to d83a715 Compare June 3, 2026 19:43
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from 89a72fe to aa3fba7 Compare June 3, 2026 19:43
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from d83a715 to dd40a33 Compare June 3, 2026 19:50
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from aa3fba7 to febd689 Compare June 3, 2026 19:51
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from dd40a33 to 47cfe52 Compare June 3, 2026 19:56
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from febd689 to 68175d1 Compare June 3, 2026 19:57
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from 47cfe52 to 606887b Compare June 3, 2026 20:02
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from 68175d1 to aaa1a46 Compare June 3, 2026 20:02
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from 606887b to d29cf67 Compare June 3, 2026 20:08
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch 2 times, most recently from 6b7ed93 to af8b204 Compare June 3, 2026 22:40
@camielvs camielvs force-pushed the 06-02-feat_guided_tours_foundation branch from d29cf67 to 5455cd2 Compare June 3, 2026 22:40
@camielvs camielvs force-pushed the 05-29-feat_guided_tours_navigation_dots_track_progress branch from af8b204 to 7938fe4 Compare June 4, 2026 18:58
Comment thread src/providers/TourProvider/TourNavigation.tsx
targetSearchTerm?: string;
targetArgumentName?: string;
targetMinCount?: number;
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This is an AI-generated code review comment.

Duplicated step-target type shape (project-conventions — extract duplicated definitions)

This ChecklistStep enumerates the same target* fields as TourActionLabelInput in tourActionLabels.ts, and tourActionLabel(interactiveStep) is already called with a ChecklistStep. The two will drift as new interaction targets are added. Both files are new in this PR, so it's the right time to unify.

Fix: type ChecklistStep = StepType & TourActionLabelInput; (import TourActionLabelInput) — single source of truth for the target fields.

const Button = props.Button as FC<PropsWithChildren<NavButtonProps>>;

const hiddenPlaceholder = (
<span aria-hidden style={{ visibility: "hidden", pointerEvents: "none" }}>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This is an AI-generated code review comment.

Inline static style (project-conventions — inline style only for dynamic/computed values)

style={{ visibility: "hidden", pointerEvents: "none" }} is fully static → use Tailwind: className="invisible pointer-events-none". Carried over from the old renderNextButton, but this file is new/extracted here so it's fair to fix now.

<InlineStack
gap="2"
blockAlign="center"
className="rounded-md bg-slate-50 px-3 py-2"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This is an AI-generated code review comment.

Hardcoded palette colors vs tone/tokens (ui-primitives)

bg-slate-50 here and text-zinc-400 / text-zinc-500 line-through / text-green-600 on the checklist Icon/Text use raw palette classes. Prefer the semantic equivalents: the checklist Texttone="subdued", bg-slate-50bg-muted. (The text-blue-*/text-zinc-* on the dot Badge variant="dot" below are decorative state colors — leave those if no token fits.)

recordTourVisited(currentStep);
const visited = getTourVisitedMax();

const NavButton: FC<PropsWithChildren<NavButtonProps>> = ({

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This is an AI-generated code review comment.

Component defined inside render (react-patterns)

NavButton is declared in TourNavigation's render body, so it gets a new component identity every render and the nav buttons remount each time. Low impact here (stateless leaves, and reactour's render-prop API nudges this shape), but hoisting it to module scope and passing currentStep/disableAll/rtl as props would avoid the churn.


// Runtime Button is always TourNavigation's NavButton (which accepts
// `disabled`); reactour's narrower type omits it.
const Button = props.Button as FC<PropsWithChildren<NavButtonProps>>;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This is an AI-generated code review comment.

as casts — informational, no change needed (typescript-standards)

props.Button as FC<...> (line 35) and step as ChecklistStep (line 105) are as casts, which typescript-standards generally discourages. Both work around genuine limitations in reactour's narrower third-party types, and the Button cast carries a clear WHY comment. Flagging only for completeness — these are acceptable as-is.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type narrowing

@camielvs camielvs mentioned this pull request Jun 15, 2026
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

#gsd:50583 Learning Hub

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant