Skip to content

feat(ui): add interactive product tour with react joyride#3655

Open
adithyaakrishna wants to merge 9 commits intosimstudioai:stagingfrom
adithyaakrishna:feat/product-tour
Open

feat(ui): add interactive product tour with react joyride#3655
adithyaakrishna wants to merge 9 commits intosimstudioai:stagingfrom
adithyaakrishna:feat/product-tour

Conversation

@adithyaakrishna
Copy link

@adithyaakrishna adithyaakrishna commented Mar 18, 2026

Summary

  • Add a guided product tour for first-time users using React Joyride
  • The tour starts on the Home page (chat input, templates, sidebar) and continues into the workflow editor (canvas, toolbar, copilot, run/deploy)
  • Auto-starts on first login, re-triggerable via Help > "Take a tour" in the sidebar

Type of Change

  • New feature

Testing

  • Clear sim-tour-completed-v1 from localStorage to re-trigger auto-start
  • Click Help > "Take a tour" in the sidebar footer to re-trigger manually
  • Verify tour shows only relevant steps per page (home steps on /home, editor steps on /w/[id])
  • Verify steps with missing targets are skipped gracefully
  • Verify spotlight shows a transparent cutout with subtle border, not a filled box

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Screenshots/Videos

screen-capture.14.webm

@vercel
Copy link

vercel bot commented Mar 18, 2026

@adithyaakrishna is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@cursor
Copy link

cursor bot commented Mar 18, 2026

PR Summary

Medium Risk
Adds a new Joyride-based overlay and persistence/trigger logic that affects core workspace navigation and workflow editor UI, plus extends the shared Popover component; regressions could impact layout/interaction across pages.

Overview
Adds an interactive, first-run product tour in the workspace using react-joyride, with two flows: a navigation/sidebar tour (NavTour) and a workflow-editor tour (WorkflowTour) backed by a shared useTour hook (localStorage completion, smooth step transitions, and manual retrigger via custom event).

Wires the tours into the app layouts (WorkspaceLayout, workflow layout) and annotates key UI elements with data-* selectors so steps can target them; also adds a Help dropdown entry (Take a tour) that dispatches start-workflow-tour.

Introduces a new EMCN TourTooltip/TourCard component and supporting Tailwind animations, and extends PopoverContent with optional arrow rendering (showArrow, arrowClassName). Updates dependencies/lockfile to include react-joyride (and overrides for React peer deps).

Written by Cursor Bugbot for commit fd51d05. This will update automatically on new commits. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 18, 2026

Greptile Summary

This PR adds an interactive product tour using React Joyride for first-time users. The tour spans 13 steps across the home page and workflow editor, auto-starts on first login, and can be re-triggered via Help > "Take a tour" in the sidebar. The implementation uses a custom TourTooltip backed by Radix UI's Popover with a virtual anchor for precise positioning, and the tour state is persisted in localStorage.

Key observations:

  • Cross-page step skipping: All 13 steps are in a flat array spanning two routes. Since there is no navigation between pages, users who trigger the tour from the workflow editor silently skip all 6 home-page steps (and vice versa), making the tour effectively page-scoped rather than the cross-page experience described in the PR.
  • Orphaned data-tour attributes: data-tour="new-workflow", data-tour="panel-menu", and data-tour="run-button" are added to DOM elements but do not correspond to any step in tour-steps.ts.
  • Fragile sidebar selectors: Steps 3–5 use bare CSS class selectors (.sidebar-container, .workflows-section) instead of the data-tour attribute pattern used by every other step, making them vulnerable to CSS refactoring.
  • refCallback ref-forwarding bug: The hasSetRef guard in TourTooltip has inverted timing with the effect reset, causing joyride's internal ref to be null after each step transition. This is currently harmless because joyride's floater is hidden, but is a latent correctness issue.
  • Accessibility: The invisible refDiv forwards aria-modal from joyride's tooltip props, which would declare an empty zero-size element as a modal dialog to screen readers.

