Malevich

Architecture decision record

ADR-0006 · Component classification

ADR 0006 — Component classification by functional role

Status

Accepted, 2026-05-18.

Source: v1.0 architectural quiz outcomes (docs-internal/architecture/v1-master-diff-merge.md §2). This ADR formalizes the decision; the master diff-merge remains the operational reference.

Context

The v0.1.0 model used three component groups — Elements, Blocks, Overlays — plus an informal notion of Sections via examples. In practice this caused recurring categorization disputes:

Without explicit functional criteria, the next ~40 v1.0 components (Spinner, Skeleton, Field-group, Site-header, Hero, etc.) would each trigger fresh categorization debates.

Decision

Components are classified into four functional layers, plus a preserved Overlays layer:

Layer Test Examples
Foundation No slots, no logic, called from many components, no own semantics Avatar, Icon, Typography, Divider, Spinner, Skeleton, Dots, Image
Element Fixed structure, takes props, doesn't accept arbitrary content Button, Input, Tabs, Badge, Alert, Tag, Kbd
Block Slots for elements; structural brick for sections Card, Accordion, Carousel, Breadcrumb, State
Section Slots for blocks; organizes a page region Hero, CTA, Site-header, Site-footer, layouts
Overlay Same component identity, but rendered in portal/top-layer Dialog, Sheet, Tooltip, Popover, Toast

The test is what the component does, not how complex it looks. A visually elaborate Foundation (Spinner with multi-ring animation) remains a Foundation because it has no slots and no semantics. A visually simple Block (a one-line Quote block) remains a Block because it has slots.

Element sub-categories

Elements subdivide into three folders by domain:

The sub-categorization is for file organization and discoverability. Lint rules and composition rules apply at the layer level, not the sub-category level.

Overlays preserved as a layer

Overlays are conceptually a presentation mode applied to existing components (a Dialog is a "Card in modal mode"). We considered collapsing them into a data-mode="overlay" modifier on Blocks. We rejected this because:

We preserve the mode concept in architectural discussions and AGENTS.md ("Toast and Notifications are overlay presentations of the same idea as inline Alert") but organize file structure and documentation as a discrete layer.

Composition rules

Circular composition is forbidden across layers. The linter (@malevich/lint) detects circular imports across layer folders.

Migration impact (v0.1.0 → v0.2.0)

Three existing components move:

The migration is a file move + import-path update. A codemod ships with v0.2.0 to update consumer imports automatically.

Consequences

Positive:

Negative / tradeoffs:

Alternatives considered

References