Skip to content

Code Block

components specs/components/code-block.kmd

Code-block widget — the multi-framework code-tabs surface that hosts per-format code samples behind a shared tab strip (HTML / Flutter / Compose / SwiftUI / Web Components), with a per-tab copy button and a transient "Copied" toast. The framework choice persists across the session so picking "Flutter" once shows Flutter in every code block.

When this spec applies

Primary triggers

All triggers

Specification body

Spec — Code Block

Facet Visual do Koder Design. The KDS realization of material.io's multi-framework code panels — the highest-value "designer crosses to developer" surface. Implemented in design-gen (internal/kinds CodeTabs + assets/js tab switcher; shipped in tools/design-gen#044, copy button #028).

Anatomy

┌───────────────────────────────────────────────┐
│ [HTML] Flutter  Compose  SwiftUI  Web   [Copy] │ ← tab strip + copy
├───────────────────────────────────────────────┤
│  <button class="kd-btn filled">Save</button>   │
│  …only the selected framework's panel shows…   │ ← <pre><code>
└───────────────────────────────────────────────┘
  • Tab strip: one tab per framework supplied; the active tab is marked aria-selected="true". Frameworks with no sample for a given block are omitted (no empty tabs).
  • Panels: one <pre><code> per framework; only the selected one is visible (others hidden). Mono type role (--kds-font-mono).
  • Copy button: top-right; copies the visible panel's text.

R1 — Single logical widget, N syntaxes

A code-block tags N samples that express the same widget in different frameworks. Switching tabs swaps syntax only — never the widget being demonstrated. A block MAY carry a single framework (then the tab strip collapses to a label, not a control).

R2 — Shared, persisted framework selection

All code-blocks on a page (and across the session) share one framework choice, persisted in localStorage["kds.framework"]. Picking a framework in any block updates every other block on the page immediately and restores on the next visit. Default when unset: the first framework declared on the block (HTML where present).

R3 — Syntax-agnostic rendering

Panels render pre-escaped, server-highlighted code. No client-side syntax-highlight dependency on the render path (policies/headless-first.kmd — the headless build emits the same HTML the user sees). Long lines scroll horizontally within the panel; they do not wrap or expand the page.

R4 — Copy affordance + transient confirmation

Each block exposes a copy button that writes the visible panel's raw text to the clipboard and shows a transient "Copied" toast for ~1.5 s, then reverts. The button keeps its label/icon between states (no layout shift). On clipboard failure the toast reads the canonical error per specs/errors/user-facing-messages.kmd — never a silent no-op. Reuses the SDK copy primitive (policies/reuse-first.kmd).

R5 — Accessibility

  • Tab strip is a role="tablist"; tabs are role="tab" with aria-controls pointing at their panel; panels are role="tabpanel".
  • Arrow keys move between tabs; Enter/Space activates; the copy button is reachable by Tab and announces its state change via aria-live.
  • Color contrast of tab/active states meets the themes/color-roles.kmd AA floor in both light and dark.

R6 — Degradation (no JS)

With JavaScript disabled, every framework panel is visible (stacked, each under its framework label) and the copy button is hidden — the content is never gated behind the switcher.

Out of scope

  • Editable / runnable code (playground) — see the component prop playground surface, not this block.
  • Diff rendering — a separate future surface.

References