import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Contributing" />

<div className="sb-doc">

# Contributing to Shade

<p className="excerpt">This guide explains how to contribute to the Shade design system, including adding or modifying components and documentation.</p>

## Quick Start (Humans and Agents)

Use this sequence before writing code:

1. Pick the right layer (`tokens`, `primitives`, `components`, `patterns`).
2. Reuse existing APIs first.
3. If no good fit exists, keep code local first.
4. Add shared abstractions to Shade only after clear repetition.
5. Add stories that prove intended usage and states.

If unsure between `components` and `patterns`:

- choose `components` for generic controls
- choose `patterns` for product workflow composition

## Repository Layout

```
/apps/shade/
  .storybook/                 # Storybook config
  src/
    components/
      ui/                     # Base ShadCN/UI primitives
      layout/                 # Composed, reusable layout components
      features/               # Feature-specific, higher-level components
    docs/                     # System docs rendered in Storybook
```

## Import From Layered Entrypoints

For new code, import from a layer-specific Shade subpath instead of the root barrel:

- `@tryghost/shade/tokens` (+ `@tryghost/shade/tokens.css` for CSS token consumption)
- `@tryghost/shade/primitives`
- `@tryghost/shade/components`
- `@tryghost/shade/patterns`
- `@tryghost/shade/app`
- `@tryghost/shade/utils`

Use the root `@tryghost/shade` entrypoint only for DS-layer compatibility (`tokens`/`primitives`/`components`/`patterns`).
Do not import `utils` or `app` symbols from root.

## Ownership and "Add to Shade" Rules

- Put token names/helpers and CSS token definitions in `tokens`.
- Put layout/structure-only abstractions in `primitives`.
- Put reusable controls and visual assets in `components`.
- Put reusable feature-level compositions/rules in `patterns`.
- Put app shell/provider/context APIs in `app`.
- Keep `utils` design-system-safe only (generic helpers/hooks + third-party namespaces).
- Do not add new domain/product helpers to `utils`; place them in app-local code or transitional `app` exports.

## Primitive Composition Guardrails

- Prefer `Stack`, `Inline`, `Box`, `Container`, `Grid`, and `Text` over anonymous wrappers that only carry layout utility classes.
- Layout-shell migration scope is limited to `apps/shade/src/components/layout/*`.
- Keep existing `@tryghost/shade/primitives` consumers compatible during migration; do not remove legacy exports during compatibility windows.
- Use semantic spacing props (`none | xs | sm | md | lg | xl | 2xl`) for primitive composition APIs.

## Component Rules and Guarantees

- Shared controls in `apps/shade/src/components/ui/*` must be product-agnostic.
- Define explicit public API and state rules before expanding variants.
- Required interactive states for shared controls: `default`, `hover`, `focus-visible`, `disabled`.
- If behavior becomes workflow-specific, move it into a `patterns` wrapper instead of growing the base control API.

## AI Agent Output Format

When an AI agent proposes or changes a shared component, include:

1. `Scope` (purpose + non-goals)
2. `Public API` (props, slots, variants)
3. `States` (`default`, `hover`, `focus-visible`, `disabled` at minimum)
4. `Compatibility notes` (what changed, what remains stable)

## Naming Conventions

- **File names:** kebab-case, e.g. `dropdown-menu.tsx` (ShadCN-generated files keep kebab-case)
  ```
  dropdown-menu.tsx
  dropdown-menu.stories.tsx
  # optional extras below
  dropdown-menu.mdx
  dropdown-menu.meta.json
  fixtures/dropdown-menu.fixtures.ts
  ```
- **Storybook titles:**
  - UI primitives: `Components / <Name>` (e.g., `Components / Button`)
  - Layout: `Layout / <Name>` (e.g., `Layout / Page`)
  - Features: `Features / <Name>` (e.g., `Features / Post Share Modal`)
- **Component folders:**
  - ShadCN primitives under `/apps/shade/src/components/ui/`
  - Composed layout components under `/apps/shade/src/components/layout/`
  - Feature components under `/apps/shade/src/components/features/`

## File Set Per Component

Each documented component requires:

```
/apps/shade/src/components/ui/button.tsx          # Component (source)
/apps/shade/src/components/ui/button.stories.tsx  # Stories (CSF)
/apps/shade/src/components/ui/button.mdx          # (optional) component docs (MDX)

# Optional metadata & fixtures
/apps/shade/src/components/ui/button.meta.json    # Machine-readable metadata
/apps/shade/src/components/ui/fixtures/button.fixtures.ts
```

## Component Documentation in Storybook

We document components through concise stories that show real use cases. Each story should have a one‑line description explaining when to use that variant/state. Prefer multiple focused stories over long prose.

Required for every component:
- A colocated `*.stories.tsx` using CSF with:
  - `title` under the right section (Components / Layout / Features)
  - `tags: ['autodocs']`
  - An overview via `parameters.docs.description.component`
  - Stories covering key variants and states with `parameters.docs.description.story`

Example:

