Data display
Code Block
Source code in a native frame, with an optional title, Copy button and tabs.
| Class name | Type | Description |
|---|---|---|
code-blockplf:code-block | Component | The frame |
code-block-headerplf:code-block-header | Part | Optional header for the title or tabs and Copy |
code-block-titleplf:code-block-title | Part | The source's name in the header |
code-block-copyplf:code-block-copy | Part | The Copy button |
code-block-copy-iconplf:code-block-copy-icon | Part | Your own SVG, in place of the drawn copy icon; an icon class there doesn't need it |
code-block-preplf:code-block-pre | Part | The scrolling pre |
code-block-codeplf:code-block-code | Part | The code inside it |
code-block-tabsplf:code-block-tabs | Part | Tab list for several sources |
code-block-tabplf:code-block-tab | Part | A source's tab |
code-block-panelplf:code-block-panel | Part | A source's panel |
code-block-tokenplf:code-block-token | Part | A highlighted token |
Default
Escape markup in the source, such as < for <.
<div data-plf-root>
<button class="btn">Save changes</button>
</div>
/* Component token overrides */
[data-plf-root] {
--plf-color-primary: #2563eb;
--plf-code-block-padding: 16px;
}
<div class="code-block" data-plf-code-block>
<div class="code-block-header">
<span class="code-block-title">HTML</span>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="code-block-pre" tabindex="0" role="region" aria-label="HTML code"><code class="code-block-code language-html"><div data-plf-root>
<button class="btn">Save changes</button>
</div></code></pre>
</div>
<div class="code-block" data-plf-code-block>
<div class="code-block-header">
<span class="code-block-title">styles.css</span>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="code-block-pre" tabindex="0" role="region" aria-label="CSS code"><code class="code-block-code language-css">/* Component token overrides */
[data-plf-root] {
--plf-color-primary: #2563eb;
--plf-code-block-padding: 16px;
}</code></pre>
</div><div class="plf:code-block" data-plf-code-block>
<div class="plf:code-block-header">
<span class="plf:code-block-title">HTML</span>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="plf:code-block-pre" tabindex="0" role="region" aria-label="HTML code"><code class="plf:code-block-code language-html"><div data-plf-root>
<button class="btn">Save changes</button>
</div></code></pre>
</div>
<div class="plf:code-block" data-plf-code-block>
<div class="plf:code-block-header">
<span class="plf:code-block-title">styles.css</span>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="plf:code-block-pre" tabindex="0" role="region" aria-label="CSS code"><code class="plf:code-block-code language-css">/* Component token overrides */
[data-plf-root] {
--plf-color-primary: #2563eb;
--plf-code-block-padding: 16px;
}</code></pre>
</div>import { CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react';
const html = `<div data-plf-root>
<button class="btn">Save changes</button>
</div>`;
const css = `/* Component token overrides */
[data-plf-root] {
--plf-color-primary: #2563eb;
--plf-code-block-padding: 16px;
}`;
export function Example() {
return (
<>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>HTML</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="HTML code">
<CodeBlockCode className="language-html">{html}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>styles.css</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="CSS code">
<CodeBlockCode className="language-css">{css}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
</>
);
}import { CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react/prefixed';
const html = `<div data-plf-root>
<button class="btn">Save changes</button>
</div>`;
const css = `/* Component token overrides */
[data-plf-root] {
--plf-color-primary: #2563eb;
--plf-code-block-padding: 16px;
}`;
export function Example() {
return (
<>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>HTML</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="HTML code">
<CodeBlockCode className="language-html">{html}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>styles.css</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="CSS code">
<CodeBlockCode className="language-css">{css}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
</>
);
}Name each pre with aria-label or aria-labelledby, and add tabindex="0" and role="region" so keyboard users can scroll it.
Project files
index.html
styles.css
app.js
<div class="code-block" data-plf-code-block>
<pre class="code-block-pre" tabindex="0" role="region" aria-label="Plain text"><code class="code-block-code">Project files
index.html
styles.css
app.js</code></pre>
</div><div class="plf:code-block" data-plf-code-block>
<pre class="plf:code-block-pre" tabindex="0" role="region" aria-label="Plain text"><code class="plf:code-block-code">Project files
index.html
styles.css
app.js</code></pre>
</div>import { CodeBlock, CodeBlockCode, CodeBlockPre } from '@pelatform/react';
const files = `Project files
index.html
styles.css
app.js`;
export function Example() {
return (
<CodeBlock>
<CodeBlockPre aria-label="Plain text">
<CodeBlockCode>{files}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
);
}import { CodeBlock, CodeBlockCode, CodeBlockPre } from '@pelatform/react/prefixed';
const files = `Project files
index.html
styles.css
app.js`;
export function Example() {
return (
<CodeBlock>
<CodeBlockPre aria-label="Plain text">
<CodeBlockCode>{files}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
);
}// Long lines stay inside the frame.
const message = "Long lines scroll inside the code block while the surrounding page keeps its width, and indentation stays exactly as written in this example.";
console.log(message);
<div class="code-block" data-plf-code-block>
<div class="code-block-header">
<span class="code-block-title">JavaScript</span>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="code-block-pre" tabindex="0" role="region" aria-label="JavaScript code"><code class="code-block-code language-javascript">// Long lines stay inside the frame.
const message = "Long lines scroll inside the code block while the surrounding page keeps its width, and indentation stays exactly as written in this example.";
console.log(message);</code></pre>
</div><div class="plf:code-block" data-plf-code-block>
<div class="plf:code-block-header">
<span class="plf:code-block-title">JavaScript</span>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="plf:code-block-pre" tabindex="0" role="region" aria-label="JavaScript code"><code class="plf:code-block-code language-javascript">// Long lines stay inside the frame.
const message = "Long lines scroll inside the code block while the surrounding page keeps its width, and indentation stays exactly as written in this example.";
console.log(message);</code></pre>
</div>import { CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react';
const javascript = `// Long lines stay inside the frame.
const message = "Long lines scroll inside the code block while the surrounding page keeps its width, and indentation stays exactly as written in this example.";
console.log(message);`;
export function Example() {
return (
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>JavaScript</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="JavaScript code">
<CodeBlockCode className="language-javascript">{javascript}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
);
}import { CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react/prefixed';
const javascript = `// Long lines stay inside the frame.
const message = "Long lines scroll inside the code block while the surrounding page keeps its width, and indentation stays exactly as written in this example.";
console.log(message);`;
export function Example() {
return (
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>JavaScript</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="JavaScript code">
<CodeBlockCode className="language-javascript">{javascript}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
);
}<form class="card" method="post">
<div class="card-header">
<h2 class="card-title">Notification settings</h2>
<p class="card-description">Choose what reaches your inbox.</p>
</div>
<div class="card-body flex flex-col gap-4">
<div class="field">
<label class="field-label" for="digest">Daily digest</label>
<select class="select" id="digest" name="digest">
<option>Every morning</option>
<option>Every evening</option>
<option>Never</option>
</select>
</div>
<div class="field">
<label class="field-label" for="email">Email address</label>
<input class="input" id="email" name="email" type="email">
</div>
<label class="choice">
<input class="checkbox" type="checkbox" name="mentions" checked>
<span class="choice-label">Mentions and replies</span>
</label>
<label class="choice">
<input class="checkbox" type="checkbox" name="updates">
<span class="choice-label">Product updates</span>
</label>
</div>
<div class="card-actions">
<button class="btn btn-primary" type="submit">Save settings</button>
<button class="btn btn-outline" type="reset">Reset</button>
</div>
</form>
<div class="code-block" data-plf-code-block style="--plf-code-block-max-height: 12rem">
<div class="code-block-header">
<span class="code-block-title">HTML</span>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="code-block-pre" tabindex="0" role="region" aria-label="Long HTML example"><code class="code-block-code language-html"><form class="card" method="post">
<div class="card-header">
<h2 class="card-title">Notification settings</h2>
<p class="card-description">Choose what reaches your inbox.</p>
</div>
<div class="card-body flex flex-col gap-4">
<div class="field">
<label class="field-label" for="digest">Daily digest</label>
<select class="select" id="digest" name="digest">
<option>Every morning</option>
<option>Every evening</option>
<option>Never</option>
</select>
</div>
<div class="field">
<label class="field-label" for="email">Email address</label>
<input class="input" id="email" name="email" type="email">
</div>
<label class="choice">
<input class="checkbox" type="checkbox" name="mentions" checked>
<span class="choice-label">Mentions and replies</span>
</label>
<label class="choice">
<input class="checkbox" type="checkbox" name="updates">
<span class="choice-label">Product updates</span>
</label>
</div>
<div class="card-actions">
<button class="btn btn-primary" type="submit">Save settings</button>
<button class="btn btn-outline" type="reset">Reset</button>
</div>
</form></code></pre>
</div><div class="plf:code-block" data-plf-code-block style="--plf-code-block-max-height: 12rem">
<div class="plf:code-block-header">
<span class="plf:code-block-title">HTML</span>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="plf:code-block-pre" tabindex="0" role="region" aria-label="Long HTML example"><code class="plf:code-block-code language-html"><form class="card" method="post">
<div class="card-header">
<h2 class="card-title">Notification settings</h2>
<p class="card-description">Choose what reaches your inbox.</p>
</div>
<div class="card-body flex flex-col gap-4">
<div class="field">
<label class="field-label" for="digest">Daily digest</label>
<select class="select" id="digest" name="digest">
<option>Every morning</option>
<option>Every evening</option>
<option>Never</option>
</select>
</div>
<div class="field">
<label class="field-label" for="email">Email address</label>
<input class="input" id="email" name="email" type="email">
</div>
<label class="choice">
<input class="checkbox" type="checkbox" name="mentions" checked>
<span class="choice-label">Mentions and replies</span>
</label>
<label class="choice">
<input class="checkbox" type="checkbox" name="updates">
<span class="choice-label">Product updates</span>
</label>
</div>
<div class="card-actions">
<button class="btn btn-primary" type="submit">Save settings</button>
<button class="btn btn-outline" type="reset">Reset</button>
</div>
</form></code></pre>
</div>import type { CSSProperties } from 'react';
import { CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react';
const html = `<form class="card" method="post">
<div class="card-header">
<h2 class="card-title">Notification settings</h2>
<p class="card-description">Choose what reaches your inbox.</p>
</div>
<div class="card-body flex flex-col gap-4">
<div class="field">
<label class="field-label" for="digest">Daily digest</label>
<select class="select" id="digest" name="digest">
<option>Every morning</option>
<option>Every evening</option>
<option>Never</option>
</select>
</div>
<div class="field">
<label class="field-label" for="email">Email address</label>
<input class="input" id="email" name="email" type="email">
</div>
<label class="choice">
<input class="checkbox" type="checkbox" name="mentions" checked>
<span class="choice-label">Mentions and replies</span>
</label>
<label class="choice">
<input class="checkbox" type="checkbox" name="updates">
<span class="choice-label">Product updates</span>
</label>
</div>
<div class="card-actions">
<button class="btn btn-primary" type="submit">Save settings</button>
<button class="btn btn-outline" type="reset">Reset</button>
</div>
</form>`;
export function Example() {
return (
<CodeBlock style={{ '--plf-code-block-max-height': '12rem' } as CSSProperties}>
<CodeBlockHeader>
<CodeBlockTitle>HTML</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="Long HTML example">
<CodeBlockCode className="language-html">{html}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
);
}import type { CSSProperties } from 'react';
import { CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react/prefixed';
const html = `<form class="card" method="post">
<div class="card-header">
<h2 class="card-title">Notification settings</h2>
<p class="card-description">Choose what reaches your inbox.</p>
</div>
<div class="card-body flex flex-col gap-4">
<div class="field">
<label class="field-label" for="digest">Daily digest</label>
<select class="select" id="digest" name="digest">
<option>Every morning</option>
<option>Every evening</option>
<option>Never</option>
</select>
</div>
<div class="field">
<label class="field-label" for="email">Email address</label>
<input class="input" id="email" name="email" type="email">
</div>
<label class="choice">
<input class="checkbox" type="checkbox" name="mentions" checked>
<span class="choice-label">Mentions and replies</span>
</label>
<label class="choice">
<input class="checkbox" type="checkbox" name="updates">
<span class="choice-label">Product updates</span>
</label>
</div>
<div class="card-actions">
<button class="btn btn-primary" type="submit">Save settings</button>
<button class="btn btn-outline" type="reset">Reset</button>
</div>
</form>`;
export function Example() {
return (
<CodeBlock style={{ '--plf-code-block-max-height': '12rem' } as CSSProperties}>
<CodeBlockHeader>
<CodeBlockTitle>HTML</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="Long HTML example">
<CodeBlockCode className="language-html">{html}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
);
}Tabs
Copy takes the visible panel.
bun add @pelatform/ui
npm install @pelatform/ui
pnpm add @pelatform/ui
<div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div>
<div data-plf-root>
<button class="plf:btn plf:btn-outline">Cancel</button>
</div>
<div class="code-block" data-plf-code-block data-plf-tabs>
<div class="code-block-header">
<div class="code-block-tabs" role="tablist" aria-label="Install command">
<button class="code-block-tab" role="tab" aria-selected="true">bun</button>
<button class="code-block-tab" role="tab">npm</button>
<button class="code-block-tab" role="tab">pnpm</button>
</div>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="bun install command"><code class="code-block-code">bun add @pelatform/ui</code></pre>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="npm install command"><code class="code-block-code">npm install @pelatform/ui</code></pre>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="pnpm install command"><code class="code-block-code">pnpm add @pelatform/ui</code></pre>
</div>
</div>
<div class="code-block" data-plf-code-block data-plf-tabs>
<div class="code-block-header">
<div class="code-block-tabs" role="tablist" aria-label="HTML code">
<button class="code-block-tab" role="tab" aria-selected="true">Clean</button>
<button class="code-block-tab" role="tab">Prefixed</button>
</div>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="Clean HTML code"><code class="code-block-code language-html"><div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div></code></pre>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="Prefixed HTML code"><code class="code-block-code language-html"><div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div></code></pre>
</div>
</div><div class="plf:code-block" data-plf-code-block data-plf-tabs>
<div class="plf:code-block-header">
<div class="plf:code-block-tabs" role="tablist" aria-label="Install command">
<button class="plf:code-block-tab" role="tab" aria-selected="true">bun</button>
<button class="plf:code-block-tab" role="tab">npm</button>
<button class="plf:code-block-tab" role="tab">pnpm</button>
</div>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="bun install command"><code class="plf:code-block-code">bun add @pelatform/ui</code></pre>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="npm install command"><code class="plf:code-block-code">npm install @pelatform/ui</code></pre>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="pnpm install command"><code class="plf:code-block-code">pnpm add @pelatform/ui</code></pre>
</div>
</div>
<div class="plf:code-block" data-plf-code-block data-plf-tabs>
<div class="plf:code-block-header">
<div class="plf:code-block-tabs" role="tablist" aria-label="HTML code">
<button class="plf:code-block-tab" role="tab" aria-selected="true">Clean</button>
<button class="plf:code-block-tab" role="tab">Prefixed</button>
</div>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="Clean HTML code"><code class="plf:code-block-code language-html"><div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div></code></pre>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="Prefixed HTML code"><code class="plf:code-block-code language-html"><div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div></code></pre>
</div>
</div>import {
CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPanel, CodeBlockPre, CodeBlockTab, CodeBlockTabs,
} from '@pelatform/react';
const clean = `<div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div>`;
const prefixed = `<div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div>`;
export function Example() {
return (
<>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTabs aria-label="Install command">
<CodeBlockTab value="bun">bun</CodeBlockTab>
<CodeBlockTab value="npm">npm</CodeBlockTab>
<CodeBlockTab value="pnpm">pnpm</CodeBlockTab>
</CodeBlockTabs>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPanel value="bun">
<CodeBlockPre aria-label="bun install command">
<CodeBlockCode>bun add @pelatform/ui</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="npm">
<CodeBlockPre aria-label="npm install command">
<CodeBlockCode>npm install @pelatform/ui</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="pnpm">
<CodeBlockPre aria-label="pnpm install command">
<CodeBlockCode>pnpm add @pelatform/ui</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
</CodeBlock>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTabs aria-label="HTML code">
<CodeBlockTab value="clean">Clean</CodeBlockTab>
<CodeBlockTab value="prefixed">Prefixed</CodeBlockTab>
</CodeBlockTabs>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPanel value="clean">
<CodeBlockPre aria-label="Clean HTML code">
<CodeBlockCode className="language-html">{clean}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="prefixed">
<CodeBlockPre aria-label="Prefixed HTML code">
<CodeBlockCode className="language-html">{prefixed}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
</CodeBlock>
</>
);
}import {
CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPanel, CodeBlockPre, CodeBlockTab, CodeBlockTabs,
} from '@pelatform/react/prefixed';
const clean = `<div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div>`;
const prefixed = `<div data-plf-root>
<button class="btn btn-outline">Cancel</button>
</div>`;
export function Example() {
return (
<>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTabs aria-label="Install command">
<CodeBlockTab value="bun">bun</CodeBlockTab>
<CodeBlockTab value="npm">npm</CodeBlockTab>
<CodeBlockTab value="pnpm">pnpm</CodeBlockTab>
</CodeBlockTabs>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPanel value="bun">
<CodeBlockPre aria-label="bun install command">
<CodeBlockCode>bun add @pelatform/ui</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="npm">
<CodeBlockPre aria-label="npm install command">
<CodeBlockCode>npm install @pelatform/ui</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="pnpm">
<CodeBlockPre aria-label="pnpm install command">
<CodeBlockCode>pnpm add @pelatform/ui</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
</CodeBlock>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTabs aria-label="HTML code">
<CodeBlockTab value="clean">Clean</CodeBlockTab>
<CodeBlockTab value="prefixed">Prefixed</CodeBlockTab>
</CodeBlockTabs>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPanel value="clean">
<CodeBlockPre aria-label="Clean HTML code">
<CodeBlockCode className="language-html">{clean}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="prefixed">
<CodeBlockPre aria-label="Prefixed HTML code">
<CodeBlockCode className="language-html">{prefixed}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
</CodeBlock>
</>
);
}<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>
<button class="plf:btn plf:btn-primary">Save</button>
<button class="plf:btn plf:btn-outline">Cancel</button>
<div class="card">
<div class="card-body">
<div class="flex flex-wrap items-center gap-4">
<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>
</div>
</div>
<div class="code-block" data-plf-code-block data-plf-tabs>
<div class="code-block-header">
<div class="code-block-tabs" role="tablist" aria-label="Preview code">
<button class="code-block-tab" role="tab" aria-selected="true">Clean</button>
<button class="code-block-tab" role="tab">Prefixed</button>
</div>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="Clean preview code"><code class="code-block-code language-html"><button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button></code></pre>
</div>
<div class="code-block-panel" role="tabpanel">
<pre class="code-block-pre" tabindex="0" aria-label="Prefixed preview code"><code class="code-block-code language-html"><button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button></code></pre>
</div>
</div>
</div><div class="plf:card">
<div class="plf:card-body">
<div class="plf:flex plf:flex-wrap plf:items-center plf:gap-4">
<button class="plf:btn plf:btn-primary">Save</button>
<button class="plf:btn plf:btn-outline">Cancel</button>
</div>
</div>
<div class="plf:code-block" data-plf-code-block data-plf-tabs>
<div class="plf:code-block-header">
<div class="plf:code-block-tabs" role="tablist" aria-label="Preview code">
<button class="plf:code-block-tab" role="tab" aria-selected="true">Clean</button>
<button class="plf:code-block-tab" role="tab">Prefixed</button>
</div>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="Clean preview code"><code class="plf:code-block-code language-html"><button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button></code></pre>
</div>
<div class="plf:code-block-panel" role="tabpanel">
<pre class="plf:code-block-pre" tabindex="0" aria-label="Prefixed preview code"><code class="plf:code-block-code language-html"><button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button></code></pre>
</div>
</div>
</div>import {
Button, Card, CardBody, CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPanel, CodeBlockPre, CodeBlockTab,
CodeBlockTabs,
} from '@pelatform/react';
const clean = `<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>`;
const prefixed = `<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>`;
export function Example() {
return (
<Card>
<CardBody>
<div className="flex flex-wrap items-center gap-4">
<Button color="primary">Save</Button>
<Button variant="outline">Cancel</Button>
</div>
</CardBody>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTabs aria-label="Preview code">
<CodeBlockTab value="clean">Clean</CodeBlockTab>
<CodeBlockTab value="prefixed">Prefixed</CodeBlockTab>
</CodeBlockTabs>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPanel value="clean">
<CodeBlockPre aria-label="Clean preview code">
<CodeBlockCode className="language-html">{clean}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="prefixed">
<CodeBlockPre aria-label="Prefixed preview code">
<CodeBlockCode className="language-html">{prefixed}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
</CodeBlock>
</Card>
);
}import {
Button, Card, CardBody, CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPanel, CodeBlockPre, CodeBlockTab,
CodeBlockTabs,
} from '@pelatform/react/prefixed';
const clean = `<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>`;
const prefixed = `<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>`;
export function Example() {
return (
<Card>
<CardBody>
<div className="plf:flex plf:flex-wrap plf:items-center plf:gap-4">
<Button color="primary">Save</Button>
<Button variant="outline">Cancel</Button>
</div>
</CardBody>
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTabs aria-label="Preview code">
<CodeBlockTab value="clean">Clean</CodeBlockTab>
<CodeBlockTab value="prefixed">Prefixed</CodeBlockTab>
</CodeBlockTabs>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPanel value="clean">
<CodeBlockPre aria-label="Clean preview code">
<CodeBlockCode className="language-html">{clean}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
<CodeBlockPanel value="prefixed">
<CodeBlockPre aria-label="Prefixed preview code">
<CodeBlockCode className="language-html">{prefixed}</CodeBlockCode>
</CodeBlockPre>
</CodeBlockPanel>
</CodeBlock>
</Card>
);
}Inside written content
Inside prose, wrap the block in not-prose.
Inside written content
Use a prose exclusion around the component to keep its own spacing and controls.
<p>Written content can include a code example.</p>
The article continues with the same compact paragraph rhythm.
<div class="card">
<div class="card-body prose">
<h3>Inside written content</h3>
<p>Use a prose exclusion around the component to keep its own spacing and controls.</p>
<div class="not-prose">
<div class="code-block" data-plf-code-block>
<div class="code-block-header">
<span class="code-block-title">HTML</span>
<button class="code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="code-block-pre" tabindex="0" role="region" aria-label="Embedded HTML code"><code class="code-block-code language-html"><p>Written content can include a code example.</p></code></pre>
</div>
</div>
<p>The article continues with the same compact paragraph rhythm.</p>
</div>
</div><div class="plf:card">
<div class="plf:card-body plf:prose">
<h3>Inside written content</h3>
<p>Use a prose exclusion around the component to keep its own spacing and controls.</p>
<div class="plf:not-prose">
<div class="plf:code-block" data-plf-code-block>
<div class="plf:code-block-header">
<span class="plf:code-block-title">HTML</span>
<button class="plf:code-block-copy" data-plf-code-block-copy hidden>
Copy
</button>
</div>
<pre class="plf:code-block-pre" tabindex="0" role="region" aria-label="Embedded HTML code"><code class="plf:code-block-code language-html"><p>Written content can include a code example.</p></code></pre>
</div>
</div>
<p>The article continues with the same compact paragraph rhythm.</p>
</div>
</div>import { Card, CardBody, CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react';
export function Example() {
return (
<Card>
<CardBody className="prose">
<h3>Inside written content</h3>
<p>Use a prose exclusion around the component to keep its own spacing and controls.</p>
<div className="not-prose">
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>HTML</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="Embedded HTML code">
<CodeBlockCode className="language-html">{'<p>Written content can include a code example.</p>'}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
</div>
<p>The article continues with the same compact paragraph rhythm.</p>
</CardBody>
</Card>
);
}import { Card, CardBody, CodeBlock, CodeBlockCode, CodeBlockCopy, CodeBlockHeader, CodeBlockPre, CodeBlockTitle } from '@pelatform/react/prefixed';
export function Example() {
return (
<Card>
<CardBody className="plf:prose">
<h3>Inside written content</h3>
<p>Use a prose exclusion around the component to keep its own spacing and controls.</p>
<div className="plf:not-prose">
<CodeBlock>
<CodeBlockHeader>
<CodeBlockTitle>HTML</CodeBlockTitle>
<CodeBlockCopy />
</CodeBlockHeader>
<CodeBlockPre aria-label="Embedded HTML code">
<CodeBlockCode className="language-html">{'<p>Written content can include a code example.</p>'}</CodeBlockCode>
</CodeBlockPre>
</CodeBlock>
</div>
<p>The article continues with the same compact paragraph rhythm.</p>
</CardBody>
</Card>
);
}Syntax highlighting
Name the language with HTML’s language-* class on the code, such as language-css, where highlighters such as Shiki, Prism and highlight.js read it. Highlight code when you build the page: wrap each token in a code-block-token span with --plf-code-block-token-light and --plf-code-block-token-dark colors. Copy takes the text, not the spans.
| Class | Language |
|---|---|
language-html |
HTML |
language-css |
CSS |
language-javascript, language-js |
JavaScript |
language-typescript, language-ts |
TypeScript |
language-shell, language-sh, language-bash |
Shell |
language-astro |
Astro |
language-php |
PHP |
Any other language your highlighter knows takes its language-* name the same way; without a highlighter, code stays plain and Copy still works.
JavaScript
Copy needs JavaScript; the code stays readable without it. The Full script (pelatform-ui.min.js) starts every component on page load, with no code of your own; with ESM imports, call init() yourself, as in Installation. For markup you add later, see Dynamic content.
<link rel="stylesheet" href="pelatform-ui.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.min.css">
<link rel="stylesheet" href="components/button.min.css">
<link rel="stylesheet" href="components/card.min.css">
<link rel="stylesheet" href="components/tabs.min.css">
<link rel="stylesheet" href="components/code-block.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/tabs.min.js" defer></script>
<script src="components/code-block.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script><link rel="stylesheet" href="pelatform-ui.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.prefixed.min.css">
<link rel="stylesheet" href="components/button.prefixed.min.css">
<link rel="stylesheet" href="components/card.prefixed.min.css">
<link rel="stylesheet" href="components/tabs.prefixed.min.css">
<link rel="stylesheet" href="components/code-block.prefixed.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/tabs.min.js" defer></script>
<script src="components/code-block.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script>| Attribute | Purpose |
|---|---|
data-plf-code-block |
Marks the frame |
data-plf-code-block-copy |
Optional <button> outside the pre, authored hidden; the script shows it |
data-plf-code-block-copy-label |
Optional: the plain-text label inside the button, otherwise the button’s own text. The script adds a polite live region that announces the result |
data-plf-copied-label |
On the button: the success text, Copied by default |
data-plf-copy-error |
On the frame: the failure message; Copy failed. by default |
Copy uses the browser’s clipboard API, which needs a secure (HTTPS) page.
| Method | Behavior |
|---|---|
PLF. |
Returns the instance, creating it for valid markup |
PLF. |
Returns the instance or null |
instance. |
Copies the visible source; resolves to true on success, otherwise false |
instance. |
Removes the listener, restores the label and hides Copy again |
| Event | When |
|---|---|
plf: |
After the source is copied |
plf: |
After a copy fails |
Each event’s detail:
| Property | Value |
|---|---|
instance |
The Code Block instance |
reason |
trigger or api |
trigger |
The Copy button, or null from a method |
| Key | Action |
|---|---|
| Enter, Space | On Copy, copies the source; on a tab, shows its source |
| Left and Right arrows, Home, End | Move between tabs |
| Arrow keys, Page Up, Page Down | Scroll the focused code |
React
CodeBlock from @pelatform/react renders this frame around your code, already highlighted if you highlight it when you build the page, with Copy’s clipboard write and status and the tabs’ keyboard; it keeps the selected tab, or the application sets it with value.
| Prop | Values | Default |
|---|---|---|
value |
The selected tab’s value, which the application changes in onValueChange |
Its own state |
defaultValue |
The value of the tab selected at first, when the application does not set value |
The first enabled tab |
onValueChange |
(value), called when a click, Enter or Space selects another tab |
None |
| Part | Element |
|---|---|
CodeBlockHeader |
A div with code-block-header |
CodeBlockTitle |
A span with code-block-title |
CodeBlockCopy |
A button with code-block-copy and type="button", labeled Copy unless given other children; after a copy, copiedLabel (Copied) takes the label’s place for two seconds, and a failure announces copyError (Copy failed.) |
CodeBlockTabs |
A div with code-block-tabs, the tab list, named by its aria-label |
CodeBlockTab |
A button with code-block-tab and type="button", whose value, unique in its Code Block, pairs it with its panel |
CodeBlockPanel |
A div with code-block-panel, the panel of the CodeBlockTab with the same value |
CodeBlockPre |
A pre with code-block-pre and tabindex="0", and role="region" outside a panel; name it with aria-label |
CodeBlockCode |
A code with code-block-code, whose className takes the language-* class |
CodeBlockToken |
A span with code-block-token, a highlighted token whose light and dark set its colors |
The other props are the element’s own, className and ref included. Write CodeBlockCopy and the tabs inside the CodeBlock itself, not in a component of your own: it reads them while rendering, for its status and its first tab.
| Variable | Default |
|---|---|
--plf-code-block-bg, --plf-code-block-color |
Raised surface and text |
--plf-code-block-border |
Subtle border |
--plf-code-block-radius |
Extra large radius (12px) |
--plf-code-block-padding |
Space 4 (16px) |
--plf-code-block-font-size, --plf-code-block-line-height |
14px, 1.5 |
--plf-code-block-max-height |
none |
--plf-code-block-header-bg, --plf-code-block-header-color |
Surface and muted text |
--plf-code-block-token-light, --plf-code-block-token-dark |
Set on each token: its color on light and dark roots |
--plf-code-block-token-color |
Unset; one color for every token in both themes |