# Documentation Reference (TypeScript + React) ## Documentation Strategy ### Three Layers 1. **Code Documentation** (JSDoc) - Inline with code 2. **Component Documentation** (Storybook) - Visual examples 3. **Feature Documentation** (Markdown) - Architecture and decisions ## JSDoc Best Practices ### Documenting Components ```typescript /** * A reusable button component with multiple variants and states. * * Supports primary, secondary, and danger variants. Can display * loading states and be disabled. Fully accessible with ARIA attributes. * * @example * ```tsx * // Primary button * * * ) * } * ``` */ export function useFormValidation( schema: ZodSchema, initialValues: T, onSubmit: (data: T) => Promise ): UseFormValidationReturn { // Implementation } ``` ### Documenting Types ```typescript /** * Branded type for user IDs. * * Prevents accidentally passing any string as a user ID. * Must be created through `createUserId` validation function. * * @example * ```typescript * // ❌ Error: Type 'string' is not assignable to type 'UserId' * const id: UserId = "some-id" * * // ✅ Must use constructor * const id = createUserId("uuid-here") * * // ✅ Type-safe function parameters * function getUser(id: UserId): User { * // id is guaranteed to be validated * } * ``` */ export type UserId = Brand /** * Creates a validated UserId. * * @param value - String to validate as user ID * @returns Branded UserId type * @throws {Error} If value is empty or invalid format * * @example * ```typescript * try { * const id = createUserId("550e8400-e29b-41d4-a716-446655440000") * // id is now UserId type * } catch (error) { * console.error("Invalid user ID") * } * ``` */ export function createUserId(value: string): UserId { if (!value || !isValidUUID(value)) { throw new Error(`Invalid user ID: ${value}`) } return value as UserId } ``` ## Storybook Templates ### Basic Component Story ```typescript import type { Meta, StoryObj } from '@storybook/react' import { Button } from './Button' const meta: Meta = { title: 'Components/Button', component: Button, parameters: { layout: 'centered', docs: { description: { component: 'A versatile button component with multiple variants and states.' } } }, tags: ['autodocs'], argTypes: { variant: { control: 'select', options: ['primary', 'secondary', 'danger'], description: 'Visual style variant' }, isDisabled: { control: 'boolean', description: 'Disables the button' } } } export default meta type Story = StoryObj export const Default: Story = { args: { label: 'Button', variant: 'primary', onClick: () => console.log('clicked') } } export const AllVariants: Story = { render: () => (
) } ``` ### Form Component Story ```typescript import type { Meta, StoryObj } from '@storybook/react' import { userEvent, within, expect } from '@storybook/test' import { LoginForm } from './LoginForm' const meta: Meta = { title: 'Features/Auth/LoginForm', component: LoginForm, parameters: { layout: 'centered' } } export default meta type Story = StoryObj export const Default: Story = {} // Interactive story with testing export const FilledForm: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement) // Fill form await userEvent.type(canvas.getByLabelText(/email/i), 'test@example.com') await userEvent.type(canvas.getByLabelText(/password/i), 'password123') // Click submit await userEvent.click(canvas.getByRole('button', { name: /log in/i })) // Assert loading state appears await expect(canvas.getByText(/logging in/i)).toBeInTheDocument() } } export const WithErrors: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement) // Submit without filling await userEvent.click(canvas.getByRole('button', { name: /log in/i })) // Assert errors appear await expect(canvas.getByText(/email is required/i)).toBeInTheDocument() } } ``` ## Feature Documentation Template Complete template in SKILL.md. Key sections: ### Executive Summary ```markdown # Feature: [Name] ## TL;DR One-paragraph summary of what this feature does and why it matters. ## Quick Start ```typescript // Minimal example showing feature in action ``` ``` ### Problem & Solution ```markdown ## Problem What pain point does this solve? Be specific. Example: "Users couldn't authenticate because..." ## Solution How does this feature solve it? High-level approach. Example: "Implemented OAuth2 flow with JWT tokens..." ``` ### Architecture ```markdown ## Architecture ### Component Tree ``` AuthProvider └── LoginContainer ├── LoginForm (presentational) ├── PasswordInput (presentational) └── ErrorDisplay (presentational) ``` ### Data Flow ```mermaid graph LR User[User Input] --> Form[LoginForm] Form --> Hook[useAuth] Hook --> API[Auth API] API --> Context[AuthContext] Context --> App[App State] ``` ### File Structure ``` src/features/auth/ ├── components/ │ ├── LoginForm.tsx # Main form component │ ├── LoginForm.test.tsx # Tests │ └── LoginForm.stories.tsx # Storybook ├── hooks/ │ ├── useAuth.ts # Auth logic │ └── useAuth.test.ts # Hook tests ├── context/ │ └── AuthContext.tsx # Shared auth state ├── types.ts # Email, UserId types ├── api.ts # API client └── index.ts # Public exports ``` ``` ### Design Decisions ```markdown ## Key Design Decisions ### 1. Context for Auth State **Decision**: Use React Context for auth state instead of prop drilling **Rationale**: - Auth state needed in 10+ components (nav, profile, settings, routes) - Prop drilling through 4+ levels would be unmaintainable - Context provides clean API and prevents coupling **Alternatives Considered**: - Redux: Overkill for single feature state - Zustand: Added dependency, context sufficient - Prop drilling: Would couple many components **Trade-offs**: - ✅ Gained: Clean API, decoupled components, easy testing - ❌ Lost: Some component isolation, potential rerender issues - ⚖️ Mitigation: Split context into state and actions to minimize rerenders ``` ### Usage Examples ```markdown ## Usage ### Basic Usage ```typescript // Most common use case (90% of usage) function ProtectedPage() { const { user, logout } = useAuth() if (!user) return return (