Confidence Score: 3/5

  • The PR introduces a useful first-time onboarding flow with no critical runtime errors, but has a UX design gap (cross-page step skipping), orphaned data attributes, fragile CSS selectors, and a latent ref-forwarding bug in the tooltip.
  • No breaking changes or security issues, and the new ProductTour component is isolated from core workflow logic. The main concern is the fragmented tour experience (users on the editor never see home steps) which contradicts the PR's stated intent. The ref bug in TourTooltip is currently dormant. Orphaned data-tour attributes are dead code. These collectively keep the score at 3 — mergeable with fixes.
  • Pay close attention to product-tour.tsx (cross-page skipping logic), tour-tooltip.tsx (hasSetRef timing and aria-modal forwarding), tour-steps.ts (CSS class selectors for steps 3–5), and panel.tsx / sidebar.tsx (orphaned data-tour attributes).

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/components/product-tour/product-tour.tsx Core tour orchestrator: manages run/stepIndex state, auto-start on first login, and manual re-trigger via custom event. The retrigger timer is now correctly tracked via a ref. However, the callback handler silently skips all cross-page steps with no user navigation, meaning users on the workflow editor never see home-page steps.
apps/sim/app/workspace/[workspaceId]/components/product-tour/tour-tooltip.tsx Custom tooltip renderer using Radix Popover with a virtual anchor for positioning. The hasSetRef guard has inverted timing logic that leaves joyride's internal ref as null after each step change. Also forwards aria-modal to an invisible zero-size div, which creates an accessibility concern.
apps/sim/app/workspace/[workspaceId]/components/product-tour/tour-steps.ts Defines all 13 tour steps spanning both the home page and workflow editor. Steps 3–5 use bare CSS class selectors (.sidebar-container, .workflows-section) inconsistent with the data-tour="..." pattern used elsewhere, making them fragile to refactoring.
apps/sim/app/workspace/[workspaceId]/layout.tsx Mounts ProductTour inside WorkspacePermissionsProvider in the workspace layout, giving it lifetime across all workspace routes. Clean integration.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx Adds the "Take a tour" button in the Help section and dispatches START_TOUR_EVENT. Also adds a data-tour="new-workflow" attribute to the + button that has no matching tour step in tour-steps.ts.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx Adds data-tab-button attributes (toolbar/copilot/editor) for tour targeting and data-tour="deploy-run". Also adds data-tour="panel-menu" and data-tour="run-button" which have no matching tour steps — orphaned attributes.
apps/sim/components/emcn/components/popover/popover.tsx Adds arrowClassName prop to PopoverContent and showArrow support with a custom SVG arrow. Well-structured addition to the existing CVA-based component, consistent with existing prop patterns.

Sequence Diagram

sequenceDiagram
    participant Layout as WorkspaceLayout
    participant PT as ProductTour
    participant LS as localStorage
    participant Joyride as Joyride (dynamic)
    participant TT as TourTooltip
    participant Sidebar as Sidebar
    participant Win as window

    Layout->>PT: mount (on workspace load)
    PT->>LS: isTourCompleted()?
    alt first-time user
        LS-->>PT: false
        PT->>PT: setTimeout(1200ms) → setRun(true), stepIndex=0
        PT->>Joyride: run=true, stepIndex=0
        Joyride->>TT: render step tooltip
        TT->>TT: querySelector(step.target)
        alt target found
            TT->>TT: createPortal(Popover, document.body)
        else target not found (cross-page step)
            Joyride-->>PT: callback(TARGET_NOT_FOUND)
            PT->>PT: setStepIndex(index + 1) — silent skip
        end
        Note over PT,Joyride: User clicks Next/Back/Skip/Done
        Joyride-->>PT: callback(STEP_AFTER / FINISHED / SKIPPED)
        PT->>LS: markTourCompleted()
        PT->>PT: setRun(false)
    else returning user
        LS-->>PT: true → no auto-start
    end

    Sidebar->>Win: dispatchEvent(START_TOUR_EVENT)
    Win-->>PT: handleStartTour()
    PT->>LS: resetTourCompletion()
    PT->>PT: setRun(false) → setTourKey(k+1) → setTimeout(50ms) → setRun(true)
Loading

Last reviewed commit: "chore: updated modal..."

@icecrasher321
Copy link
Collaborator

@waleedlatif1 will assign you as review for this one

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants