一键导入
storybook-story
Create a Storybook story for a component. Use when the user asks to add a story, write a story, or create a Storybook story for a component.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create a Storybook story for a component. Use when the user asks to add a story, write a story, or create a Storybook story for a component.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Run affected tests, typecheck, and lint (with autofix) to catch CI failures locally before pushing. Use when CI is failing or before pushing to avoid CI failures. Offers to fix typecheck/test failures and to amend+push when clean.
Create a GitHub PR for the current branch with auto-generated description. Use when the user asks to create a pull request, open a PR, or put up changes for review.
Create a Linear ticket for the current branch on the One Big Team, auto-assigning the appropriate Linear project and team/product labels based on which part of the codebase changed. Use when the user asks to create a Linear ticket, file a Linear issue, or track work in Linear for changes on the current branch.
Render, read, and add component examples in the examples renderer. Files take two forms — colocated `*.examples.tsx` (e.g. `Checkbox.examples.tsx` next to `Checkbox.tsx`) or grouped `examples/*.tsx` (e.g. `Checkbox/examples/Default.tsx`). Covers exact iframe URLs per example, story-id derivation, multi-worktree-aware server discovery, file conventions, and the onboarding gate. Onboarded products (the authoritative validation list — only invoke this skill when the work touches one of these): `apps/staff/`. Verify at runtime with `nx show projects --with-target examples`. Use to render, screenshot, inspect, or extend an example in an onboarded product. For anything outside the onboarded list, this skill does not apply.
Go through a PR's review comments one by one, propose solutions, and commit fixes. Use when the user wants to address PR feedback, review comments, or resolve PR review requests.
GitHub CLI (gh) comprehensive reference for repositories, issues, pull requests, Actions, projects, releases, gists, codespaces, organizations, extensions, and all GitHub operations from the command line.
基于 SOC 职业分类
| name | storybook-story |
| description | Create a Storybook story for a component. Use when the user asks to add a story, write a story, or create a Storybook story for a component. |
This skill covers how to write Storybook stories (CSF3 format) for components in this monorepo.
There is currently one active Storybook app:
apps/@jii/storybook/.storybook/main.tsRead that file to confirm the current stories glob scope before writing a story. Additional Storybook instances (e.g. for Staff) may be added to the repo in the future; when they are, read each config file to determine which directories each one covers, and use that to drive the title conventions in Step 3.
Read the target component file to understand:
MemoryRouter decorator)Component<T>) — use a concrete type in the storychildren)value + onChange)Also check sibling files: related types, constants, sub-components used in composition.
Use when the component is stateless and can be rendered directly.
const meta = {
title: "Common UI/MyComponent",
component: MyComponent,
args: { children: "Label text" },
} satisfies Meta<typeof MyComponent>;
For components with interesting variants, add multiple named stories.
Use when the component needs children or siblings composed around it, but no state.
const meta: Meta<CombinedArgs> = {
title: "Common UI/MyComponent",
render: ({ foo, bar, onAction }) => (
<MyComponent foo={foo} bar={bar}>
<MyChildComponent onClick={onAction}>Item</MyChildComponent>
</MyComponent>
),
...
};
examples/example.tsx file (stateful)Use when the component requires controlled state (useState) — e.g. a controlled input, checkbox, selector, or slider.
examples/example.tsx alongside the story file*ExampleArgs type and a default named React component (not an arrow function — hooks require named components)?raw for the code panel source// examples/example.tsx
export type MyExampleArgs = {
onChange: (v: string) => void;
disabled: boolean;
};
export default function MyExample({ onChange, disabled }: MyExampleArgs) {
const [value, setValue] = useState("");
return (
<MyComponent
value={value}
disabled={disabled}
onChange={(next) => {
setValue(next);
onChange(next);
}}
/>
);
}
// MyComponent.stories.tsx
import MyExample, { type MyExampleArgs } from "./examples/example";
import exampleSource from "./examples/example?raw";
const meta: Meta<MyExampleArgs> = {
title: "Common UI/MyComponent",
render: (args) => <MyExample {...args} />,
parameters: {
docs: { codePanel: true, source: { code: exampleSource } },
},
...
};
Story titles encode both which Storybook the story belongs to and what library it comes from.
Shared libraries are anything outside of libs/@jii/ — they are not scoped to JII and may eventually appear in other Storybooks. JII-specific libraries live under libs/@jii/.
When additional Storybook instances are added to the repo, check each config file's
storiesglobs to determine which directories each one covers, and use that to driveShared/vs. app-specific titles.
libs/ outside libs/@jii/)Prefix with Shared/ followed by the library name:
| Source | Title prefix |
|---|---|
libs/design-system/src/components/ | "Shared/Design System/Components/MyComponent" |
libs/design-system/src/styles/ | "Shared/Design System/Styles/MyThing" |
libs/@jii/)Prefix with the library's short name — no Shared/ prefix:
| Source | Title prefix |
|---|---|
libs/@jii/common-ui/ | "Common UI/MyComponent" |
libs/@jii/states/US_TN/ | "US_TN/MyComponent" |
libs/@jii/sentence-dates/ | "Sentence Dates/MyComponent" |
Add a subfolder segment when a component lives in a named subdirectory that differs from the component name and contains multiple documented components, e.g.:
"Common UI/Header/HeaderBarContainer""Common UI/Buttons/ButtonLink""Shared/Design System/Components/Dropdown"fn() from storybook/test (not @storybook/test) for callback args (onClick, onChange, etc.)table: { disable: true }options + control for enums:
kind: { options: ["primary", "secondary"], control: "radio" }
"text", "boolean", "color", "select", "radio", { type: "range", min, max, step }, { type: "number" }children when managed in render) with table: { disable: true }If the component (or anything it renders) imports from react-router-dom, wrap with a MemoryRouter decorator:
decorators: [
(Story) => (
<MemoryRouter>
<Story />
</MemoryRouter>
),
],
If the component opens a dropdown or popover that would be clipped, add:
parameters: {
docs: { story: { height: "300px" } },
},
Use generic placeholder text in story args and render functions — not domain-specific or app-specific copy. Unless the user specifies otherwise:
"Label", "Option A", "First item", "Section heading""The quick brown fox jumps over the lazy dog." or similar"/" or "#""Days without a violation" or "Back to home" — the user will provide that if neededAdd separate named exports when the component has distinct visual states:
export const Primary: Story = { args: { kind: "primary" } };
export const Secondary: Story = { args: { kind: "secondary" } };
export const Disabled: Story = { args: { disabled: true } };
Always run both after creating or modifying story files:
npx eslint path/to/Component.stories.tsx [path/to/examples/example.tsx] --fix
npx prettier --write path/to/Component.stories.tsx [path/to/examples/example.tsx]
simple-import-sort will reorder imports; Prettier formats the files.
fn() import: use storybook/test, not @storybook/testexport default function Foo(), not const Foo = () => — React hooks require named componentssatisfies vs explicit annotation: use satisfies Meta<typeof Component> when the component type aligns; use const meta: Meta<CustomArgs> = {} when using a custom args type (e.g. for generic components or composed args)string) in the example wrapper