Code block
Mono code on Row Mist with a title bar and copy, plus inline code.
Quick start
Send the key as a bearer token. Every endpoint returns JSON.
curl https://api.oration.app/v1/suppliers \
-H "Authorization: Bearer $ORATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Northwind Freight",
"remittance_email": "ar@northwindfreight.com"
}'import { Button } from "@oration/canon/components/button";import { CodeBlock } from "@oration/canon/components/code-block";import { toast } from "@oration/canon/components/toast";import * as React from "react";export function Hero() { const code = `curl https://api.oration.app/v1/suppliers \\ -H "Authorization: Bearer $ORATION_API_KEY" \\ -H "Content-Type: application/json" \\ -d '{ "name": "Northwind Freight", "remittance_email": "ar@northwindfreight.com" }'`; const headingId = React.useId(); return ( <section aria-labelledby={headingId} className="flex w-full max-w-xl flex-col gap-4" > <div className="flex flex-wrap items-end justify-between gap-3"> <div> <h2 id={headingId} className="text-sm font-semibold text-foreground" > Quick start </h2> <p className="mt-1 text-13 text-muted-foreground"> Send the key as a bearer token. Every endpoint returns JSON. </p> </div> <Button type="button" variant="outline" size="sm" onClick={() => toast.add({ title: "API reference", description: "Opens docs.oration.app in the full product.", }) } > View API reference </Button> </div> <CodeBlock title="Create a supplier" code={code} /> </section> );}Usage#
Code block shows a snippet or payload people copy or read exactly: 12px Geist Mono on Row Mist, under a 36px title bar with a copy button. InlineCode is its inline sibling for a key, ID or variable inside a sentence. Both exist for The Machine Mono Rule: mono is only for strings a machine produced or will parse. The mistake runs the other way too, putting amounts, counts or labels in InlineCode because they look technical.
When to use
- For a request people run, such as a curl command in the API quick start.
- For a request preamble people read line by line: a method, URL and headers.
- For a value they paste somewhere else in full, such as a generated URL.
- Use
InlineCodefor a machine string inside a sentence:vendor_id,{{vendor_id}},YOUR_PUBLIC_KEY, a slug to type.
When not to use
- For a JSON payload people inspect: a webhook body, an API response, an audit log event, a tool's input and output. It needs folding, search and path copy. Use JSON viewer
- For the same snippet in several languages. Use Code snippet tabs
- For one secret or ID on a line with a copy button. Use Copy row
- For a before-and-after of text or fields. Use Diff
- For a template variable people insert into a prompt. Use Variable chip
- For JSON people edit. Use an editor or a structured builder. Use JSON schema builder
- For keyboard shortcuts. Use Kbd
The Machine Mono Rule
The Tabular Figures Rule
$58,902.14 is a figure, not code.Anatomy#
{
"status": "paid",
"amount": 18420.00
}- Surface. Row Mist (
bg-surface) with 10px corners and the hairline lift. - Title. 12px medium Slate Meta in a 36px bar with a hairline bottom. Defaults to Code.
- Copy button. A 24px ghost Copy button named Copy {title}. The icon swaps to a green check for 1.6s after copying.
- Code.
<pre><code>in 12px Geist Mono at a 20px line height, 12px padding, scrolling sideways when a line is long.
Examples#
A request
A method, URL and headers, titled for what they are, above the body in a JSON viewer. The endpoint in the sentence above is InlineCode.
Delivered to https://erp.cedarline.io/hooks in 212 ms.
POST https://erp.cedarline.io/hooks
Content-Type: application/json
Oration-Signature: t=1759086131,v1=5f2c…Arrow keys move between rows and open or close them. C copies a value, P copies its path.
import { CodeBlock, InlineCode } from "@oration/canon/components/code-block";import { JsonViewer } from "@oration/canon/components/json-viewer";export function Request() { const preamble = `POST https://erp.cedarline.io/hooksContent-Type: application/jsonOration-Signature: t=1759086131,v1=5f2c…`; return ( <div className="flex w-full max-w-md flex-col gap-2"> <p className="text-13 text-muted-foreground"> Delivered to{" "} <InlineCode>https://erp.cedarline.io/hooks</InlineCode> in 212 ms. </p> <CodeBlock title="Request" code={preamble} /> <JsonViewer title="Request body" value={{ id: "evt_7Qm2Lx", type: "payment_run.sent", created_at: "2026-09-25T19:02:11Z", data: { run_id: "run_0925_card", invoices: 41, amount: 58902.14, currency: "USD", }, }} /> </div> );}Long lines
Lines never wrap. The code scrolls sideways inside the block, so a URL or token copies exactly as shown.
https://cdn.oration.app/widget.js?key=pk_live_7f3a9c2e41b84d0f9e6a&agent=agt_where_is_my_payment&theme=autoimport { CodeBlock } from "@oration/canon/components/code-block";export function LongLines() { const code = "https://cdn.oration.app/widget.js?key=pk_live_7f3a9c2e41b84d0f9e6a&agent=agt_where_is_my_payment&theme=auto"; return ( <CodeBlock title="Widget URL" code={code} className="w-full max-w-md" /> );}Inline code
InlineCode marks machine strings in a sentence at 0.85em. A placeholder people must replace can take a Caution Amber tint.
Pass the supplier ID as vendor_id and the agent reads it as {{vendor_id}} in the prompt.
Replace YOUR_PUBLIC_KEY with an active live key.
import { InlineCode } from "@oration/canon/components/code-block";export function Inline() { return ( <div className="flex max-w-md flex-col gap-3 text-sm text-foreground"> <p> Pass the supplier ID as <InlineCode>vendor_id</InlineCode> and the agent reads it as <InlineCode>{"{{vendor_id}}"}</InlineCode>{" "} in the prompt. </p> <p className="text-13 text-muted-foreground"> Replace{" "} <InlineCode className="bg-warning/15"> YOUR_PUBLIC_KEY </InlineCode>{" "} with an active live key. </p> </div> );}In a typed confirmation
The string someone must type to confirm sits in InlineCode inside the field's label, and the field itself is mono.
import { Button } from "@oration/canon/components/button";import { InlineCode } from "@oration/canon/components/code-block";import { Input } from "@oration/canon/components/input";import { Label } from "@oration/canon/components/label";import { toast } from "@oration/canon/components/toast";import * as React from "react";export function TypedConfirmation() { const inputId = React.useId(); const [value, setValue] = React.useState(""); const slug = "northwind-freight"; return ( <form className="flex w-full max-w-sm flex-col gap-3" onSubmit={(event) => { event.preventDefault(); toast.add( value === slug ? { type: "success", title: "Supplier archived" } : { type: "error", title: "Type the supplier ID to confirm", description: `It's ${slug}.`, }, ); }} > <Label htmlFor={inputId} className="block leading-6 font-normal"> Type <InlineCode>{slug}</InlineCode> to archive this supplier. </Label> <Input id={inputId} value={value} onChange={(event) => setValue(event.target.value)} autoComplete="off" spellCheck={false} className="font-mono text-xs" /> <div className="flex justify-end"> <Button type="submit" variant="destructive"> Archive supplier </Button> </div> </form> );}States#
| State | Treatment |
|---|---|
| Rest | Title, copy button and code. No syntax colors. |
| Copied | The copy icon becomes a Ledger Green check and the button's name becomes Copied for 1.6s. |
| Overflowing | Long lines scroll horizontally inside the block; the block never wraps or grows past its container. |
| Highlighted placeholder | An InlineCode placeholder people must replace can take bg-warning/15, as the widget install instructions do. |
Behavior#
- The copy button writes the exact
codestring to the clipboard, including line breaks, and swallows clipboard errors silently. - Whitespace is preserved: pass the code already indented. For JSON, pass the value to JSON viewer instead of
JSON.stringifyoutput. - There is no maximum height. Long payloads grow the block; wrap it in a scroll area or a sheet when that matters.
InlineCodesizes itself at 0.85em of the surrounding text, so it scales with the sentence it sits in.
Do and don't#
curl -X POST https://erp.cedarline.io/lookup -d '{"phone":"+13125550100"}'curl -X POST https://erp.cedarline.io/lookup -d '{"phone":"+13125550100"}'Run run_0925_card paid $58,902.14 to 41 suppliers.
InlineCode and keep amounts and counts in Geist Sans with tabular figures.Run run_0925_card paid $58,902.14 to 41 suppliers.
InlineCode. It breaks The Machine Mono Rule and makes figures look like identifiers.Content#
- Titles are short and sentence case: Create a supplier, Request body, Widget URL.
- Use real, runnable examples with Cedarline's data, and environment variables for secrets:
$ORATION_API_KEY, never a live key. - Placeholders people must replace are upper snake case (
YOUR_PUBLIC_KEY) and called out in the sentence around the block. - Keep the sentence outside the block: explain what the code does above it, not in comments inside it.
Accessibility#
- The copy button is named after the title (Copy Create a supplier), so give every block a distinct title when several share a page.
- After copying, the button's name changes to Copied; there is no live announcement, so pair important copies with a toast.
- The
<pre>scrolls horizontally with the pointer or trackpad, but it isn't focusable, so keyboard users can't scroll a clipped line. Keep lines short where you can. InlineCodeis a<code>element and is read as plain text. Don't rely on the mono face alone to mark something people must type; say it in words too.
| Keys | Action |
|---|---|
| Tab | Moves to the copy button. |
| Enter | Copies the code. |
Design tokens#
| Token | Used for |
|---|---|
--surface | Row Mist behind the code |
shadow-border | The block's hairline lift |
--border | Hairline under the title bar |
--muted | InlineCode fill |
--muted-foreground | Title text |
--font-mono | Geist Mono for code |
--radius-lg | 10px block corners |
--radius-sm | 6px InlineCode corners |
API reference#
CodeBlock
A titled, copyable block of code. Takes only the props below.
| Prop | Type | Default | Description |
|---|---|---|---|
codeRequired | string | No default | The exact text to show and copy. |
title | string | "Code" | Shown in the bar and used to name the copy button. |
className | string | No default | Merged onto the outer container, for width and margins. |
InlineCode
A machine string inside running text.
Other props spread onto <code>.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | No default | Merged after the base classes, for example bg-warning/15 on a placeholder. |
Known gaps#
Where the implementation and the system disagree today. Follow the system, not the gap.
CodeBlock draws the hairline lift. Placed inside a card it becomes a raised surface inside a raised surface, which The Tint Well Rule rules out; there is no flat variant.
There's no language prop or syntax highlighting, while Code snippet tabs records a language per snippet. Canon's own docs highlight code; product code blocks don't.
There's no maxHeight or wrapping option, so long audit log payloads grow the sheet they sit in.
title doubles as the copy button's name, so a block without a title copies as Copy code. There's no separate copyLabel.
CodeBlock accepts no other props (no id, no aria-*), so a block can't be referenced by aria-describedby.