App reorganization
This commit is contained in:
@@ -22,24 +22,27 @@ app/components/controls/<Name>/
|
||||
**Container** (`<Name>.container.tsx`):
|
||||
|
||||
- Marked `"use client"`.
|
||||
- Receives `<Name>Props`; normalizes PascalCase enums via
|
||||
`lib/propNormalization.ts`; computes derived state (clamps, ids, bounds).
|
||||
- Renders `<<Name>View />` with already-normalized `<Name>ViewProps`.
|
||||
- Receives `<Name>Props`; computes derived state (clamps, ids, bounds, prop
|
||||
defaults) and bound event handlers.
|
||||
- Renders `<<Name>View />`. Containers do **not** translate prop casing —
|
||||
enum props are lowercase end-to-end (see `component-props.mdc`).
|
||||
- Default export: `memo(<Name>Container)` with `.displayName = "<Name>"`.
|
||||
- Carries the Figma docstring (`Figma: "<Path>" (<node-id>)`).
|
||||
|
||||
**View** (`<Name>.view.tsx`):
|
||||
|
||||
- Marked `"use client"`.
|
||||
- Pure render of `<Name>ViewProps`. No prop normalization, no data fetching,
|
||||
no derived business logic.
|
||||
- Default export: `memo(<Name>View)` with
|
||||
`.displayName = "<Name>View"`.
|
||||
- Pure render of `<Name>ViewProps`. No data fetching, no derived business
|
||||
logic, no enum casing translation.
|
||||
- Default export: `memo(<Name>View)` with `.displayName = "<Name>View"`.
|
||||
|
||||
**Types** (`<Name>.types.ts`):
|
||||
|
||||
- Export `<Name>Props` (consumer-facing, accepts PascalCase + lowercase).
|
||||
- Export `<Name>ViewProps` (already-normalized shape the view consumes).
|
||||
- Export any locally-defined value types (`<Name>SizeValue`, etc.).
|
||||
- Export `<Name>Props` (consumer-facing).
|
||||
- Export `<Name>ViewProps` (the shape the view consumes — typically a
|
||||
resolved superset of `<Name>Props`).
|
||||
- Export any locally-defined value types (`<Name>SizeValue`, etc.) sourced
|
||||
from the matching `*_OPTIONS` array in `lib/propNormalization.ts`.
|
||||
|
||||
**Index** (`index.tsx`):
|
||||
|
||||
@@ -51,10 +54,10 @@ export type { <Name>Props } from "./<Name>.types";
|
||||
## Single-file pattern (exception)
|
||||
|
||||
`app/components/buttons/*.tsx` and other trivially-presentational components
|
||||
can stay as a single file when they have **no enum prop normalization and no
|
||||
derived state** (e.g. `Button.tsx`, `InlineTextButton.tsx`). If you find
|
||||
yourself adding state, enum normalization, or more than a handful of props,
|
||||
promote it to the split pattern.
|
||||
can stay as a single file when they have **no derived state and only a
|
||||
handful of props** (e.g. `Button.tsx`, `InlineTextButton.tsx`). If you find
|
||||
yourself adding state, side effects, or enum logic, promote it to the split
|
||||
pattern.
|
||||
|
||||
## Wrapper / group components
|
||||
|
||||
|
||||
Reference in New Issue
Block a user