Source code with syntax colors, a title, a copy action, line numbers, diff lines and a collapsible height.
<tp-code-block>
Code block
Default density
Compact density
Restart from the initial state
Show the copyable source
import type { Invoice } from './types';
/** Fetches the unpaid invoices for one workspace. */
export async function unpaidInvoices(id: string): Promise<Invoice[]> {
const url = `/api/workspaces/${id}/invoices?status=open`;
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
import type { Invoice } from './types';
/** Fetches the unpaid invoices for one workspace. */
export async function unpaidInvoices(id: string): Promise<Invoice[]> {
const url = `/api/workspaces/${id}/invoices?status=open`;
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
<tp-code-block language="typescript" label="invoices.ts" style="max-inline-size:40rem;margin-inline:auto">
import type { Invoice } from './types';
/** Fetches the unpaid invoices for one workspace. */
export async function unpaidInvoices(id: string): Promise<Invoice[]> {
const url = `/api/workspaces/${id}/invoices?status=open`;
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
</tp-code-block>
Usage
The source comes from the element’s text content, dedented and trimmed, or from the code property. In markup, escape < and & as < and &, or set code from script. label adds a header with the title and language; the title slot replaces it with your own content. Text content is read when the element connects and whenever it changes.
Custom title
Title slot
Default density
Compact density
Restart from the initial state
Show the copyable source
Deploy to production
Requires approval
npx tweakpad deploy --env production --confirm
Deploy to production
Requires approval
npx tweakpad deploy --env production --confirm
<tp-code-block language="bash" style="max-inline-size:40rem;margin-inline:auto">
<span slot="title" style="display:inline-flex;align-items:center;gap:var(--tp-space-2)">
Deploy to production
<tp-badge variant="warning">Requires approval</tp-badge>
</span>
npx tweakpad deploy --env production --confirm
</tp-code-block>
Content in the title slot replaces the label text in the header, for example to add a Badge. Slotted elements are not part of the source, so the copied code stays exactly the command.
Line numbers and highlights
line-numbers adds a gutter that stays put while long lines scroll. highlight-lines takes lines and ranges such as 2,5-7 to draw attention to the part that matters.
Highlighted lines
Default density
Compact density
Restart from the initial state
Show the copyable source
added-lines and removed-lines mark lines with a gutter marker, a tint and visually hidden text, so the change is clear without relying on color.
Diff
Default density
Compact density
Restart from the initial state
Show the copyable source
export function subtotal(items) {
let sum = 0;
for (const item of items) sum += item.total;
return sum;
return items.reduce((sum, item) => sum + item.total, 0);
}
export function subtotal(items) {
let sum = 0;
for (const item of items) sum += item.total;
return sum;
return items.reduce((sum, item) => sum + item.total, 0);
}
<tp-code-block language="javascript" label="cart.js" line-numbers removed-lines="2-4" added-lines="5" style="max-inline-size:40rem;margin-inline:auto">
export function subtotal(items) {
let sum = 0;
for (const item of items) sum += item.total;
return sum;
return items.reduce((sum, item) => sum + item.total, 0);
}
</tp-code-block>
Collapsible
collapsible clips long files to collapsed-lines (12 by default) and adds an Expand control. Use it for reference files where the first lines tell most of the story.
Collapsible
Default density
Compact density
Restart from the initial state
Show the copyable source
Without label the copy action floats in the top corner. Set copyable="false" to remove it, and wrap to wrap long lines instead of scrolling.
Shell
Default density
Compact density
Restart from the initial state
Show the copyable source
# Install the library and its peer dependency
npm install @tweakpad/ui lit
# Install the library and its peer dependency
npm install @tweakpad/ui lit
<tp-code-block language="bash" style="max-inline-size:40rem;margin-inline:auto">
# Install the library and its peer dependency
npm install @tweakpad/ui lit
</tp-code-block>
Languages and theming
The built-in highlighter covers TypeScript, JavaScript, HTML, CSS, JSON, Bash and diffs; other languages render as plain text. Syntax colors are --tp-syntax-* tokens, so setting them on an ancestor restyles every block inside it.
CSS
Default density
Compact density
Restart from the initial state
Show the copyable source
The wrapper above sets four --tp-syntax-* roles, and both blocks inside pick them up, light and dark alike. language="diff" colors a unified patch as written; use added-lines and removed-lines instead when you want to mark changes in highlighted source.
For full grammar coverage, assign a Shiki-based highlighter from @tweakpad/ui/code to the highlighter property. The block renders plain text first and swaps in colors without shifting layout. The library never
imports Shiki; you create the highlighter with the languages and themes you need:
Languages Shiki has not loaded fall back to the built-in tokenizer. Tokens
with explicit colors (Shiki themes) use their light or dark color for the current scheme. Theme colors are the theme’s own: check their contrast on the code surface (for example, github-light-default comments measure about 4.3:1 on the default surface). The built-in --tp-syntax-* defaults keep every role at 4.5:1 or more on the surface and on highlighted and diff lines in both schemes.
A highlighter implements highlight(code, language, { signal }) and returns
CodeTokens (lines of { text, scope?, light?, dark?, fontStyle? } tokens) or a promise
of them. A newer request aborts signal.
Accessibility
The block is a figure named by its title, or by the language and the code message.
The scroll region becomes focusable (and a labelled region) only when it overflows, so
keyboard users can scroll it. Code stays left-to-right in right-to-left pages. Line
numbers and diff markers are hidden from assistive technology; added and removed lines
carry visually hidden text. The Expand control exposes aria-expanded and controls the
viewport. Reduced motion removes the height transition.
API Reference
Every element also accepts motion-policy.
Attributes
AttributePropertyTypeDefaultDescriptioncodecodestring | undefinedundefinedThe source, in place of the element's text content; set it from script to avoid escaping markup.languagelanguagestring'plaintext'The language the highlighter colors; one it does not know renders as plain text.labellabelstring''A title such as the file name, shown in a header with the language and the copy action.line-numberslineNumbersbooleanfalseAdds a gutter of line numbers that stays put while long lines scroll.highlight-lineshighlightLinesstring''Lines to emphasize, as numbers and ranges such as 2,5-7.added-linesaddedLinesstring''Lines marked as added, as numbers and ranges.removed-linesremovedLinesstring''Lines marked as removed, as numbers and ranges.collapsiblecollapsiblebooleanfalseClips a long block to collapsed-lines and adds an Expand control.default-expandeddefaultExpandedbooleanfalseStarts a collapsible block expanded.collapsed-linescollapsedLinesnumber12How many lines a collapsed block shows.copyablecopyablebooleantrueShows the copy action; copyable="false" removes it.wrapwrapbooleanfalseWraps long lines instead of scrolling them sideways.
Properties
PropertyTypeDefaultDescriptionhighlighterCodeHighlighter | nullbuiltinHighlighterProduces the syntax tokens: the built-in tokenizer, an adapter from @tweakpad/ui/code, or null for plain text.messagesCodeBlockMessages{}Replacements for the built-in text, such as the copy action's name; missing entries keep the defaults.onExpandedChange((event: TpValueChangeEvent<boolean>) => void) | undefined—Called with each accepted or vetoed expanded proposal.expandedboolean—Controlled expansion of a collapsible block; undefined makes it uncontrolled.sourceread-onlystring—The source text the block shows and copies.codeMessagesread-onlyRequired<CodeBlockMessages>—The text in use: messages over the defaults.
Events
EventTypeDescriptiontp-code-copyCustomEvent<CodeCopyDetail>Cancelable, before copying; detail.text.tp-value-changeTpValueChangeEvent<boolean>Cancelable expanded proposal (trigger-press, imperative-action).
Methods
MethodReturnsDescriptionsetExpanded(value, reason, event?)booleanProposes expanding or collapsing; resolves to whether it was accepted.copy(sourceEvent?)Promise<boolean>Copies the source text through the composed Copy button (which announces and confirms);
without a copy action it writes the clipboard directly.
Slots
SlotDescriptiontitleTitle content in the header, in place of label; it is never part of the copied source.
CSS parts
PartDescription::part(code-block)The figure.::part(header)Title row with the language and the copy action.::part(title)The title in the header.::part(language)The language name in the header.::part(copy)The Copy button.::part(viewport)The scrollable pre.::part(line)One source line; data-highlighted, data-inserted or data-deleted.::part(line-number)The line number gutter cell.::part(line-marker)The added or removed marker of a diff line.::part(token)A token span with data-scope.::part(expand)The row with the Expand control of a collapsible block.
Related
Components, widgets and patterns that use this one.