```tsx
import type {Meta, StoryObj} from '@storybook/react-vite';
import {Button} from './button';

const meta: Meta<typeof Button> = {
  title: 'Components / Button',
  component: Button,
  tags: ['autodocs'],
  parameters: {
    docs: {
      description: {
        component: 'Reusable button for actions. Choose variant/size by context.'
      }
    }
  }
};
export default meta;
type Story = StoryObj<typeof Button>;

export const Default: Story = {
  args: {children: 'Continue'},
  parameters: {
    docs: {description: {story: 'Primary call‑to‑action with default styling.'}}
  }
};

export const Destructive: Story = {
  args: {variant: 'destructive', children: 'Delete'},
  parameters: {
    docs: {description: {story: 'Use for dangerous or irreversible actions.'}}
  }
};
```

## Component Implementation

### Using ShadCN/UI

1. **Install Component**
   ```bash
   npx shadcn@latest add button
   ```

2. **Customize Implementation**

   > ⚠️ Always use the `cn` utility to combine classNames and `cva` for component variants. This ensures consistent class merging and variant handling across the design system.

   ```tsx
   import { cn } from "@/lib/utils"
   import { cva, type VariantProps } from "class-variance-authority"

   // Define variants using cva
   const buttonVariants = cva(
       // Base styles applied to all variants
       "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
       {
           variants: {
               variant: {
                   solid: "bg-primary text-primary-foreground hover:bg-primary/90",
                   outline: "border border-input bg-background hover:bg-accent",
                   ghost: "hover:bg-accent hover:text-accent-foreground"
               },
               size: {
                   sm: "h-9 px-3",
                   md: "h-10 px-4",
                   lg: "h-11 px-8"
               }
           },
           defaultVariants: {
               variant: "solid",
               size: "md"
           }
       }
   );

   // Extract variant props type
   interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>,
       VariantProps<typeof buttonVariants> {}

   // Use cn to combine variants with custom classes
   export function Button({ className, variant, size, ...props }: ButtonProps) {
       return (
           <button
               className={cn(buttonVariants({ variant, size }), className)}
               {...props}
           />
       );
   }
   ```

   **Key Points:**
   - Use `cn` to merge component variants with custom className props
   - Define variants with `cva` for type-safe variant combinations
   - Extract variant props using `VariantProps` type
   - Always provide sensible default variants
   - Include hover/focus states in variant definitions

### Prefer Compound Subcomponents

When a component has multiple meaningful regions (title, meta, actions, etc.), prefer a compound subcomponents API over many props. This keeps the API composable and flexible.

Example (Header):

```tsx
function Header(props) { /* ... */ }
function HeaderTitle(props) { /* ... */ }
function HeaderMeta(props) { /* ... */ }
function HeaderActions(props) { /* ... */ }

Header.Title = HeaderTitle;
Header.Meta = HeaderMeta;
Header.Actions = HeaderActions;

export {Header};

// Usage
<Header>
  <Header.Title>Members</Header.Title>
  <Header.Meta>42,102 total</Header.Meta>
  <Header.Actions><Button>New member</Button></Header.Actions>
  {/* ... */}
</Header>
```

Tips:
- Attach parts as static properties and export them as named exports for convenience.
- Keep parts small and focused; forward and merge `className`.
- Demonstrate parts usage in stories (e.g., “With actions”, “With meta”).

### Creating Custom Components

1. **File Structure**
   ```
   # Layout component
   src/components/layout/
   ├── custom-component.tsx
   ├── custom-component.stories.tsx
   └── custom-component.mdx

   # Feature component
   src/components/features/
   ├── custom-component.tsx
   ├── custom-component.stories.tsx
   └── custom-component.mdx
   ```

2. **Implementation Pattern**
   ```tsx
   import { cn } from "@/lib/utils"

   interface CustomComponentProps {
       className?: string;
   }

   export function CustomComponent({ className }: CustomComponentProps) {
       return (
           <div className={cn("base-styles", className)}>
               {/* Component content */}
           </div>
       );
   }
   ```

## Acceptance Checklist

For each component:

- [ ] Component follows design system principles
- [ ] Prefer compound subcomponents for multi‑region components
- [ ] `*.stories.tsx` includes: overview + key variants and states
- [ ] Each story has a short “when to use” description
- [ ] Accessibility is considered (labels, focus, disabled) and reflected in stories/args
- [ ] Slots are listed in Anatomy and demonstrated
- [ ] Accessibility items include keyboard, ARIA, and contrast
- [ ] (Optional) `*.meta.json` present and valid

## ShadCN Installation Guardrails

- Never overwrite existing Shade components during `npx shadcn@latest add <name>` prompts — choose “No”.
- Work on a fresh branch before running the installer: `git checkout -b chore/shadcn-add-<name>`.
- If a component already exists, generate into a scratch repo and manually diff; port only the desired changes.
- After integrating, run `yarn lint`, `yarn test`, and verify in Storybook.

## Utilities

- Import utilities from `@/lib/utils`.
- Always forward and merge `className` with `cn(...)` and prefer CVA for variants when useful.

## Agents & Repo Conventions

Refer to `AGENTS.md` at the repository root for additional, repo-specific guidance used by both humans and agents. It covers:
- Project structure and module organization
- Build, test, and development commands
- Coding style, naming conventions, and Tailwind scoping
- Adding new components and ShadCN guardrails
- Testing expectations and commit/PR guidelines

</div>
