component-docs
About
The component-docs skill generates and maintains component documentation including usage examples, props tables, and Storybook stories. It's designed for documenting new components or improving existing docs in the `packages/ui/` directory. Developers should use this when creating API documentation, maintaining README files, or setting up component stories.
Documentation
Component Documentation Skill
This skill helps you create and maintain component documentation in packages/ui/.
When to Use This Skill
- Writing documentation for new components
- Creating usage examples and code snippets
- Documenting component props and variants
- Setting up Storybook stories
- Generating API documentation
- Maintaining component README files
Documentation Structure
packages/ui/
├── src/
│ ├── components/
│ │ ├── button.tsx # Component implementation
│ │ ├── button.stories.tsx # Storybook stories (optional)
│ │ └── __tests__/
│ │ └── button.test.tsx # Component tests
├── docs/
│ ├── components/
│ │ ├── button.md # Component documentation
│ │ └── card.md
│ └── guides/
│ ├── getting-started.md
│ └── customization.md
└── README.md # Package overview
Component Documentation Template
Basic Component Documentation
# Button
A customizable button component built with Radix UI primitives.
## Installation
This component is part of the `@sgcarstrends/ui` package.
\`\`\`bash
pnpm add @sgcarstrends/ui
\`\`\`
## Usage
\`\`\`tsx
import { Button } from "@sgcarstrends/ui";
export function Example() {
return <Button>Click me</Button>;
}
\`\`\`
## Variants
### Default
\`\`\`tsx
<Button variant="default">Default Button</Button>
\`\`\`
### Destructive
\`\`\`tsx
<Button variant="destructive">Delete</Button>
\`\`\`
### Outline
\`\`\`tsx
<Button variant="outline">Outline Button</Button>
\`\`\`
## Sizes
\`\`\`tsx
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon">
<Icon />
</Button>
\`\`\`
## Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| variant | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"default"` | The visual style of the button |
| size | `"default" \| "sm" \| "lg" \| "icon"` | `"default"` | The size of the button |
| asChild | `boolean` | `false` | Render as child element |
| disabled | `boolean` | `false` | Whether button is disabled |
## Examples
### With Icon
\`\`\`tsx
import { Button } from "@sgcarstrends/ui";
import { DownloadIcon } from "lucide-react";
export function DownloadButton() {
return (
<Button>
<DownloadIcon className="mr-2 h-4 w-4" />
Download
</Button>
);
}
\`\`\`
### Loading State
\`\`\`tsx
"use client";
import { useState } from "react";
import { Button } from "@sgcarstrends/ui";
export function LoadingButton() {
const [isLoading, setIsLoading] = useState(false);
return (
<Button disabled={isLoading} onClick={() => setIsLoading(true)}>
{isLoading ? "Loading..." : "Submit"}
</Button>
);
}
\`\`\`
### As Link
\`\`\`tsx
import { Button } from "@sgcarstrends/ui";
import Link from "next/link";
export function LinkButton() {
return (
<Button asChild>
<Link href="/about">Learn More</Link>
</Button>
);
}
\`\`\`
## Accessibility
- Uses semantic `<button>` element
- Supports keyboard navigation (Enter, Space)
- Proper focus states
- ARIA attributes supported via props
## Styling
The Button component uses Tailwind CSS and CSS variables for theming. Customize via:
\`\`\`tsx
<Button className="custom-classes">Custom Styled</Button>
\`\`\`
## Related Components
- [Link Button](#)
- [Icon Button](#)
- [Button Group](#)
JSDoc Comments
Add comprehensive JSDoc comments to components:
/**
* A customizable button component with multiple variants and sizes.
*
* @component
* @example
* ```tsx
* <Button variant="default" size="md">
* Click me
* </Button>
* ```
*/
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
/**
* Render the button as a child element (e.g., Link)
* @default false
*/
asChild?: boolean;
/**
* The visual style variant of the button
* @default "default"
*/
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
/**
* The size of the button
* @default "default"
*/
size?: "default" | "sm" | "lg" | "icon";
}
/**
* Button component
*
* @param {ButtonProps} props - Button props
* @returns {React.ReactElement} Button element
*
* @example
* Basic usage
* ```tsx
* <Button>Click me</Button>
* ```
*
* @example
* With variant
* ```tsx
* <Button variant="destructive">Delete</Button>
* ```
*
* @example
* As a link
* ```tsx
* <Button asChild>
* <Link href="/about">About</Link>
* </Button>
* ```
*/
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = "Button";
Storybook Stories
Installing Storybook (if not present)
cd packages/ui
# Initialize Storybook
npx storybook@latest init
Basic Story
// packages/ui/src/components/button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "./button";
const meta = {
title: "Components/Button",
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {
variant: {
control: "select",
options: ["default", "destructive", "outline", "secondary", "ghost", "link"],
},
size: {
control: "select",
options: ["default", "sm", "lg", "icon"],
},
},
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
children: "Button",
},
};
export const Destructive: Story = {
args: {
variant: "destructive",
children: "Delete",
},
};
export const Outline: Story = {
args: {
variant: "outline",
children: "Outline",
},
};
export const Small: Story = {
args: {
size: "sm",
children: "Small Button",
},
};
export const Large: Story = {
args: {
size: "lg",
children: "Large Button",
},
};
export const WithIcon: Story = {
args: {
children: (
<>
<span className="mr-2">📥</span>
Download
</>
),
},
};
export const Disabled: Story = {
args: {
children: "Disabled Button",
disabled: true,
},
};
Complex Story with Interactions
import type { Meta, StoryObj } from "@storybook/react";
import { within, userEvent, expect } from "@storybook/test";
import { Card, CardHeader, CardTitle, CardContent } from "./card";
const meta = {
title: "Components/Card",
component: Card,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
} satisfies Meta<typeof Card>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
render: () => (
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Card Title</CardTitle>
</CardHeader>
<CardContent>
<p>Card content goes here.</p>
</CardContent>
</Card>
),
};
export const WithInteraction: Story = {
render: () => (
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Interactive Card</CardTitle>
</CardHeader>
<CardContent>
<button data-testid="card-button">Click me</button>
</CardContent>
</Card>
),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByTestId("card-button");
await userEvent.click(button);
await expect(button).toBeInTheDocument();
},
};
TypeDoc for API Documentation
Setup TypeDoc
cd packages/ui
pnpm add -D typedoc
Add to package.json:
{
"scripts": {
"docs:generate": "typedoc --out docs/api src/index.ts"
}
}
TypeDoc Configuration
// packages/ui/typedoc.json
{
"entryPoints": ["src/index.ts"],
"out": "docs/api",
"exclude": ["**/*.test.ts", "**/*.stories.tsx"],
"excludePrivate": true,
"excludeProtected": true,
"plugin": ["typedoc-plugin-markdown"],
"readme": "README.md",
"theme": "default"
}
Generate documentation:
pnpm docs:generate
README Documentation
Package README Template
# @sgcarstrends/ui
Shared UI component library for SG Cars Trends platform.
## Installation
\`\`\`bash
pnpm add @sgcarstrends/ui
\`\`\`
## Usage
\`\`\`tsx
import { Button, Card, Dialog } from "@sgcarstrends/ui";
export function Example() {
return (
<Card>
<Button>Click me</Button>
</Card>
);
}
\`\`\`
## Components
### Core Components
- [Button](docs/components/button.md) - Customizable button with variants
- [Card](docs/components/card.md) - Container for content
- [Dialog](docs/components/dialog.md) - Modal dialog
- [Badge](docs/components/badge.md) - Status badges
### Form Components
- [Input](docs/components/input.md) - Text input
- [Textarea](docs/components/textarea.md) - Multi-line text input
- [Select](docs/components/select.md) - Dropdown select
- [Checkbox](docs/components/checkbox.md) - Checkbox input
### Layout Components
- [Separator](docs/components/separator.md) - Visual divider
- [Tabs](docs/components/tabs.md) - Tabbed interface
## Styling
Components use Tailwind CSS and CSS variables for theming.
### Dark Mode
Dark mode is supported via CSS variables defined in \`globals.css\`.
### Customization
Customize component styles:
\`\`\`tsx
<Button className="custom-classes">Custom Button</Button>
\`\`\`
## Development
\`\`\`bash
# Install dependencies
pnpm install
# Run tests
pnpm test
# Run Storybook
pnpm storybook
# Build package
pnpm build
\`\`\`
## Contributing
See [CONTRIBUTING.md](../../CONTRIBUTING.md)
## License
MIT
Props Table Generator
Create a script to generate props tables from TypeScript:
// scripts/generate-props-table.ts
import * as ts from "typescript";
import * as fs from "fs";
function generatePropsTable(componentPath: string) {
const program = ts.createProgram([componentPath], {});
const sourceFile = program.getSourceFile(componentPath);
if (!sourceFile) return;
const checker = program.getTypeChecker();
ts.forEachChild(sourceFile, (node) => {
if (ts.isInterfaceDeclaration(node) && node.name.text.endsWith("Props")) {
console.log(`| Prop | Type | Default | Description |`);
console.log(`|------|------|---------|-------------|`);
node.members.forEach((member) => {
if (ts.isPropertySignature(member) && member.name) {
const name = member.name.getText(sourceFile);
const type = checker.typeToString(
checker.getTypeAtLocation(member)
);
const docs = ts.displayPartsToString(
member.symbol?.getDocumentationComment(checker)
);
console.log(`| ${name} | \`${type}\` | - | ${docs} |`);
}
});
}
});
}
// Usage
generatePropsTable("src/components/button.tsx");
Component Checklist
When documenting a component, ensure:
- Component file has JSDoc comments
- Props interface is fully documented
- Markdown documentation file exists
- Usage examples provided
- Props table included
- Variants documented
- Accessibility notes added
- Related components linked
- Storybook stories created (if using Storybook)
- Exported from package index
- Added to README component list
Documentation Patterns
Code Examples
Always provide working code examples:
## Example: Search Form
\`\`\`tsx
"use client";
import { useState } from "react";
import { Input, Button } from "@sgcarstrends/ui";
export function SearchForm() {
const [query, setQuery] = useState("");
return (
<form className="flex gap-2">
<Input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
<Button type="submit">Search</Button>
</form>
);
}
\`\`\`
Do's and Don'ts
## Best Practices
### ✅ Do
- Use semantic HTML elements
- Provide accessible labels
- Test keyboard navigation
- Support dark mode
### ❌ Don't
- Nest buttons inside buttons
- Forget hover states
- Override core styles directly
- Skip accessibility attributes
Automated Documentation
Using react-docgen
pnpm add -D react-docgen-typescript
// scripts/generate-docs.ts
import { parse } from "react-docgen-typescript";
const options = {
savePropValueAsString: true,
shouldExtractLiteralValuesFromEnum: true,
};
const docs = parse("src/components/button.tsx", options);
console.log(JSON.stringify(docs, null, 2));
Testing Documentation
Ensure examples work:
// __tests__/docs/examples.test.tsx
import { render } from "@testing-library/react";
// Test all documented examples
describe("Documentation Examples", () => {
it("renders basic button example", () => {
const { container } = render(<Button>Click me</Button>);
expect(container.querySelector("button")).toBeInTheDocument();
});
it("renders button with icon example", () => {
const { container } = render(
<Button>
<span className="mr-2">📥</span>
Download
</Button>
);
expect(container.textContent).toContain("Download");
});
});
References
- Related files:
packages/ui/docs/- Component documentationpackages/ui/README.md- Package overviewpackages/ui/src/components/*.stories.tsx- Storybook storiespackages/ui/CLAUDE.md- UI package documentation
Best Practices
- Clear Examples: Provide complete, working code examples
- Props Documentation: Document every prop with type and description
- Accessibility: Include accessibility notes
- Visual Examples: Use Storybook for interactive demos
- Keep Updated: Update docs when components change
- Search Friendly: Use clear headings and keywords
- Code Quality: Test documented examples
- Version History: Track changes in documentation
Quick Install
/plugin add https://github.com/sgcarstrends/sgcarstrends/tree/main/component-docsCopy and paste this command in Claude Code to install this skill
GitHub 仓库
Related Skills
llamaindex
MetaLlamaIndex is a data framework for building RAG-powered LLM applications, specializing in document ingestion, indexing, and querying. It provides key features like vector indices, query engines, and agents, and supports over 300 data connectors. Use it for document Q&A, chatbots, and knowledge retrieval when building data-centric applications.
canvas-design
MetaThe canvas-design skill generates original visual art in PNG and PDF formats for creating posters, designs, and other static artwork. It operates through a two-step process: first creating a design philosophy document, then visually expressing it on a canvas. The skill focuses on original compositions using form, color, and space while avoiding copyright infringement by never copying existing artists' work.
go-test
MetaThe go-test skill provides expertise in Go's standard testing package and best practices. It helps developers implement table-driven tests, subtests, benchmarks, and coverage strategies while following Go conventions. Use it when writing test files, creating mocks, detecting race conditions, or organizing integration tests in Go projects.
business-rule-documentation
MetaThis skill provides standardized templates for systematically documenting business logic and domain knowledge following Domain-Driven Design principles. It helps developers capture business rules, process flows, decision trees, and terminology glossaries to maintain consistency between requirements and implementation. Use it when documenting domain models, creating business rule repositories, or bridging communication between business and technical teams.
