---
name: create-component
description: >-
Creates a new UI component with implementation, index, tests, and Storybook
stories following PageZERO conventions. Use when adding a UI component or when
the user asks to scaffold a component in packages/ui or apps.
disable-model-invocation: true
---
# Create Component
Create a new UI component following the PageZERO component structure pattern.
## Gather Information
Ask the user in a single question:
> What component would you like to create and where should it go?
>
> - **Purpose**: What should it do/display?
> - **Location**: `packages/ui/` (reusable) or `apps/{feature}/components/` (feature-specific)
## Instructions
After gathering the information, create the full component structure:
1. **Determine the location**:
- UI components go in `packages/ui/{component-name}/`
- Feature components go in `apps/{feature}/components/{component-name}/`
- Ask if unclear
2. **Create 4 files** following the naming convention `{component-name}.tsx`:
### `{component-name}.tsx` - Component Implementation
```tsx
import * as React from "react"
import { cn } from "@/ui/utils"
interface {ComponentName}Props {
className?: string
children?: React.ReactNode
}
function {ComponentName}({ className, children }: {ComponentName}Props) {
return (
{children}
)
}
export { {ComponentName}, type {ComponentName}Props }
```
### `index.ts` - Public Exports
```ts
export * from "./{component-name}"
```
### `{component-name}.test.tsx` - Unit Tests
```tsx
import { render, screen } from "@testing-library/react"
import { describe, expect, it } from "vitest"
import { {ComponentName} } from "./{component-name}"
describe("<{ComponentName} />", () => {
it("renders", () => {
render(<{ComponentName}>Test content{ComponentName}>)
expect(screen.getByText("Test content")).toBeInTheDocument()
})
})
```
### `{component-name}.stories.tsx` - Storybook Stories
```tsx
import type { Meta, StoryObj } from "@storybook/tanstack-react"
import { {ComponentName} } from "./{component-name}"
const meta = {
title: "{StoryTitle}/{ComponentName}",
component: {ComponentName},
parameters: {
layout: "centered",
},
tags: ["autodocs"],
} satisfies Meta
export default meta
type Story = StoryObj
export const Default: Story = {
args: {
children: "{ComponentName}",
},
}
```
## Naming Conventions
- **File names**: Use kebab-case (e.g., `checkout-button.tsx`)
- **Component names**: Use PascalCase (e.g., `CheckoutButton`)
- **Story titles**:
- UI components: `"Packages/UI/{ComponentName}"`
- Feature components: `"Apps/{FeatureName}/{ComponentName}"`
## Variants (if needed)
For components with variants, use `cva` (class-variance-authority):
```tsx
import { cva, type VariantProps } from "class-variance-authority"
const {componentName}Variants = cva("base-classes", {
variants: {
variant: {
default: "default-classes",
secondary: "secondary-classes",
},
size: {
default: "size-default",
sm: "size-sm",
lg: "size-lg",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
})
type {ComponentName}Props = React.ComponentProps<"div"> &
VariantProps
```
## After Creation
1. Run `bun run check:fix` to format the new files (use `required_permissions: ["all"]` to run outside sandbox)
2. Run `bun run test` to verify tests pass
3. Provide user link to relevant Storybook story