docs: teach overzicht, max-lines and the step contract (RD-33)

CLAUDE.md did not name the overzicht context that RD-03 created, and it did
not name the max-lines budget that RD-02 enforces. An agent that follows it
writes a long page into the wrong context, and meets a red build with no
warning.

CLAUDE.md now names the context, the @overzicht/* alias, the
overzicht -> registratie arrow, the 250-line budget and its glob, and the
step-component contract. layers.mdx gains the same arrow.

atomic-design.mdx credited eslint.config.mjs with the layer rules.
dependency-cruiser enforces them. Each tool is now named for what it does.
The page also gains the layer-folder table and the step contract.

Four paths were pre-monorepo: three example paths in the ui-component skill,
and two citations of libs/shared/src/ui/async, which RD-27 moved to
libs/shared/src/ui/molecules/async.

npm run ci --full passes: 67 and 45 storybook suites, 306 axe tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-09 16:14:56 +02:00
co-authored by Claude Opus 5
parent 682db41344
commit d9aef9541f
6 changed files with 179 additions and 23 deletions
+30 -3
View File
@@ -57,9 +57,36 @@ atoms — that is the whole point: fewer things to understand, nothing bespoke p
## The rule, enforced
**Each layer only uses layers below it, and dependencies point inward.** This is not a
convention you have to remember — `eslint.config.mjs` fails the build if `domain/` imports
Angular, or if a context imports "upward". See [the FP-in-the-UI primer](?path=/docs/foundations-fp-in-the-ui--docs)
for how the same discipline shapes state and effects.
convention you have to remember — `npm run dep:check` (dependency-cruiser) fails the build if
`domain/` imports Angular, or if a context imports "upward". `eslint.config.mjs` enforces a
different rule: the `any` ban, and a `max-lines` budget (250 lines, `skipBlankLines`,
`skipComments`) on every `{apps,libs}/**/*.{page,component,section,step}.ts` file — reachable,
not a style-guide default, since the dashboard page lands at 42 lines. See
[the FP-in-the-UI primer](?path=/docs/foundations-fp-in-the-ui--docs) for how the same
discipline shapes state and effects.
## The layer folders
| Layer | Where |
| --------- | --------------------------------------------------------------------------------------------------------------------------- |
| Atoms | `libs/shared/src/ui/atoms/` |
| Molecules | `libs/shared/src/ui/molecules/` |
| Organisms | `libs/shared/src/ui/organisms/` |
| Templates | `libs/shared/src/layout/` — deliberately holds several layers; its own organisms are chrome that only its own templates use |
## The step-component contract
A wizard step follows the same rule as `address-fields.component.ts`: values in, events
out, no internal state.
1. **Inputs down.** A step reads its data only from `input()`s the container passes it.
2. **One narrow output up.** A step emits one specific event, not the container's whole
`dispatch`.
3. **`dispatch` is never passed down.** The container owns the Model and decides what a
step's event means; a step never calls `dispatch` itself.
Corollary: a step gets **no** story of its own. The wizard's own story already mounts every
step, because it seeds the machine.
## A composition chain, live
+1
View File
@@ -38,6 +38,7 @@ different login flows, so the two copies are expected to diverge.
**Dependencies only point inward, in one declared direction between contexts:**
```
overzicht → registratie → libs/shared|beheer (ssp)
herregistratie → registratie → libs/shared|beheer (ssp)
auth → libs/shared|beheer (ssp)
brief → libs/shared|beheer (ssp)