Skip to the content.

Atoms, molecules, organisms: the vocabulary of a component system

Atoms, molecules, organisms: the vocabulary of a component system

Atomic design gets dismissed as a folder-naming fad — “why do I have to call it an atom?” — but that misses the point. The value is not the folders; it is a shared vocabulary that lets a team argue about where a component belongs before anyone writes it. When “is this an atom or a molecule?” has an answer, so does “should this hold state?” and “may this fetch?” — because each layer carries rules. The names are a compression scheme for a whole set of decisions, and a team that shares them stops re-litigating the same structural questions on every PR.

Atoms compose into molecules, molecules into organisms An atom (input) and an atom (label) compose into a molecule (form field), and several molecules compose into an organism (a form). Complexity and responsibility grow left to right. atoms inputlabel molecule form field organism sign-up formmany fields + button complexity and responsibility grow →
The layers are a composition ladder: atoms are indivisible, molecules combine a few atoms, organisms assemble molecules into a meaningful section.

Atoms are indivisible and dumb

An atom is the smallest useful UI piece — a button, an input, a label, an icon. It takes props, renders, and emits events, and it holds no business logic and no knowledge of your data. The test for an atom is: could it live in any app? A button that knows about your cart is not an atom:

// atom: pure, reusable anywhere, knows nothing about your domain
export function Button({ variant = "primary", children, onClick }) {
  return <button className={`btn btn--${variant}`} onClick={onClick}>{children}</button>;
}

Molecules combine a few atoms into a unit

A molecule groups a small number of atoms into something with a single, clear job — a labelled input, a search field (input + button), a card header. It coordinates its atoms but still takes its data as props and stays free of business logic:

// molecule: composes atoms into one reusable unit, still prop-driven
export function FormField({ label, id, error, ...inputProps }) {
  return (
    <div className="field">
      <Label htmlFor={id}>{label}</Label>
      <Input id={id} aria-invalid={!!error} {...inputProps} />
      {error && <span className="field__error">{error}</span>}
    </div>
  );
}

Organisms are a meaningful section, still without a fetch

An organism assembles molecules and atoms into a distinct part of an interface — a sign-up form, a site header, a product card grid. It is the level where a “feature” starts to be visible, and it is exactly where discipline matters most: an organism still takes its data and callbacks as props. It does not fetch, and it does not reach into the store — that is a container’s job, one level up. Keeping the organism prop-driven is what lets you reuse the same sign-up form on the marketing site and inside the app, and render it in Storybook with fake data. The payoff of the whole vocabulary is this predictability: the layer name tells you the rules, so “where does this belong?” and “may it fetch?” stop being debates. The atom-boundaries exercise makes you place components on this ladder and defend the placement, which is the skill the names exist to support.