Component Organization
When to Use
Use when setting up a design system repository or deciding where to put a new component.
Decision
| If you need... | Use... | Why |
|---|---|---|
| Small-medium system (<50 components) | Flat component folders | Simple; no mental model overhead; easy to navigate |
| Large system or team structure guidance | Atomic design (atoms/molecules/organisms) | Shared vocabulary; consistent grouping decisions |
| Co-located styles/stories/tests | Same folder as component | Easier to find, move, and delete; no cross-directory tracking |
| Public API control | Explicit barrel exports | Prevent consumers from importing internal utilities |
| Monorepo design system package | packages/ui/ with its own package.json |
Separate versioning; consumed by multiple apps |
Pattern
Recommended flat structure (small-medium systems):
src/components/
Button/
Button.tsx # Component
Button.stories.tsx # Stories
Button.test.tsx # Tests
index.ts # Re-export: export { Button } from './Button';
Input/
...
Card/
...
index.ts # Root barrel: export * from './Button'; export * from './Input';
Atomic structure (large systems):
src/components/
atoms/ # Button, Input, Icon, Badge, Label
molecules/ # FormField (Label + Input + Error), SearchBar
organisms/ # NavigationBar, DataTable, PageHeader
layout/ # Stack, Flex, Grid, Container
index.ts # Single export point
Barrel export (explicit — don't re-export internals):
// components/Button/index.ts
export { Button } from './Button';
export type { ButtonProps } from './Button';
// NOT: export * from './Button' (leaks internal helpers)
Common Mistakes
- Wrong: Deep barrel exports with
export * from '...'at every level → Right: Prefer explicit named exports; wildcard re-exports break tree-shaking in some bundlers - Wrong: Mixing component files with page/feature files → Right: The components directory is for reusable UI only; page-specific code lives in
app/orpages/ - Wrong: No
index.tsper component folder → Right: Always add one; without it callers import fromButton/Buttoninconsistently - Wrong: Committing to atomic terminology too early → Right: Use flat structure until patterns emerge naturally; rename later
- Wrong: Putting test utilities and mock data inside component folders → Right: Shared mocks belong in
src/test-utils/; co-location is for component-specific tests only