소스 정보
- 저장소
- ivanboring/canvas-storybook-ai
- 최근 소스 활동
- 2026년 8월 20일 08:21
- 감지된 SKILL.md 언어
- 영어
- 스타
- 0
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/ivanboring/canvas-storybook-ai --skill stories명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
How to build a site's pages and UI to the chosen build approach — faithfully rebuilding an existing source site (like-for-like, pixel-perfect or close-match) or building to a design system. Use when recreating a page or site from an existing source, migrating a design, or building UI to a design system / component library.
Requirements and patterns for creating or modifying React components with Tailwind CSS and CVA
Step-by-step guide for creating new components from scratch including folder structure and naming conventions
SKILL.md 표시 중
| name | stories |
| description | Creating and modifying Storybook stories for components and pages |
Stories fall into a few categories:
src/components/<component_name>/<component_name>.stories.tsx (snake_case, the same base
name as the component)These are intended to provide examples of how to use a component.
Auto documentation should be used, and all parameter types must be explicitly
defined with appropriate controls. Always cross-reference the story parameters
with the <component_name>.component.yml props and slots.
Non-interactive tests (e.g. expects) can be added to component stories, but interactive tests that simulate user input MUST NOT be included in stories.
Every component story's meta MUST include a
parameters.docs.description.component string. It renders at the top of the
autodocs page and is the first thing an author reads about the component.
card_container wraps heading
and grid_container).getSiteData(), etc.),
note the data source.table.category groupings (see
"Group argTypes by Canvas vs Internal" below).const meta = {
title: 'Components/Stats',
component: Stats,
parameters: {
docs: {
description: {
component:
'Block of metrics with an optional heading. Items are supplied via the `items` slot using `stat_item` children.',
},
},
},
argTypes: {
/* ... */
},
} satisfies Meta<typeof Stats>;
Every prop the React component accepts MUST appear in argTypes with a
table.category — otherwise it renders uncategorised in the auto-docs args
table. Group each into one of three buckets:
Canvas Props (tables.CANVAS) — props declared under props: in
<component_name>.component.yml, editable by content authors in Canvas.Canvas Slots (tables.SLOT) — slot props declared under slots: in
<component_name>.component.yml; authors drop child components into these.Internal (JSX only) (tables.INTERNAL) — props the component accepts
but that are NOT in <component_name>.component.yml: className, children,
JSX-composition helpers (e.g. a rightColumn node), and test/mock props.Import the shared tables presets from @/stories/argtypes and attach the
right one to each argType — never re-declare the presets inline. Declare the
argTypes grouped in that order (Canvas Props, then Canvas Slots, then Internal),
which is also how the categories sort in the args table.
import { tables } from '@/stories/argtypes';
const meta = {
title: 'Components/Foo',
component: Foo,
argTypes: {
// Canvas Props — mirror component.yml `props:`
variant: {
control: 'select',
options: ['Solid', 'Outline'],
description: 'Visual style variant.',
table: tables.CANVAS,
},
text: { control: 'text', description: 'Label text.', table: tables.CANVAS },
// Canvas Slots — mirror component.yml `slots:`
content: {
control: false,
description: 'Slot for the components rendered inside Foo.',
table: tables.SLOT,
},
// Internal — accepted by the component, not surfaced to Canvas editors
className: {
control: 'text',
description: 'Extra CSS classes appended to the outer element.',
table: tables.INTERNAL,
},
children: {
control: false,
description: 'React nodes rendered inside the component.',
: tables.,
},
},
} < >;
Guidance on control:
<component_name>.component.yml enum):
control: 'select' with an options: […] mirroring the enum values exactly.control: 'text'.control: 'boolean'.control: { type: 'number', min, max } or
control: { type: 'range', min, max, step }.children): control: false.control: 'object'.Autodocs generates a "Hide … items" toggle per category. Storybook does not currently expose a "collapsed by default" API for categories; consider that a known limitation.
Both props and slots arguments MUST be either scalar values, a media object
type, or a React fragment of public components. You MUST NOT use direct markup
or custom styling — all visual presentation must be encapsulated within the
components themselves. Stories MUST only use props and slots defined in the
component's <component_name>.component.yml, unless the prop exists to
facilitate testing or mocking (e.g. injecting test data).
src/components/<component_name>/<component_name>.tests.tsx (snake_case), although if a
component has a large number of tests, they can be grouped using
<component_name>-<group>.tests.tsx. The .tests.tsx suffix (not
.stories.tsx) keeps these test-only stories out of the component-story glob;
they are indexed via testsIndexer in .storybook/main.ts.These are intended to provide automated tests for components and other UI elements.
Auto documentation MUST be disabled.
If a component makes use of the canvas parsing to directly inspect or manipulate components in props, a test should be added to ensure that the component correctly parses the canvas island.
Any component whose layout or controls change by breakpoint MUST be tested at both a desktop and a mobile viewport — never only one. Either re-run the assertions at each width inside a single play function, or provide separate desktop and mobile test stories.
Set the viewport from within the play function:
const setViewport = async (width: number, height: number) => {
const { page } = await import('vitest/browser');
await page.viewport(width, height);
await new Promise((r) => setTimeout(r, 100)); // let the layout settle
};
Assert the breakpoint-specific differences explicitly, including that the control for the other breakpoint is hidden — e.g. a desktop sidebar nav is visible and the mobile dropdown is not, and vice versa. Hidden-when-it-should-show (and the reverse) is a common regression that only surfaces when both widths are tested.
A component that renders differently before hydration (server / no-JavaScript) than once interactive — i.e. progressive enhancement — MUST have its pre-hydration render tested, not just its hydrated one, because that is what search engines and no-JS visitors receive. Storybook always runs JavaScript, so reproduce the no-JS render by preventing the component from upgrading to its interactive state.
When the upgrade is gated on a one-shot requestAnimationFrame (a common
useHydrated-style flag), stub it in the story's beforeEach so the callback
never fires, and restore it in the returned teardown:
beforeEach: () => {
const original = window.requestAnimationFrame;
window.requestAnimationFrame = () => 0; // returns a handle, never calls back
return () => {
window.requestAnimationFrame = original;
};
},
The component then stays in its static/stacked render. Assert the no-JS
contract: it never gains its interactive marker (e.g. an is-interactive
class), all content is reachable (every panel present and visible, not just the
active one), and any navigation degrades to working native anchors (each link's
href targets a real element id). Test this at both desktop and mobile
viewports. A matching no-play story is also useful for visually inspecting the
pre-hydration render.
src/pages<page-name>.stories.tsx using kebab-case.These provide an example of how a page could be built using components.
Autodocs must be disabled and the fullscreen layout must be used. There must only be one story per page.
The PageLayout component from the layouts story should be used to ensure consistent wrapping of the page.
Both props and slots arguments MUST be either scalar values, a media object
type, or a React fragment of public components. You MUST NOT use direct markup
or custom styling — all visual presentation must be encapsulated within the
components themselves. Stories MUST only use props and slots defined in the
component's <component_name>.component.yml, unless the prop exists to
facilitate testing or mocking. Pages should be directly composed of components
so that the "show code" view reflects real component usage.
Placeholder.io can be used to generate placeholder images for components:
{
src: "https://placehold.co/800x600",
alt: "Example image placeholder",
width: 800,
height: 600,
}
Assets should be stored in the src/stories/assets directory, in suitable
subdirectories depending on the scope of the asset. An index.ts file must be
created to export the assets with the correct image type. Real assets must never
be directly imported in stories without their image type. The image type must
include the correct dimensions and provide alt text.