add-onboarding-tour
GitHub为前端功能添加首次运行引导、产品演示或空状态示例数据。提供集中式组件和钩子,支持步骤定义、锚点高亮及模拟数据切换,用于新用户引导和界面解释。
Trigger Scenarios
Install
npx skills add lightdash/lightdash --skill add-onboarding-tour -g -y
SKILL.md
Frontmatter
{
"name": "add-onboarding-tour",
"metadata": {
"internal": true
},
"description": "Add a first-run guided tour, product walkthrough, coachmarks, or empty-state mock\/example data to a Lightdash frontend feature. Use when the user wants to onboard users to a page, add a \"Take the tour\" flow, explain an unfamiliar UI, or show sample data on an empty page.",
"allowed-tools": "Read, Edit, Write, Glob, Grep"
}
Add an Onboarding Tour
A zero-dependency, centralised kit for first-run onboarding in packages/frontend. Three reusable pieces do the heavy lifting; each feature only supplies its own steps, copy, anchors, and (optionally) example data.
Building blocks
| Piece | Path | Job |
|---|---|---|
useGuidedTour |
src/hooks/useGuidedTour.ts |
localStorage seen-flag, first-visit auto-open, replay. Returns { isOpen, startTour, closeTour }. |
GuidedTour |
src/components/common/GuidedTour |
Spotlight rendering. Dims the page, highlights a data-tour target, anchors a Next/Back/Skip card. target: null → centered card. |
useOnboardingMock |
src/hooks/useOnboardingMock.ts |
A react-query select that swaps real data for deterministic mock rows while a flag is on. |
Reference implementation: the Reviews page — src/ee/features/aiCopilot/components/Admin/settings/AiReviewsSettingsPage.tsx (wiring), AiAgentAdminReviewItemsTable.tsx (mock rows), and Admin/onboarding/ (the content). Read these first — copying them is the fastest path.
Where content lives
Kit = global, content = per-feature. The three building blocks above are shared. Everything specific to one feature — its steps, copy, sample rows, and any onboarding-only visuals — goes in a co-located onboarding/ folder next to the feature, with the same fixed layout every time:
<feature-dir>/onboarding/
index.ts public surface (re-exports)
steps.tsx TOUR_STEPS: GuidedTourStep[] (all the step copy)
exampleData.ts EXAMPLE_*, isExample*() (only if the feature shows mock rows)
<Visual>.tsx onboarding-only visuals, e.g. a diagram (+ .module.css)
The feature imports from ./onboarding. Do not put feature content in a global folder, and do not inline steps or mock data in the page/table — keep components about rendering. Only re-export from index.ts what's consumed outside the folder (ts-unused-exports is enforced).
Recipe
-
Wire the tour state in the feature page:
const { isOpen, startTour, closeTour } = useGuidedTour({ storageKey: 'ld.<feature>.tour.v1', }); -
Define steps in
onboarding/steps.tsxas a module constant (they're static — nouseMemoneeded). Eachtargetis a CSS selector resolved when the step is reached, ornullfor a centered explainer:export const TOUR_STEPS: GuidedTourStep[] = [ { target: '[data-tour="<feature>-intro"]', title: '…', body: '…' }, { target: '[data-tour="<feature>-row"]', title: '…', body: '…' }, { target: null, title: '…', body: <SomeDiagram /> }, // centered ];The page imports
{ TOUR_STEPS }from./onboardingand passes it to<GuidedTour>. -
Add
data-touranchors to the elements each step points at. For a table row, add it in the row props so the whole row is spotlit:mantineTableBodyRowProps: ({ row }) => row.index === 0 ? { 'data-tour': '<feature>-row' } : {}, -
Render the tour and a replay button:
<Button variant="subtle" leftSection={<MantineIcon icon={IconRoute} />} onClick={startTour}> Take the tour </Button> <GuidedTour steps={steps} opened={isOpen} onClose={closeTour} /> -
(Optional) Deterministic example data so a tour on an empty (or any) page always highlights the same rows. Put stable, clearly-labelled mock rows and the
isExamplehelper inonboarding/exampleData.ts, and inject them viaselectwhile the tour is open:const select = useOnboardingMock(EXAMPLE_ROWS, isOpen); const { data } = useThings(args, { select }); // hook must forward `select` to useQueryRender example rows muted and inert (disabled actions, no navigation); mark them with an "Example" badge. Gate interactivity off a sentinel id (e.g.
id.startsWith('example:')).
Conventions
- Zero dependencies. No joyride/driver/intro.js. The spotlight is a
box-shadow: 0 0 0 9999pxdim — already handled byGuidedTour. - storageKey:
ld.<feature>.tour.v<n>. Bump the version to re-show the tour after a redesign. - Copy: warm, natural, straight to the point. No em dashes, no arrows. Short titles.
- Styling: follow
frontend-style-guide— nostyleprop (pass runtime geometry via__vars), CSS modules, theme tokens /ldGray/ldDark. - Mock rows must never look or act real: muted, "Example" badge, disabled actions.
Gotchas
- Targets that render late (data still loading): handled —
GuidedTourpolls for each step's element and shows a centered card until it appears. Do not filter steps at open time; that drops steps whose targets haven't rendered yet. - Determinism: tie mock data to
isOpen(tour running), not to emptiness, if you want the tour to highlight the same rows every run. Closing the tour flips back to real data. selectpassthrough: the data hook must accept and forward aselectoption touseQuery(seeuseAiAgentAdminReviewItems). Add it if missing.
Version History
- 71d06ec Current 2026-08-20 16:06


