Code block

Code block docs Controller

Fenced code surface with optional language chip and copy control — server-emitted chrome for docs and samples. Syntax colour is build-time token spans (Python), not a browser highlighter.

Layer: L1 surface · Recipe: unset — see docs/agent/pick-a-surface.md. Curriculum: AGENTS.md; pick matrix: docs/agent/pick-a-surface.md; blast radius: CONSUMER_MAP.md.

python
def greet(name: str) -> str:
    """Return a friendly hello."""
    return f"Hello, {name}"

Copy this

html
<figure class="code" data-code data-language="python">
  <div class="code__meta"><span class="code__lang">python</span><button type="button" class="code__copy" data-code-copy aria-label="Copy code to clipboard"><span class="code__copy-idle">Copy</span><span class="code__copy-done">Copied</span></button></div>
  <pre class="code__pre" tabindex="0" role="region" aria-label="Python example"><code class="code__source">def greet(name: str) -> str:
    """Return a friendly hello."""
    return f"Hello, {name}"
</code></pre>
</figure>

Server exchange

This Hyperpart has no server exchange — it is presentation or client chrome only. htmx does not issue a request on this part's behalf. If you put an affordance (hx-*) on a control that uses this markup, that action's exchange belongs to the action, not this part. See Swap contract for host-owned envelopes.

Swap contract

Agent-visible HTMX topology (ADR-0054 / decision 0012). exchange envelope = what the response may re-emit relative to the persistent slot (body_only | outer | none | host_owned | document). dual-lock validates part markup only — not this envelope. Stem: stems/morph-safe-hypermedia.md; decision: docs/decisions/0012-swap-identity-contract.md.

No host HTMX exchange on this part — presentation or client chrome only. exchange envelope: n/a.

If a host wraps this markup in hx-*, that host owns the swap contract (sole identity + envelope). Prefer innerMorph / outerMorph for stable slots; replacement for flash; body-only responses under inner swaps.

Envelope response examples

This part has no owned exchange (envelope n/a). If a host adds hx-*, that host’s envelope applies — typically body_only:

html
<!-- Host wraps this presentation part with hx-* (host owns envelope) -->
<!-- Prefer: hx-swap="innerMorph" hx-target="#panel-body" -->
<!-- Server returns body_only interior for #panel-body -->
<div class="dz-stack">content…</div>

Do not re-own the slot:

html
<!-- WRONG: server returns the presentation root with a new id every poll -->
<div id="code-root" data-dz-region>…</div>

How to use it

Seams

  • figure[data-code] → div.code__meta → pre.code__pre > code.code__source
  • meta flex row: optional .code__lang, optional [data-code-copy] (CSS margin-inline-start:auto keeps copy trailing)
  • build-time token spans (.code__tok--*) for Python and HTML colour
  • surface uses light-dark() — follows [data-theme], not always-dark

Do / Don't

DoDon't
emit figure > .code__meta > (lang? + copy?) > pre > codeabsolute-position the copy control or invent a one-off toolbar

Pitfalls

  • do not absolute-position .code__copy — it drifts left inside nested min-width:0 containers (Hyperpart detail pages); use the meta flex row
  • do not put copy/lang as direct children of the figure without .code__meta
  • do not ship a browser syntax engine for static docs — highlight at build (python + html/svg/xml only today)
  • copy must read textContent (not innerHTML) so spans never paste

Keyboard / AT

  • pre is a keyboard-scrollable region (tabindex=0)
  • copy button is a real button with aria-label

DOM contract

What the emitted HTML must satisfy — the table is the required surface; Python under contracts/ is the package-internal dual-lock CI runs (tests/test_contracts.py), not an app route. Standalone HTMX4: implement the API so responses match this markup. Dazzle: the agent emits SSR that already satisfies it. Do not invent attrs outside these tables. For request/response wiring see Server exchange.

contracts/code.py

Required in the DOM: root [data-code] (part code). Emit only these attributes — inventing extras is fine only if controllers ignore them; omitting required ones fails CI (tests/test_contracts.py).

NodeAttrConstraint
[data-code]data-codepresent (any value)
[data-code-copy]data-code-copypresent (any value)

Module source

Import path is monorepo/package-local (from contracts._kit import …). Source-token form often uses data-*; gallery demos above are unprefixed. Do not copy this into app routes.

python
"""HYPERPART: code — fenced code surface (root + optional copy control)."""

from contracts._kit import DomContract, Node, Present

DOM_CONTRACT = DomContract(
    part="code",
    root="[data-dz-code]",
    nodes=(
        Node("[data-dz-code]", attrs={"data-dz-code": Present()}),
        # Copy is optional chrome; when present the attr marks the control.
        Node("[data-dz-code-copy]", attrs={"data-dz-code-copy": Present()}),
    ),
)

__all__ = ["DOM_CONTRACT"]

Notes

Use the code Hyperpart for any fenced sample in docs or app chrome. Required nesting: figure.code[data-code] → div.code__meta (optional lang + optional copy) → pre.code__pre → code.code__source. Copy is pushed trailing by CSS (margin-inline-start: auto on the button) — do not absolute-position it (nested part-page flex/min-width:0 chains left-shift absolute children). The gallery builder runs a stdlib highlighter (site/highlight.py) for Python and HTML into code__tok--* spans; copy uses textContent so spans never paste. Omit the lang span when there is no language; omit the copy button when display-only (keep the meta bar if a lang chip remains). Scheme: the surface follows the page theme via light-dark() (light code on light pages, dark on dark) — not always-dark, so dense docs stay scannable.

Source files

One logical Hyperpart, 4 code items (CSS layered, JS bundled). Bound by HYPERPART: code — python tools/hyperpart.py code lists them.

site/registry.py · contracts/code.py · components/code.css:1 · controllers/dz-code.js