Skip to content

Designing — Elements

foundations specs/foundations/elements.kmd

Element-level guidance for every Koder UI. Defines the unit cells of the design system — surfaces, text, controls, containers, and affordances — and the rules that compose them into pages. Material parity (`/foundations/designing/elements`); ratified as part of the Koder Design Visual facet expansion (#049.1).

When this spec applies

Primary triggers

All triggers

Specification body

Spec — Designing: Elements

Facet Visual do Koder Design. Material parity ref: https://m3.material.io/foundations/designing/elements.

Every Koder UI decomposes into 5 element families. Knowing which family a thing belongs to determines its allowed tokens, motion, elevation, and accessibility contract.

The 5 element families

FamilyPurposeExamplesToken group
SurfaceThe "paper" the UI is painted onApp background, sheet, card, dialog bodybg, surface, surface-variant
ContainerVisual grouping with structureCard frame, section group, list blocksurface, border, radius-*
ControlUser-actionable affordanceButton, switch, slider, linkaccent, accent-strong, accent-on
ContentConveyed informationText, image, icon, code blocktext, text-muted, typography scale
DecorationPure visual rhythm (no semantics)Divider, badge accent stripe, ornamentborder, accent-strong (sparingly)

Composition: every screen reduces to a tree where surfaces hold containers, containers hold content + controls, decorations punctuate.

R1 — Element identity is mandatory

A new visual block must declare which family it belongs to via class prefix:

  • .s-* — surface
  • .c-* — container (use the bare slug; existing convention)
  • .btn-*, .input-*, .switch-* — control (named by control type)
  • text, code, kbd, img — content (semantic HTML preferred)
  • .divider, .dot, .bar — decoration

Mixed-family blocks are an anti-pattern; split into nested elements.

R2 — Token discipline per family

FamilyMUST useMUST NOT use
Surfacebg/surface/surface-variantaccent (controls only)
Containersurface/border/radiusbg (surface owns the page bg)
Controlaccent/accent-strong/accent-on for actionstext-muted for primary action label
Contenttypography scale + text/text-mutedaccent as body text color (use links)
Decorationborder or muted accent at low opacityfull-strength accent (steals focus)

R3 — Affordance hierarchy

Within a single surface, controls follow strict hierarchy:

  1. Primary action — at most ONE per surface. accent filled.
  2. Secondary action — 0..N. outlined style.
  3. Tertiary — text-only / icon-only.
  4. Destructive — visually separated (right-aligned or hierarchy marker), uses error token not accent.

R4 — Touch target

All controls must satisfy minimum touch target per safe-area.kmd (48×48 dp mobile, 32×32 px desktop with 8px spacing).

R5 — Accessibility per family

FamilyA11y requirement
Surfacecolor-scheme matching theme; sufficient contrast for nested content
Containerrole="region" + aria-label when not implicit from heading
ControlVisible focus ring (outline: 2px solid focus); keyboard reachable; aria-* for state
ContentSemantic HTML (<h1>-<h6>, <p>, <img alt>); contrast AA minimum, AAA preferred
Decorationaria-hidden="true" (purely visual)

Examples

<!-- ✅ Surface > Container > (Content + Control) -->
<main class="s-page">
  <section class="c-card">
    <h2 class="text-title">User profile</h2>
    <p class="text-body">Update your display name.</p>
    <input class="input-text" type="text">
    <button class="btn-primary">Save</button>
  </section>
</main>
<!-- ❌ Mixed family: surface uses accent (control color) -->
<main class="s-page" style="background: var(--accent);">
  ...
</main>
  • app-layout/safe-area.kmd — touch targets + window insets
  • themes/color-schemes.kmd — token names per family
  • interaction/states.kmd — focus/hover/pressed/disabled per control
  • themes/ui-style.kmd — shape/density vary per family

References