Overview
Components in this project follow a strict organizational pattern that emphasizes consistency, maintainability, and developer experience. Every component lives in its own directory with colocated CSS modules and follows kebab-case naming conventions.Directory Structure
Each component lives in its own directory within/components/ with the following pattern:
Key Principles
- One component per directory: Each component gets its own folder named in kebab-case
- Named exports from
index.tsx: Always export components using named exports, never default exports - Colocated styles: CSS modules live alongside components with the name
styles.module.css - Colocated utilities: Component-specific utilities can be added to the component directory
Naming Conventions
All file and directory names use kebab-case throughout the project. The only exception is React component function names, which use PascalCase.
Examples
Component Definition Patterns
Function Declarations with Explicit Interfaces
Always use function declarations (not arrow functions) with explicit TypeScript interfaces:components/button/index.tsx
Data Attributes for Variants
Use data attributes instead of multiple className conditionals for cleaner variant styling:clsx with multiple conditional classes and keeps the variant logic in CSS.
Client vs Server Components
When to Use “use client”
Only add the"use client" directive when the component needs client-side features:
required
Components using
useState, useEffect, useRef, etc.required
Access to
window, localStorage, document, etc.required
Components with
onClick, onChange, or other interactive eventsrequired
Using Motion (Framer Motion) or other animation libraries
Examples
Integration with Base UI
The project uses Base UI for headless component primitives. Components wrap Base UI components to add styling and project-specific behavior:components/popover/index.tsx
Usage
Motion Integration
Usemotion.create() to wrap Base UI components with animation capabilities:
Import Patterns
Use path aliases fromtsconfig.json for clean imports:
Type Definitions
Component-Specific Types
Define component props interfaces in the same file:Shared Types
Define shared types in/lib/types.ts:
lib/types.ts
Content Components
MDX content uses the same organizational pattern with colocated demos:Demo Export Pattern
content/12-principles-of-animation/demos/index.ts
content/12-principles-of-animation/index.mdx
Best Practices
- Keep components small and focused on a single responsibility
- Colocate styles, utilities, and tests with components
- Use TypeScript interfaces for all props, no
anytypes - Export using named exports, not default exports
- All files and directories use kebab-case:
button-group/,use-audio.ts - Component implementation is always
index.tsx - Styles are always
styles.module.css - React functions use PascalCase:
function Button()
- Always define explicit prop interfaces
- Avoid
anytype, useunknownwhen type is uncertain - Extend base component props when wrapping libraries
- Use strict TypeScript configuration