Data display

Code Block

Source code in a native frame, with an optional title, Copy button and tabs.

Class nameTypeDescription
code-blockplf:code-blockComponentThe frame
code-block-headerplf:code-block-headerPartOptional header for the title or tabs and Copy
code-block-titleplf:code-block-titlePartThe source's name in the header
code-block-copyplf:code-block-copyPartThe Copy button
code-block-copy-iconplf:code-block-copy-iconPartYour own SVG, in place of the drawn copy icon; an icon class there doesn't need it
code-block-preplf:code-block-prePartThe scrolling pre
code-block-codeplf:code-block-codePartThe code inside it
code-block-tabsplf:code-block-tabsPartTab list for several sources
code-block-tabplf:code-block-tabPartA source's tab
code-block-panelplf:code-block-panelPartA source's panel
code-block-tokenplf:code-block-tokenPartA highlighted token

Default

Escape markup in the source, such as &lt; for <.

HTML
<div data-plf-root>
  <button class="btn">Save changes</button>
</div>
styles.css
/* Component token overrides */
[data-plf-root] {
  --plf-color-primary: #2563eb;
  --plf-code-block-padding: 16px;
}

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
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);
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>

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>
<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>

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.

HTML
<p>Written content can include a code example.</p>

The article continues with the same compact paragraph rhythm.

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="pelatform-ui.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></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. Select and copy the code. by default

Copy uses the browser’s clipboard API, which needs a secure (HTTPS) page.

Method Behavior
PLF.CodeBlock.getOrCreateInstance(block) Returns the instance, creating it for valid markup
PLF.CodeBlock.getInstance(block) Returns the instance or null
instance.copy() Copies the visible source; resolves to true on success, otherwise false
instance.destroy() Removes the listener, restores the label and hides Copy again
Event When
plf:code-block:copy After the source is copied
plf:code-block:copy-error 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. Select and copy the code.)
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

Built with Pelatform UIv0.1.0

Components

Getting started

Foundations

Components

Actions

Data display

Navigation

Feedback

Data input

Layout

Advanced

Integrations

Blocks

Application

Authentication

Icons