import { Meta, Canvas } from '@storybook/addon-docs/blocks';
import * as ButtonStories from '../app/shared/ui/button/button.stories';
import * as FormFieldStories from '../app/shared/ui/form-field/form-field.stories';
import * as PageShellStories from '../app/shared/layout/page-shell/page-shell.stories';

<Meta title="Foundations/Atomic Design" />

# Atomic design

Every screen in this app is built from a small set of layers, each composed **only from
the layer below it**. Read a screen top-down and you always land on the same handful of
atoms — that is the whole point: fewer things to understand, nothing bespoke per page.

<div style={{ display: 'grid', gap: '0.5rem', maxWidth: '32rem', margin: '1.5rem 0' }}>
  {[
    ['Templates', 'shared/layout', 'shell, page-shell, wizard-shell — the page skeleton', '#1e3a5f'],
    ['Organisms', 'shared/ui/upload/document-upload …', 'self-contained sections that own a bit of behaviour', '#2a5a8a'],
    ['Molecules', 'shared/ui/form-field, async …', 'a label + control + error, grouped', '#3f7cb5'],
    ['Atoms', 'shared/ui/button, text-input …', 'thin wrappers over Utrecht/RHC CSS classes', '#6aa6d8'],
  ].map(([name, where, why, bg], i) => (
    <div key={name} style={{ background: bg, color: '#fff', padding: '0.75rem 1rem', borderRadius: '6px', marginLeft: `${i * 1.5}rem` }}>
      <strong>{name}</strong> <span style={{ opacity: 0.85 }}>— {why}</span>
      <div style={{ fontFamily: 'monospace', fontSize: '0.75rem', opacity: 0.8, marginTop: '0.2rem' }}>{where}</div>
    </div>
  ))}
</div>

## 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.

## A composition chain, live

Here is one real chain from atom → molecule → template. Each is a published Storybook
story below; click through to the sidebar entries to explore every variant.

### Atom — `button`

A thin wrapper: we own a typed `variant` input, the RHC CSS owns the pixels.

<Canvas of={ButtonStories.Primary} />

### Molecule — `form-field`

Label + control + error text, grouped so the error is announced via `role="alert"`. It
composes atoms; it adds no new visual primitives of its own.

<Canvas of={FormFieldStories.WithError} />

### Organism — `document-upload`

`shared/ui/upload/document-upload` composes molecules (a file input, status banner,
progress bar, chips) into a section that owns real upload behaviour. It has no story yet
(Track A backlog); read it at `src/app/shared/ui/upload/document-upload/`.

### Template — `page-shell`

The page skeleton — title, optional back-link, content slot. Pages drop composed
organisms into it; the template never knows what they are.

<Canvas of={PageShellStories.WithBackLink} />

## Why bother

A new page should be **composition of existing blocks**. Adding a new building block is the
exception, not the reflex — if you reach for one, that is a signal to check whether an
existing atom/molecule already covers it. Fewer primitives → less to test, less to learn,
one place to fix a bug.