Welcome {user.name}

) } ``` ### Advanced Usage ```typescript // Complex scenario or edge case function AdminDashboard() { const { user, isLoading, error, refreshToken } = useAuth() // Handle token refresh useEffect(() => { const interval = setInterval(refreshToken, 14 * 60 * 1000) // 14 min return () => clearInterval(interval) }, [refreshToken]) // ... rest of component } ``` ``` ## Documentation Checklist Before considering documentation complete: ### Storybook Stories - [ ] Story file created for each component - [ ] Default story shows typical usage - [ ] All prop variants documented - [ ] Interactive states shown (loading, error, disabled) - [ ] Accessibility checks pass (a11y addon) - [ ] Controls configured for props - [ ] Component description added ### JSDoc Comments - [ ] All public types documented - [ ] All custom hooks documented - [ ] Complex functions documented - [ ] Examples included and working - [ ] Parameters documented with types - [ ] Return values documented ### Feature Documentation - [ ] Problem/solution described - [ ] Architecture explained - [ ] Design decisions documented (WHY) - [ ] Usage examples provided (basic + advanced) - [ ] API reference complete - [ ] Testing strategy documented - [ ] Accessibility features listed - [ ] Troubleshooting guide included - [ ] Related features linked ## Documentation Maintenance ### When Code Changes | Change | Update Needed | |--------|--------------| | New prop added | Update Storybook story, JSDoc, examples | | Prop removed | Update all documentation, mark as breaking | | New variant | Add Storybook story, update docs | | API change | Update JSDoc, examples, feature docs | | New hook | Create JSDoc, add examples | | Refactor (no API change) | May update architecture docs | | Bug fix | Update troubleshooting if relevant | | Design decision changed | Update design decisions section | ### Regular Reviews - **Quarterly**: Review all feature docs for accuracy - **On major releases**: Update all examples to latest API - **When onboarding**: Test docs with new team members ## Tools and Automation ### Storybook Addons ```javascript // .storybook/main.js module.exports = { addons: [ '@storybook/addon-essentials', // Docs, controls, actions, etc. '@storybook/addon-a11y', // Accessibility checks '@storybook/addon-interactions', // Interactive testing '@storybook/addon-links' // Navigate between stories ] } ``` ### TypeDoc Configuration ```json // typedoc.json { "entryPoints": ["src/index.ts"], "out": "docs/api", "exclude": ["**/*.test.ts", "**/*.stories.tsx"], "excludePrivate": true, "excludeProtected": true, "readme": "README.md" } ``` ## Summary ### Key Principles 1. **Document WHY**: Decisions and trade-offs 2. **Show Code**: Working examples over prose 3. **Keep Updated**: Docs with code changes 4. **Test Examples**: Storybook stories compile and run 5. **Multiple Audiences**: Humans and AI both need context 6. **Focus on Usage**: Not implementation details 7. **Colocate**: Docs near code they document ### Documentation Types - **JSDoc**: Inline code documentation - **Storybook**: Visual component examples - **Feature Docs**: Architecture and decisions ### Quality Indicators Good documentation: - Has working code examples - Explains WHY, not just WHAT - Shows common AND edge cases - Is kept up to date - Helps both debugging and extending Bad documentation: - Out of date with code - Only describes WHAT code does - No examples or broken examples - Implementation details instead of usage - Written once, never updated