Azalea

CodeBlock

Text meant to be read exactly.

Why it exists

Nineteen files render a <pre> and eleven of them JSON.stringify into one, each with its own padding, background and decision about overflow. That last one is the bug: several set no overflow at all, so a single long line — a base64 body, a minified error — stretched the page and gave the whole document a horizontal scrollbar. On a phone that makes every other element scroll sideways too.

POST /v1/messages
POST /v1/messages 400 {"error":"invalid_recipient","detail":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkF2ZXJvYSIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}

A payload

JsonBlock stringifies for you, because the failure mode is shared: JSON.stringify throws on a circular structure and returns undefined for a function, and a page that renders a payload has no business crashing over the shape of one.

event.payload
{
  "id": "evt_9f2c4a7e",
  "type": "message.delivered",
  "recipient": "ops@example.co.id",
  "provider": {
    "name": "postmark",
    "latencyMs": 412,
    "region": "eu-west-1"
  },
  "attempts": [
    {
      "at": "2026-09-08T11:58:02Z",
      "status": "failed"
    }
  ]
}

Numbered, for a trace

Line numbers where the line numbers are the point. They are select-none, so copying the block by hand does not drag them into the paste — and the copy button never had them in the first place.

stack
TypeError: Cannot read properties of undefined (reading 'id')    at resolveRecipient (/app/src/lib/echo/send.ts:142:28)    at async deliver (/app/src/lib/echo/deliver.ts:61:14)    at async tick (/app/src/app/api/cron/tick/route.ts:29:5)

In both themes

light

curl -X POST https://echo.trellis.id/v1/messages \
  -H "authorization: Bearer $ECHO_KEY"

dark

curl -X POST https://echo.trellis.id/v1/messages \
  -H "authorization: Bearer $ECHO_KEY"

Guidance

Use it when

  • A payload, a command, a trace — anything a person will read character by character or paste elsewhere.
  • maxLines whenever the content is unbounded. A 4,000-line payload buries the page it was attached to.
  • numbered for a trace, where the line number is how people talk about it.

Reach for something else when

  • Prose. Monospace tells the reader this is an identifier, and a sentence in it is a mixed signal.
  • A single short value with a copy button — that is CopyField, which wraps rather than scrolls.
  • Syntax highlighting. It is not here, deliberately: it needs a parser per language, and a wrong highlight is a false claim about the code.

Props

PropTypeDefaultDescription
codestringThe text.
titlestringA filename, an endpoint, a content type — shown in the bar above.
copybooleantrueThe copy button. This text exists to be pasted.
maxLinesnumberCaps the height. The block still scrolls to the end.
numberedbooleanfalseLine numbers down the left.
JsonBlock valueunknownStringified for you, and safely.

Accessibility

The <pre> carries tabIndex=0, because a region that scrolls must be reachable by keyboard — without it, everything past the right edge is available only to a mouse. The focus ring is inset so it draws inside the block rather than overlapping the border above it.