Code listing
ProCode to read, with line numbers: a file the agent wrote, the lines a finding points at, a config before it changes. The language is named above it, and Copy gives the code exactly, without the line numbers, saying "Copied" only once the clipboard took it. Lines wrap by default, so the whole of each can be read on a phone; Wrap lines turns that off and the listing scrolls sideways instead.
highlights marks ranges of lines with the app's reason, shown under each range. Given a previous version, a Code / Changes switch shows what changed, line by line. The code is split into tokens rendered as text, never as HTML, so nothing in it can run or add markup; tokens are coloured when highlight is set, or anywhere under data-syntax="highlight". For a short snippet with no line numbers, use Payload.
Version 5.2.0· other versions
This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).
Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0 and 2.8.0: the page came later, or had another name then.
Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.
Preview
Loading the preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/code-listing
Brings in: bidi, diff, highlight, locale, tokens, use-copy, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import { CodeListing } from "@/components/candor/code-listing"
const before = `export async function refund(orderId: string) {
const order = await db.orders.find(orderId)
return payments.refund(order.chargeId, order.total)
}
`
const after = `export async function refund(orderId: string) {
const order = await db.orders.find(orderId)
// Only settled orders can be refunded
if (order.status !== "settled") return { ok: false, reason: "not settled" }
return payments.refund(order.chargeId, order.total)
}
`
const excerpt = ` const rows = await db.query(sql, [workspaceId])
for (const row of rows) {
await notify(row.ownerEmail, template.render(row))
}`
export default function Example() {
return (
<div className="flex max-w-2xl flex-col gap-4">
{/* previous adds the Code / Changes switch; highlights mark lines with the app's reason. */}
<CodeListing
highlight
language="ts"
title="src/refund.ts"
code={after}
previous={before}
highlights={[{ from: 3, to: 4, reason: "The guard the agent added" }]}
/>
{/* An excerpt from further down a file: startLine numbers it from there. */}
<CodeListing language="ts" title="jobs/notify.ts" code={excerpt} startLine={118} highlights={[{ from: 120, reason: "One email per row, with no limit" }]} />
</div>
)
}<CodeListing>
| Prop | Type | Default | Description |
|---|---|---|---|
| coderequired | string | — | The code, shown as text and copied exactly. |
| languagerequired | string | — | The language, named above the code and used for its colours: "ts", "python", "sql", "json". Never run. |
| title | string | undefined | — | What it is, e.g. "src/refund.ts" or "The query I ran". |
| startLine | number | undefined | 1 | The number of the first line, for an excerpt from further down a file. Defaults to 1. |
| highlights | CodeHighlight[] | undefined | — | Ranges of lines to mark, each with the reason, shown under the range. Numbers count from `startLine`. |
| previous | string | undefined | — | The version before this one. Given, a Code / Changes switch shows the difference line by line. |
| defaultView | "code" | "changes" | undefined | "code" | Which view opens first when there's a `previous`. Defaults to "code". |
| defaultWrap | boolean | undefined | true | Whether long lines wrap when it opens; the person can switch. Defaults to true. False scrolls sideways instead. |
| highlight | boolean | undefined | — | Colour the code by its syntax. Left out, it follows the nearest `data-syntax` attribute (off by default). |
| className | string | undefined | — | Extra classes for the outer element. |
Functions
codeLanguageLabel(language: string, t: (key: "shell" | "text") => string)"json" → "JSON", "python" → "Python", short unknown ones upper-cased ("hcl" → "HCL"); "bash" and "text" from t.
codeLines(text: string, language: string)The text's tokens split into lines; each line's texts joined give back that line exactly.
codeLineNodes(tokens: Token[])One line from codeLines as spans of text. Each token is a text child, so nothing in the code is parsed as markup.
Strings
The fixed words, in English by default. Change any of them under codeListing in <LocaleProvider strings={{ … }}>; the table is exported as codeListingStrings.
| Key | English |
|---|---|
| copy | Copy |
| copied | Copied |
| copyFailed | Couldn’t copy |
| wrap | Wrap lines |
| view | View |
| code | Code |
| changes | Changes |
| shell | Shell |
| text | Text |
| note | {lines}: {reason} |
| line | Line {line} |
| lines | Lines {from}–{to} |
| added | Added: |
| removed | Removed: |
| linesAdded | { one: "{count} line added", other: "{count} lines added" } |
| linesRemoved | { one: "{count} line removed", other: "{count} lines removed" } |
| noChanges | No changes from the previous version. |
| tooLong | Too long to compare line by line: the whole previous version is shown removed and this one added. |
Motion
| Moment | Family | What it does |
|---|---|---|
| tint | tint | The buttons' background and text colour change when the pointer is over them, and a ring fades in when one takes keyboard focus. |
Set with --cd-motion-code-listing-<moment>-* in your brand file; the families are in the design reference.
Types
- CodeHighlight
- A range of lines the app points at, with why. Line numbers are as shown, so they count from `startLine`.
{ /** The first line of the range. */ from: number; /** The last line; left out, the range is the one line `from`. */ to?: number | undefined; /** Why these lines matter, in the app's words. Shown under the range as text. */ reason: string; }
Types from other items
The props above take these. Each is defined by another item; import it from the path shown.
- Token from @/lib/candor/highlight
{ type: TokenType; text: string }- TokenType from @/lib/candor/highlight
"keyword" | "string" | "number" | "comment" | "function" | "property" | "type" | "tag" | "variable" | "operator" | "plain"