본문으로 건너뛰기
cccskills
무료GitHub에 공개

add-tour

Add or update guided feature tours in the web app. Covers registering interface targets, writing steps, guiding users toward hidden controls, and checking the tour with saved progress and different sidebar states.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Add or change an in-app feature tour (a view's guided flyover) in the web app. Use when adding a tour to a view, adding or editing tour steps, pointing a step at a new control, or when a step's target needs something opened first.

설치 방법 보기

이럴 때 유용합니다

  • Add a guided tour to a view
  • Revise tour steps and their target controls
  • Guide users toward controls in a collapsed sidebar
  • Check tour behavior and update its documentation

포함된 파일(1)

  • SKILL.md7.1 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Add or change an in-app tour

Frontend only. Two layers:

LayerWhereWhat
Primitiveapps/web/src/components/ui/components/Tour/Tour.* parts, defineTourTargets, tourTarget. Generic; no app knowledge.
Appapps/web/src/features/tours/ViewTour (desktop gate, per-user dismissal, connector/video CTAs), defineViewTour.
Per viewapps/web/src/features/<view>/tour.tsThe view's targets and its tour definition.

Read an existing tour.ts first. channels-view/tour.ts and agents-view/tour.ts show entries; calendar-view/tour.ts shows the sidebar toggle entry.

1. Declare targets

In the view's tour.ts:

export const REPORTS_TOUR = defineTourTargets('reports', ['filters', 'chart']);
  • Ids are namespace.name. Use the view's name as the namespace.
  • Targets are view-scoped: they resolve only inside the tour's split. Pass { scope: 'app' } only for shared chrome outside any split (see command/sidebar/tour.ts).
  • Reuse shared targets before adding new ones:
    • VIEW_SHELL_TOUR (@app/components/view-shell/tour): aside, main, topBar, sidebarToggle. Every ViewShell registers these.
    • SOUP_TOUR (features/next-soup/tour.ts): list.
    • CHANNEL_TOUR (features/channel/tour.ts): messages, composer, call.
    • APP_TOUR (features/command/sidebar/tour.ts): createMenu.

Never target with selectors, data-* attributes, or aria-label lookups. If the control you want isn't registered, register it (step 2).

2. Attach targets

<div ref={tourTarget(REPORTS_TOUR.filters)}>…</div>
  • The element must have a box. display: contents wrappers never resolve; attach to a real element.
  • Never write a conditional ref like ref={cond ? tourTarget(X) : undefined}. The Solid compiler silently drops it, and the target never registers. Create the ref in the component body and decide inside a callback: const target = tourTarget(X); then ref={(el) => { if (cond) target(el); }}.
  • If the element already has a ref, call both: ref={(el) => { existing(el); target(el); }} with const target = tourTarget(...) created in the component body, or use mergeRefs from @solid-primitives/refs.
  • For a component that doesn't forward ref, add a ref prop that it passes to its root (see SidebarCreateButton).
  • A lower-level feature may import targets from the view that owns the tour (for example, features/calendar imports CALENDAR_TOUR).

3. Define the tour

export const reportsTour = defineViewTour({
  id: 'reports',            // dismissal key: never reuse or rename casually
  title: 'Reports',
  connector: { kind: 'mcp', label: 'Linear', tools: ['Linear'] }, // optional
  video: { youtubeId: '…', title: '…', duration: '1:23' },          // optional
  steps: [
    { target: REPORTS_TOUR.filters, title: '…', description: '…' },
    { target: [REPORTS_TOUR.chart, VIEW_SHELL_TOUR.main], title: '…', description: '…' },
  ],
});
  • target may be a list; the first shown one wins. Use this for features that aren't always rendered (behind a flag, a connection, or data such as "more than one calendar"): list the real control first and the nearest always-present surface after it, and set missingHint. The hint shows whenever the step falls back.
  • Before relying on a target, check every branch that renders it: touch vs desktop headers, preview vs workspace, empty states. Register the same target in each branch that shows the control.
  • A step without target floats in the split.
  • missingHint explains how to reach or enable the feature when the step floats or falls back.
  • placement (a floating-ui Placement) overrides the default right-start.

4. Never navigate for the user: use an entry

If a step's target is behind something (a collapsed sidebar, another page, an unopened item), don't open it from the tour. Give the step an entry:

{
  target: REPORTS_TOUR.chart,
  entry: VIEW_SHELL_TOUR.sidebarToggle,
  entryLabel: 'Open the sidebar to continue the tour',
  title: '…',
  description: '…',
}

While the target is missing and the entry is shown, the card hides, a beacon marks the entry, and a small card beside it shows entryLabel with Skip. The beacon stays until the target appears, however the user gets there. Register the entry control as a target like any other.

  • Keep entryLabel short and imperative: "Open a channel or DM to continue".
  • Chain entries when the entry itself can be hidden. The first shown one wins, so list the real control first and the sidebar toggle last: entry: [CHANNELS_TOUR.conversation, VIEW_SHELL_TOUR.sidebarToggle]. With the sidebar collapsed the beacon marks the toggle; once it opens, the beacon moves to the row.
  • ViewTour appends VIEW_SHELL_TOUR.sidebarToggle to every step that has a target, so a step whose target is in a collapsed sidebar always marks the toggle. You still need it explicitly only as the last link of a chain you write yourself.
  • A view that collapses its sidebar itself instead of through ViewShell (like Customers' NavigationToggle) must register its own expand control as VIEW_SHELL_TOUR.sidebarToggle, or those steps will float.
  • Point entries at a specific control, not a large container. When many elements share a target (every conversation row), the top-most one on screen is used.

5. Mount it

Mount once, inside the view's split (usually in ViewShell.Main or next to the list):

<ViewTour tour={reportsTour} />
<ViewTour tour={tasksTour} actions={<ImportLinearAction />} />  // extra CTAs
  • For SoupView-based routes, pass it through the slot: <SoupView … tour={<ViewTour tour={callsTour} />} />.
  • Don't put it inside a <Show> branch that remounts on navigation, or the tour restarts at step 1.
  • Don't gate it on desktop or on a flag yourself; ViewTour already checks both. All tours sit behind the enableInAppTours flag (enable-in-app-tours in PostHog). To see tours on the local dev server, start it with VITE_ENABLE_IN_APP_TOURS=true.
  • Don't pass step callbacks that change pages or open panels.

6. Test and document

  • Unit behavior of the primitive lives in Tour/Tour.test.tsx and app behavior in features/tours/ViewTour.test.tsx; add cases there when you change them.
  • The primitive's gallery page is Tour/Tour.docs.tsx.
  • Progress is saved per user in local storage under macro:tour:<id> (completed, dismissed, or the active step). Changing a tour's steps doesn't reset it for users who finished it; bump the id only if everyone must see the new version.
  • Check it in a browser with VITE_ENABLE_IN_APP_TOURS=true: on localhost the tour reopens on every mount. Walk every step, including one that waits on an entry, once with the sidebar open and once collapsed.
  • Update docs/agent-guide/view-tours.md when a view gains a tour or its steps change.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Expose new backend API endpoints through the TypeScript SDK, or record intentional exclusions. Follow existing entity and client conventions, check generated request types, and verify that each endpoint is either used by the SDK or explicitly skipped.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Adding SDK support for a new Rust service endpoint
  • Investigating endpoints reported as uncovered
  • Recording agreed SDK exclusions
macro-inc/macro4.8천2026년 10월 21일 업데이트

audit

무료

Identify the checks required for changed files, run tests, and review applicable project rules. Get a table of passed, failed, and skipped checks with evidence, helping you verify changes before handoff or pushing code.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Checking changes before reporting work complete
  • Reviewing required checks before pushing code
  • Finding missing tests or documentation updates
macro-inc/macro4.8천2026년 10월 21일 업데이트

Review and structure Rust backend changes using hexagonal architecture, which separates business rules from external interfaces. Check dependency direction, place authorization policy in domain services, and keep database operations and external clients behind defined interfaces.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Reviewing layer boundaries before Rust backend changes
  • Moving permission decisions into domain services
  • Separating database and external client implementations
macro-inc/macro4.8천2026년 10월 21일 업데이트

Guide the integration of collaboratively edited Markdown fields into an application feature. It explains service selection, permissions inherited from parent records, content storage in Loro sessions, and how to initialize and retire each editing surface.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Adding a collaboratively edited description field
  • Implementing shared input through a public API
  • Connecting editing permissions to a parent record
macro-inc/macro4.8천2026년 10월 21일 업데이트

Add a new AI tool to an existing Rust application, from implementation and service connections to infrastructure configuration, generated TypeScript types, and a frontend component that displays the tool's results.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Adding an AI tool to an existing Rust application
  • Connecting a tool to services and environment variables
  • Generating frontend types from tool schemas
macro-inc/macro4.8천2026년 10월 21일 업데이트

Design features such as CRM around reusable database storage and a shared editor. It guides ownership, permissions, API contracts, and update behavior so different applications can use the same database components while enforcing their own access rules.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Adding shared database storage to CRM
  • Reusing one database editor across applications
  • Separating storage from ownership and lifecycle metadata
macro-inc/macro4.8천2026년 10월 21일 업데이트

macro-inc의 스킬 모두 보기

이 스킬의 문제 신고