Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
211 commits
Select commit Hold shift + click to select a range
d581a3b
Fix invalid story specifier for non-story pages (e.g. settings)
ghengeveld Oct 22, 2025
4c9e929
Prevent pages from scrolling beyond the layout container (shifting th…
ghengeveld Oct 22, 2025
e662368
Add Collapsible and FocusProxy components
ghengeveld Oct 22, 2025
b0fbf3c
Pull Card component out of TestingModule and make it more generic
ghengeveld Oct 22, 2025
0ff85f0
Add generic Listbox component and allow Button to be used as label
ghengeveld Oct 22, 2025
5110838
Add Guided Tour page and ChecklistModule
ghengeveld Oct 22, 2025
e7ca5c1
UI tweaks
ghengeveld Oct 22, 2025
b91e701
TypeScript fix
ghengeveld Oct 22, 2025
3b384b4
Merge branch 'next' into onboarding-checklist
ghengeveld Nov 4, 2025
f473e21
Rename 'Guided tour' to 'Guide'
ghengeveld Oct 23, 2025
69cc7ba
Add support for task dependencies and update ChecklistModule to show …
ghengeveld Oct 23, 2025
ce5ebc0
Change ChecklistModule based on progress
ghengeveld Oct 23, 2025
4cd3631
Support custom action button label
ghengeveld Oct 23, 2025
bd55f1e
Allow muting the ChecklistModule, either permanently or for a particu…
ghengeveld Oct 23, 2025
c89bce5
Change selection of items in the ChecklistModule
ghengeveld Oct 27, 2025
02c9aca
Tweak spacing for visual consistency
ghengeveld Oct 27, 2025
d685d12
Make ChecklistModule collapsible and fix card shadow styling
ghengeveld Oct 27, 2025
489113d
Split Card 'All' story into separate stories
ghengeveld Oct 27, 2025
e23d3f9
Drop superfluous initialCollapsed arg for Collapsible
ghengeveld Oct 27, 2025
b7e60c5
Hide ChecklistModule in prod mode
ghengeveld Oct 27, 2025
46081e5
Support providing useCollapsible state to Collapsible
ghengeveld Oct 27, 2025
b92f735
Animate closing of last checklist task
ghengeveld Oct 27, 2025
2e65137
Fix a11y issue
ghengeveld Oct 27, 2025
6c633c4
Don't show Guide page in production mode
ghengeveld Oct 27, 2025
91a3519
Fix visual snapshot for FocusProxy
ghengeveld Oct 27, 2025
770baf7
Prevent showing empty checklist on first render when all tasks are co…
ghengeveld Oct 27, 2025
84440e2
Move ChecklistModule above search and fix Explorer stories to show th…
ghengeveld Oct 27, 2025
36e688a
Revert "Tweak spacing for visual consistency"
ghengeveld Oct 27, 2025
385066d
Fix sidebar spacing
ghengeveld Oct 27, 2025
7c51785
More flexible component API
ghengeveld Oct 27, 2025
1a917a3
Collapse spacing when ChecklistModule is hidden
ghengeveld Oct 27, 2025
36df52d
Drop useless story
ghengeveld Oct 28, 2025
69eac58
Add progress indicator, animate progress value changes and add menu t…
ghengeveld Oct 28, 2025
5d1b37e
Centralize hashchange detection and add several FocusRing utility com…
ghengeveld Oct 28, 2025
9f8bf34
Add story for GuidePage and hoist store/state up from Checklist to Gu…
ghengeveld Oct 28, 2025
7db2e15
Update sidebar menu to use Listbox components and put What's new last…
ghengeveld Oct 28, 2025
0e109db
Pull checklist logic out into a hook
ghengeveld Oct 28, 2025
4289e0e
Fix progress updates for guide in sidebar menu
ghengeveld Oct 28, 2025
000cae7
Refactor checklist state management to use accepted and done properti…
ghengeveld Oct 30, 2025
076adee
Fix import
ghengeveld Oct 30, 2025
c5cc465
Fix collapsible state
ghengeveld Oct 31, 2025
0f5f1a6
Avoid passing unsupported attribute to SVG
ghengeveld Oct 31, 2025
894f311
Don't show link to onboarding guide in prod mode
ghengeveld Oct 31, 2025
f5f0ad8
Add missing key prop
ghengeveld Oct 31, 2025
dcfe2fc
Avoid conditional hook call
ghengeveld Oct 31, 2025
49492f0
Avoid NodeJS type in client-side file
ghengeveld Oct 31, 2025
2a2eb6c
Fix type errors and story data
ghengeveld Oct 31, 2025
b82881f
Simplify TextFlip component
ghengeveld Oct 31, 2025
4c0104f
Use ref to track latest text value so onAnimationEnd always syncs wit…
ghengeveld Oct 31, 2025
8030fc3
Fix numeric sorting
ghengeveld Oct 31, 2025
230577e
Fix invalid nesting of buttons
ghengeveld Oct 31, 2025
405b934
Fix invalid DOM nesting
ghengeveld Oct 31, 2025
1eea810
Update checklist according to latest proposal
ghengeveld Oct 30, 2025
8e471bf
Update checklistData according to latest concept
ghengeveld Nov 1, 2025
c0eb34b
Handle narrow width for ChecklistModule by introducing an Optional co…
ghengeveld Nov 1, 2025
94c5c62
Update checklist criteria and checks
ghengeveld Nov 3, 2025
5f1bd57
Persist autocompleted items in node_modules/.cache and add telemetry
ghengeveld Nov 4, 2025
5ba33eb
Support conditional guide items
ghengeveld Nov 4, 2025
9d28bb0
Use simpler navigation API
ghengeveld Nov 4, 2025
cd97967
Add guided tour and intent survey to checklist
ghengeveld Nov 4, 2025
10917ad
Show completion message instead of mute toggle when all tasks are com…
ghengeveld Nov 4, 2025
589f1f0
Prevent onboarding from returning to splash screen
ghengeveld Nov 4, 2025
624bfc6
Fix build command
ghengeveld Nov 4, 2025
5845f57
Prevent guided tour from showing intent survey if it has already been…
ghengeveld Nov 4, 2025
1411869
Ensure subscription callback is a function
ghengeveld Nov 4, 2025
70914fe
Revert back to using ReactDOM.render
ghengeveld Nov 5, 2025
af5996a
Completion detection for install-vitest and run-tests tasks
ghengeveld Nov 6, 2025
571eb37
Don't skip checklist tasks when closing tour tooltip
ghengeveld Nov 6, 2025
da9c7b8
Better looking code blocks
ghengeveld Nov 6, 2025
8a27b33
Fix mocks
ghengeveld Nov 6, 2025
2adfb83
Add items for installing dependencies
ghengeveld Nov 6, 2025
870ab94
Use createRoot rather than deprecated ReactDOM.render
ghengeveld Nov 7, 2025
d6e6f09
Fix testing widget overflow to allow highlighting for onboarding
ghengeveld Nov 7, 2025
85b9fa1
Reduce update frequency by throttling index updates
ghengeveld Nov 7, 2025
8c5c660
Pass index to available function to receive updates, and don't pass i…
ghengeveld Nov 7, 2025
02917c4
Make content a function
ghengeveld Nov 7, 2025
073778c
Ignore example stories where appropriate
ghengeveld Nov 7, 2025
bc7ac39
Prevent clicking on underlying collapse toggle when using checklist r…
ghengeveld Nov 7, 2025
9aef937
Fix addon identifier
ghengeveld Nov 7, 2025
e311a22
Rename Tour to TourGuide and make it a generic component
ghengeveld Nov 7, 2025
1f79889
Make renderTourGuide a static method on the TourGuide component
ghengeveld Nov 7, 2025
1c8bb66
Fix GuidePage sidebar toggle
ghengeveld Nov 7, 2025
056a80f
Refactor onboarding components: consolidate HighlightElement and Tour…
ghengeveld Nov 10, 2025
f0dfab7
Refactor useChecklist to provide all data needed in Checklist component
ghengeveld Nov 12, 2025
d9df904
Animate the completion of a checklist item in the widget
ghengeveld Nov 12, 2025
2fd404c
Animate strikethrough
ghengeveld Nov 13, 2025
bb87ae0
Hide certain checklist items once completed, and update API for items…
ghengeveld Nov 13, 2025
7591d75
Reset itemIndex to only include ready items, in order to fix round-ro…
ghengeveld Nov 13, 2025
88afdc1
Hide action buttons in checklist module unless hovering the item
ghengeveld Nov 13, 2025
64c5d96
Update FocusProxy to use a data attribute rather than id attribute
ghengeveld Nov 13, 2025
c2eaf69
Merge branch 'next' into onboarding-checklist
ghengeveld Nov 13, 2025
c051458
Merge branch 'onboarding-checklist' into onboarding-guide
ghengeveld Nov 13, 2025
760764f
Merge branch 'onboarding-guide' into checklist-tasks
ghengeveld Nov 13, 2025
e49e0ba
Replace react-transition-group with react-transition-state
ghengeveld Nov 14, 2025
f367ae4
Fix TS type issue
ghengeveld Nov 14, 2025
990d21e
Merge branch 'onboarding-checklist' into onboarding-guide
ghengeveld Nov 14, 2025
eb45f76
Handle review comments
ghengeveld Nov 14, 2025
3cac5c1
Fix type shenanigans
ghengeveld Nov 14, 2025
e6456e2
Merge pull request #32874 from storybookjs/onboarding-guide
ghengeveld Nov 14, 2025
bc804e3
Merge branch 'onboarding-checklist' into checklist-tasks
ghengeveld Nov 14, 2025
aad4c79
Remove storybook/internal/manager/manager-stores
ghengeveld Nov 14, 2025
48c0efb
Merge pull request #32799 from storybookjs/checklist-tasks
ghengeveld Nov 14, 2025
a38f6f0
Typecheck fixes
ghengeveld Nov 14, 2025
d8293cb
Update progress calculation in useChecklist to handle zero available …
ghengeveld Nov 14, 2025
6327559
Enhance equality check in checklist utility to ensure key length matc…
ghengeveld Nov 14, 2025
f329817
Handle checklist initialization errors
ghengeveld Nov 14, 2025
858d2a1
Move manager components out of core
ghengeveld Nov 14, 2025
7217660
Refactor onboarding and checklist components to import TourGuide and …
ghengeveld Nov 14, 2025
d8e826e
Refactor checklist store management by creating a dedicated `createCh…
ghengeveld Nov 14, 2025
2977758
Add missing story context
ghengeveld Nov 14, 2025
aecbc3b
Fix bad content
ghengeveld Nov 15, 2025
8990d19
Avoid inline styles
ghengeveld Nov 15, 2025
9dcb0da
Ensure play function waits for timeouts
ghengeveld Nov 15, 2025
8189bb1
Keep collapsed while loading
ghengeveld Nov 15, 2025
ab25430
Remove duplicate tooltip
ghengeveld Nov 15, 2025
5a83618
Fix ariaLabel props
ghengeveld Nov 15, 2025
31255a1
Only animate opacity
ghengeveld Nov 15, 2025
05d50a0
Reduce timeout
ghengeveld Nov 15, 2025
e54c910
Fix invalid keys
ghengeveld Nov 15, 2025
4af5c3a
Fix sidebar menu tests, keep it open for toggle actions and fix docum…
ghengeveld Nov 15, 2025
d7e0a57
Fix e2e test for fullscreen toggle
ghengeveld Nov 15, 2025
32ee70d
Close menu when hiding sidebar
ghengeveld Nov 15, 2025
c75648e
Fix E2E tests for menu toggles
ghengeveld Nov 15, 2025
0ffd1f7
Update fullscreen toggling test logic for proper order of actions
ghengeveld Nov 16, 2025
659e860
Properly close settings menu
ghengeveld Nov 16, 2025
a3b63a3
No need for refs in deps
ghengeveld Nov 16, 2025
90a716c
Remove nonexistent keys
ghengeveld Nov 16, 2025
5fa9a01
Avoid deleting nonexistent items
ghengeveld Nov 16, 2025
b51a36d
Suppress some warnings during test
ghengeveld Nov 16, 2025
2e80f98
Share play function between stories
ghengeveld Nov 16, 2025
505e7ec
Fix contrast
ghengeveld Nov 16, 2025
df04cb7
Use proper heading level
ghengeveld Nov 16, 2025
48a1bc8
Clean up and ignore example stories
ghengeveld Nov 16, 2025
2eda64c
Merge branch 'next' into onboarding-checklist
ghengeveld Nov 16, 2025
b9437f2
Fix type
ghengeveld Nov 16, 2025
81cf1f2
Avoid locator conflict
ghengeveld Nov 16, 2025
5be3a1f
align usage of Fragment to rest of repo
ndelangen Nov 17, 2025
b753270
align usage of ReactNode to rest of repo
ndelangen Nov 17, 2025
e00e1ee
Update code/vitest-setup.ts
ghengeveld Nov 17, 2025
46cc469
Ignore error stack trace in Chromatic
ghengeveld Nov 16, 2025
1defe4c
A cleaner way to disable onboarding search param
ghengeveld Nov 17, 2025
fb4f186
Use compound component pattern
ghengeveld Nov 17, 2025
331d34d
Merge styles
ghengeveld Nov 17, 2025
35fa041
Add step definitions
ghengeveld Nov 17, 2025
f0ac445
Linting
ghengeveld Nov 17, 2025
8f91857
Use useId from react-aria instead of react to maintain React 17 compa…
ghengeveld Nov 17, 2025
50b98b6
Wrap interpolate-size in feature detection media query
ghengeveld Nov 17, 2025
135a375
Respect disabled prop
ghengeveld Nov 17, 2025
72e49a8
Remove unused react-transition-group styles
ghengeveld Nov 17, 2025
68ef860
Remove unused outlineStyles prop
ghengeveld Nov 17, 2025
2e876cc
Remove unused outlineStyles prop
ghengeveld Nov 17, 2025
703de3e
Add docblock
ghengeveld Nov 17, 2025
21e2d4a
Fix story styles
ghengeveld Nov 17, 2025
f4de5b2
Fix story styles
ghengeveld Nov 17, 2025
baa9d8b
Merge branch 'next' into onboarding-checklist
ndelangen Nov 17, 2025
87b19f3
Ensure proper ARIA behavior for readOnly button
ghengeveld Nov 17, 2025
ec29889
Fix ARIA attributes for readOnly button handling
ghengeveld Nov 17, 2025
2df3d62
Avoid inline identifiers (use constants instead) and fix autodetectio…
ghengeveld Nov 17, 2025
cba209c
Merge branch 'next' into onboarding-checklist
ndelangen Nov 17, 2025
a585c45
Content styling
ghengeveld Nov 17, 2025
15cc514
Add support for asset URLs in getDocsUrl util
ghengeveld Nov 17, 2025
5d7f60a
Fix getDocsUrl to use 'asset' parameter and add corresponding tests
ghengeveld Nov 17, 2025
941600c
Remove invalid and unnecessary role attribute for readOnly buttons
ghengeveld Nov 17, 2025
4e8d31d
No point in snapshotting an animation
ghengeveld Nov 17, 2025
499a8a9
Set fixed height for story to avoid flake
ghengeveld Nov 17, 2025
d88ac22
Increase height so particles always fit
ghengeveld Nov 17, 2025
839b6a7
Mark dependent steps as skipped if one of their ancestors is skipped
ghengeveld Nov 17, 2025
0baca2b
fix bundle size
ndelangen Nov 17, 2025
3a02ac2
Merge branch 'next' into onboarding-checklist
ndelangen Nov 17, 2025
7eaa90f
Update content
kylegach Nov 18, 2025
e0ea357
Update checklist hierarchy styles
kylegach Nov 18, 2025
b29a44a
Merge branch 'next' into onboarding-checklist
ndelangen Nov 18, 2025
75f3867
Avoid marking completed items as skipped
ghengeveld Nov 18, 2025
9b509a7
Merge branch 'next' into onboarding-checklist
ndelangen Nov 18, 2025
6122ed5
Fix cursor for clickable rows
ghengeveld Nov 18, 2025
1760149
Rename TestingModule and ChecklistModule to TestingWidget and Checkli…
ghengeveld Nov 18, 2025
499b583
Merge branch 'next' into onboarding-checklist
ndelangen Nov 19, 2025
cbbeb47
Merge branch 'next' into onboarding-checklist
ghengeveld Nov 19, 2025
4caa1e1
Remove unused prop which was replaced by the Listbox.HoverItem component
ghengeveld Nov 19, 2025
d6f26a6
Remove stray import
ghengeveld Nov 19, 2025
44543da
Add stopPropagation() to prevent nested action button from triggering…
ghengeveld Nov 19, 2025
50bba49
Revert key rename to avoid breaking change
ghengeveld Nov 19, 2025
d0cb3b7
Ensure state update is immutable
ghengeveld Nov 19, 2025
131ecbb
Store checklist state as single object rather than arrays
ghengeveld Nov 19, 2025
27a8514
Update how checklist updates are tracked
ghengeveld Nov 19, 2025
4baf5db
Only log telemetry message once
ghengeveld Nov 19, 2025
679e4a6
Merge branch 'next' into onboarding-checklist
ndelangen Nov 20, 2025
dc8603e
Rework telemetry notification to ensure it is logged only once and im…
ghengeveld Nov 20, 2025
c141c98
wip
ghengeveld Nov 20, 2025
dec8cfc
Merge branch 'next' into onboarding-checklist
ndelangen Nov 20, 2025
c71d37f
Fix incorrect state initialization from persistence, which was overri…
ghengeveld Nov 20, 2025
26b351c
Rename property 'values' to 'items'
ghengeveld Nov 20, 2025
89faea2
Consistent keyFn usage
ghengeveld Nov 20, 2025
c5f7c39
Add JSDoc
ghengeveld Nov 20, 2025
bff2d46
Remove incorrect return type
ghengeveld Nov 20, 2025
a08e8d0
Add JSDoc
ghengeveld Nov 20, 2025
0f548b3
Use dequal in place of own implementation
ghengeveld Nov 20, 2025
6925f08
Add missing mock data
ghengeveld Nov 20, 2025
1cfaf81
improve type-safety
ndelangen Nov 20, 2025
2d2f717
fix stories? I hope. just maybe. it would be cool
ndelangen Nov 20, 2025
cfccdc6
Enhance type safety in checklist utility by refining item state handl…
ndelangen Nov 20, 2025
08bdbd0
Merge branch 'next' into onboarding-checklist
ndelangen Nov 20, 2025
a37edcb
Enforce version number for docs-assets links
ghengeveld Nov 20, 2025
8a9fa97
Persisted object should be partial
ghengeveld Nov 20, 2025
5d02fb8
Fix checklist store types
ghengeveld Nov 20, 2025
d79a162
Run check once preview is ready, because index is invalidated only on…
ghengeveld Nov 20, 2025
d42319a
Only store mutedAt in user-local storage
ghengeveld Nov 20, 2025
bf693a3
Ensure settings are properly written, and rename identifiers to camel…
ghengeveld Nov 20, 2025
5f29a50
Add missing api mocks
ghengeveld Nov 20, 2025
a65a429
Throttle at callsite
ghengeveld Nov 20, 2025
2ff8d29
Fix story data
ghengeveld Nov 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions code/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ const config = defineMain({
directory: '../addons/onboarding/src',
titlePrefix: 'addons/onboarding',
},
{
directory: '../addons/onboarding/example-stories',
},
{
directory: '../addons/pseudo-states/src',
titlePrefix: 'addons/pseudo-states',
Expand All @@ -100,6 +103,7 @@ const config = defineMain({
},
],
addons: [
'@storybook/addon-onboarding',
'@storybook/addon-themes',
'@storybook/addon-docs',
'@storybook/addon-designs',
Expand Down
53 changes: 53 additions & 0 deletions code/addons/onboarding/example-stories/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/react-vite';

import { fn } from 'storybook/test';

import { Button } from './Button';

const meta = {
title: 'Example/Button',
component: Button,
parameters: {
layout: 'centered',
parameters: {
chromatic: {
disableSnapshot: true,
},
},
},
tags: ['autodocs'],
argTypes: {
backgroundColor: { control: 'color' },
},
args: { onClick: fn() },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {
primary: true,
label: 'Button',
},
};

export const Secondary: Story = {
args: {
label: 'Button',
},
};

export const Large: Story = {
args: {
size: 'large',
label: 'Button',
},
};

export const Small: Story = {
args: {
size: 'small',
label: 'Button',
},
};
37 changes: 37 additions & 0 deletions code/addons/onboarding/example-stories/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import './button.css';

export interface ButtonProps {
/** Is this the principal call to action on the page? */
primary?: boolean;
/** What background color to use */
backgroundColor?: string;
/** How large should the button be? */
size?: 'small' | 'medium' | 'large';
/** Button contents */
label: string;
/** Optional click handler */
onClick?: () => void;
}

/** Primary UI component for user interaction */
export const Button = ({
primary = false,
size = 'medium',
backgroundColor,
label,
...props
}: ButtonProps) => {
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
return (
<button
type="button"
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
style={{ backgroundColor }}
{...props}
>
{label}
</button>
);
};
30 changes: 30 additions & 0 deletions code/addons/onboarding/example-stories/button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.storybook-button {
display: inline-block;
cursor: pointer;
border: 0;
border-radius: 3em;
font-weight: 700;
line-height: 1;
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.storybook-button--primary {
background-color: #555ab9;
color: white;
}
.storybook-button--secondary {
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
background-color: transparent;
color: #333;
}
.storybook-button--small {
padding: 10px 16px;
font-size: 12px;
}
.storybook-button--medium {
padding: 11px 20px;
font-size: 14px;
}
.storybook-button--large {
padding: 12px 24px;
font-size: 16px;
}
145 changes: 87 additions & 58 deletions code/addons/onboarding/src/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import React, { useCallback, useEffect, useState } from 'react';
import { SyntaxHighlighter } from 'storybook/internal/components';
import { SAVE_STORY_RESPONSE } from 'storybook/internal/core-events';

import type { Step } from 'react-joyride';
import { type API } from 'storybook/manager-api';
import { ThemeProvider, convert, styled, themes } from 'storybook/theming';

import { HighlightElement } from '../../../core/src/manager/components/TourGuide/HighlightElement';
import { TourGuide } from '../../../core/src/manager/components/TourGuide/TourGuide';
import { Confetti } from './components/Confetti/Confetti';
import { HighlightElement } from './components/HighlightElement/HighlightElement';
import type { STORYBOOK_ADDON_ONBOARDING_STEPS } from './constants';
import { ADDON_CONTROLS_ID, STORYBOOK_ADDON_ONBOARDING_CHANNEL } from './constants';
import { GuidedTour } from './features/GuidedTour/GuidedTour';
import { ADDON_CONTROLS_ID, ADDON_ONBOARDING_CHANNEL } from './constants';
import { IntentSurvey } from './features/IntentSurvey/IntentSurvey';
import { SplashScreen } from './features/SplashScreen/SplashScreen';

Expand Down Expand Up @@ -44,30 +43,14 @@ const CodeWrapper = styled.div(({ theme }) => ({
const theme = convert();

export type StepKey = (typeof STORYBOOK_ADDON_ONBOARDING_STEPS)[number];
export type StepDefinition = {
key: StepKey;
hideNextButton?: boolean;
onNextButtonClick?: () => void;
} & Partial<
Pick<
// Unfortunately we can't use ts-expect-error here for some reason
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Ignore circular reference
Step,
| 'content'
| 'disableBeacon'
| 'disableOverlay'
| 'floaterProps'
| 'offset'
| 'placement'
| 'spotlightClicks'
| 'styles'
| 'target'
| 'title'
>
>;

export default function Onboarding({ api }: { api: API }) {
export default function Onboarding({
api,
hasCompletedSurvey,
}: {
api: API;
hasCompletedSurvey: boolean;
}) {
const [enabled, setEnabled] = useState(true);
const [showConfetti, setShowConfetti] = useState(false);
const [step, setStep] = useState<StepKey>('1:Intro');
Expand Down Expand Up @@ -98,33 +81,36 @@ export default function Onboarding({ api }: { api: API }) {
[api]
);

const disableOnboarding = useCallback(() => {
// remove onboarding query parameter from current url
const url = new URL(window.location.href);
// @ts-expect-error (not strict)
const path = decodeURIComponent(url.searchParams.get('path'));
url.search = `?path=${path}&onboarding=false`;
history.replaceState({}, '', url.href);
api.setQueryParams({ onboarding: 'false' });
setEnabled(false);
}, [api, setEnabled]);
const disableOnboarding = useCallback(
(dismissedStep?: StepKey) => {
if (dismissedStep) {
api.emit(ADDON_ONBOARDING_CHANNEL, {
dismissedStep,
type: 'dismiss',
userAgent,
});
}
// remove onboarding query parameter from current url
const url = new URL(window.location.href);
url.searchParams.set('onboarding', 'false');
history.replaceState({}, '', url.href);
api.setQueryParams({ onboarding: 'false' });
setEnabled(false);
},
[api, setEnabled, userAgent]
);

const completeOnboarding = useCallback(
const completeSurvey = useCallback(
(answers: Record<string, unknown>) => {
api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, {
step: '7:FinishedOnboarding' satisfies StepKey,
type: 'telemetry',
userAgent,
});
api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, {
api.emit(ADDON_ONBOARDING_CHANNEL, {
answers,
type: 'survey',
userAgent,
});
setStep('7:FinishedOnboarding');
selectStory('configure-your-project--docs');
disableOnboarding();
},
[api, selectStory, disableOnboarding, userAgent]
[api, selectStory, userAgent]
);

useEffect(() => {
Expand All @@ -148,6 +134,10 @@ export default function Onboarding({ api }: { api: API }) {

useEffect(() => {
setStep((current) => {
if (hasCompletedSurvey && current === '6:IntentSurvey') {
return '7:FinishedOnboarding';
}

if (
['1:Intro', '5:StoryCreated', '6:IntentSurvey', '7:FinishedOnboarding'].includes(current)
) {
Expand All @@ -162,12 +152,13 @@ export default function Onboarding({ api }: { api: API }) {
return '3:SaveFromControls';
}

if (primaryControl) {
if (primaryControl || current === '2:Controls') {
return '2:Controls';
}

return '1:Intro';
});
}, [createNewStoryForm, primaryControl, saveFromControls]);
}, [hasCompletedSurvey, createNewStoryForm, primaryControl, saveFromControls]);

useEffect(() => {
return api.on(SAVE_STORY_RESPONSE, ({ payload, success }) => {
Expand All @@ -183,7 +174,7 @@ export default function Onboarding({ api }: { api: API }) {
}, [api]);

useEffect(
() => api.emit(STORYBOOK_ADDON_ONBOARDING_CHANNEL, { step, type: 'telemetry', userAgent }),
() => api.emit(ADDON_ONBOARDING_CHANNEL, { step, type: 'telemetry', userAgent }),
[api, step, userAgent]
);

Expand All @@ -196,7 +187,7 @@ export default function Onboarding({ api }: { api: API }) {
const snippet = source?.slice(startIndex).trim();
const startingLineNumber = source?.slice(0, startIndex).split('\n').length;

const steps: StepDefinition[] = [
const controlsTour = [
{
key: '2:Controls',
target: '#control-primary',
Expand All @@ -213,7 +204,7 @@ export default function Onboarding({ api }: { api: API }) {
disableBeacon: true,
disableOverlay: true,
spotlightClicks: true,
onNextButtonClick: () => {
onNext: () => {
const input = document.querySelector('#control-primary') as HTMLInputElement;
input.click();
},
Expand All @@ -234,7 +225,7 @@ export default function Onboarding({ api }: { api: API }) {
disableBeacon: true,
disableOverlay: true,
spotlightClicks: true,
onNextButtonClick: () => {
onNext: () => {
const button = document.querySelector(
'button[aria-label="Create new story with these settings"]'
) as HTMLButtonElement;
Expand Down Expand Up @@ -280,21 +271,59 @@ export default function Onboarding({ api }: { api: API }) {
},
},
},
] as const;
];

const checklistTour = [
{
key: '7:FinishedOnboarding',
target: '#storybook-checklist-module',
title: 'Continue at your own pace using the guide',
content: (
<>
Nice! You've got the essentials. You can continue at your own pace using the guide to
discover more of Storybook's capabilities.
<HighlightElement targetSelector="#storybook-checklist-module" pulsating />
</>
),
offset: 0,
placement: 'right-start',
disableBeacon: true,
disableOverlay: true,
styles: {
tooltip: {
width: 350,
},
},
},
];
Comment on lines +276 to +298
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the target element exists when this tour step is shown.

The checklist tour targets #storybook-checklist-module. Ensure this element is rendered in the UI before the FinishedOnboarding step becomes active, otherwise the tour positioning will fail.

Run the following script to verify the checklist module is referenced in related components:


🏁 Script executed:

#!/bin/bash
# Description: Verify that the storybook-checklist-module element is defined in the codebase.

# Search for the checklist module ID definition or usage
rg -n "storybook-checklist-module" --type=tsx --type=ts --type=jsx --type=js -C3

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for storybook-checklist-module reference without type restrictions
rg -n "storybook-checklist-module" -C3

Length of output: 1068


🏁 Script executed:

#!/bin/bash
# Search for checklist module related definitions
rg -n "checklist" -i --type=ts --type=js -C2 | head -50

Length of output: 3468


🏁 Script executed:

#!/bin/bash
# Look for element IDs being set or assigned
rg -n 'id=.*checklist|id: .*checklist' -i -C2

Length of output: 50538


🏁 Script executed:

#!/bin/bash
# Search ChecklistModule for the specific ID
rg -n "storybook-checklist-module" code/core/src/manager/components/sidebar/ -C5

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look at ChecklistModule.tsx for its root element ID
rg -n "id=" code/core/src/manager/components/sidebar/ChecklistModule.tsx -C2

Length of output: 493


🏁 Script executed:

#!/bin/bash
# Check if there's a wrapper or parent with id attribute in ChecklistModule
cat code/core/src/manager/components/sidebar/ChecklistModule.tsx | head -250

Length of output: 7168


🏁 Script executed:

#!/bin/bash
# Look for where ChecklistModule is rendered and if ID is set there
rg -n "ChecklistModule" code/addons/onboarding/src/ -A3 -B3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check if the tour step with FinishedOnboarding key is actually used/activated
rg -n "FinishedOnboarding\|7:FinishedOnboarding" code/addons/onboarding/src/ -C3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for where the root checklist element/module might get the ID
rg -n "storybook-checklist" code/core/src/manager/components/sidebar/ChecklistModule.tsx -C5

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search entire codebase for the ID pattern used in a return/render statement
rg -n "id=['\"]storybook-checklist-module" -A2 -B2

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look at the full Onboarding.tsx file to see how tour steps are used
cat code/addons/onboarding/src/Onboarding.tsx | grep -n -A10 -B10 "checklistTour"

Length of output: 1607


🏁 Script executed:

#!/bin/bash
# Check if there's any element rendering at this location
rg -n "ChecklistModule\|checklist.*Module" code/core/src/manager/ -l | head -10

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Find where ChecklistModule component is imported and rendered
rg -n "ChecklistModule" code/core/src/manager/ -A3 -B3 -l

Length of output: 182


🏁 Script executed:

#!/bin/bash
# Look for sidebar components that render the checklist
fd "sidebar" code/core/src/manager/components/ --type f -name "*.tsx" -exec grep -l "Checklist" {} \;

Length of output: 230


🏁 Script executed:

#!/bin/bash
# Search for any element with id containing checklist
rg -n 'id\s*=\s*["\'].*checklist' code/core/src/manager/components/sidebar/ -C2

Length of output: 68


🏁 Script executed:

#!/bin/bash
# Examine Sidebar.tsx where ChecklistModule is imported
cat code/core/src/manager/components/sidebar/Sidebar.tsx | grep -n "ChecklistModule" -A5 -B5

Length of output: 990


🏁 Script executed:

#!/bin/bash
# Look for the root container/div of ChecklistModule in Sidebar
rg -n "ChecklistModule" code/core/src/manager/components/sidebar/Sidebar.tsx -C10

Length of output: 1790


🏁 Script executed:

#!/bin/bash
# Search for ID assignments in Sidebar
cat code/core/src/manager/components/sidebar/Sidebar.tsx | grep -n "id="

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check the full context around ChecklistModule rendering in Sidebar
cat code/core/src/manager/components/sidebar/Sidebar.tsx | sed -n '150,185p'

Length of output: 1197


🏁 Script executed:

#!/bin/bash
# Final comprehensive search: look for any div/element with this exact ID anywhere
rg "storybook-checklist-module" code/ --type-list

Length of output: 389


🏁 Script executed:

#!/bin/bash
# Check if ID might be set via props or data attributes
rg -n "data-testid.*checklist\|id.*=.*checklist" code/core/src/manager/components/sidebar/ChecklistModule.tsx

Length of output: 0


Add id="storybook-checklist-module" to the ChecklistModule's root element.

The tour targets #storybook-checklist-module (lines 279, 285), but this ID is not defined anywhere in the codebase. The ChecklistModule component is rendered without an ID attribute. This will cause the tour step to fail positioning and the HighlightElement to not find its target.

Add the ID to ChecklistModule's root container (the CollapsibleWithMargin wrapper) so the tour can properly locate and highlight the element when the FinishedOnboarding step is shown.

🤖 Prompt for AI Agents
In code/addons/onboarding/src/Onboarding.tsx around lines 276 to 298, the tour
targets "#storybook-checklist-module" but the ChecklistModule root element has
no id; add id="storybook-checklist-module" to the ChecklistModule's root
container (the CollapsibleWithMargin wrapper) so the tour and HighlightElement
can find and highlight it—if CollapsibleWithMargin doesn't accept id directly,
forward the id to its underlying DOM element or add the id on the actual DOM
node rendered by ChecklistModule.


return (
<ThemeProvider theme={theme}>
{showConfetti && <Confetti />}
{step === '1:Intro' ? (
<SplashScreen onDismiss={() => setStep('2:Controls')} />
) : step === '6:IntentSurvey' ? (
<IntentSurvey onComplete={completeOnboarding} onDismiss={disableOnboarding} />
<IntentSurvey
onComplete={completeSurvey}
onDismiss={() => disableOnboarding('6:IntentSurvey')}
/>
) : step === '7:FinishedOnboarding' ? (
<TourGuide
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Circular reference in Step type
step={step}
steps={checklistTour}
onComplete={() => disableOnboarding()}
onDismiss={() => disableOnboarding(step)}
/>
) : (
<GuidedTour
<TourGuide
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Circular reference in Step type
step={step}
steps={steps}
onClose={disableOnboarding}
onComplete={() => setStep('6:IntentSurvey')}
steps={controlsTour}
onComplete={() => setStep(hasCompletedSurvey ? '7:FinishedOnboarding' : '6:IntentSurvey')}
onDismiss={() => disableOnboarding(step)}
/>
)}
</ThemeProvider>
Expand Down
Loading
Loading