Codeblock overview
Headless codeblock is a structural primitive. It gives you stable slot directives for the root, header, body, gutter, and code surface while you keep full ownership of copy actions, token markup, and line presentation.
Imports
Use the headless directives when you want to build your own shell around a <pre> and <code> surface.
Primitive imports
ts
import {
TngCodeBlock,
TngCodeBlockHeader,
TngCodeBlockBody,
TngCodeBlockGutter,
TngCodeBlockCode,
} from '@tailng-ui/primitives';
Structural composition
The primitive only marks the major regions. Title text, language badges, copy buttons, token spans, and captions are all authored by the owner.
Minimal headless composition
html
<section tngCodeBlock class="docs-codeblock">
<header tngCodeBlockHeader class="docs-codeblock__header">
<h3 class="docs-codeblock__title">app.config.ts</h3>
</header>
<div tngCodeBlockBody class="docs-codeblock__body">
<ol tngCodeBlockGutter class="docs-codeblock__gutter" aria-hidden="true">
<li>1</li>
<li>2</li>
<li>3</li>
</ol>
<pre class="docs-codeblock__pre"><code tngCodeBlockCode class="docs-codeblock__code">
<span class="docs-codeblock__line">const appConfig = {};</span>
<span class="docs-codeblock__line">export default appConfig;</span>
</code></pre>
</div>
</section>
Style variants
Own the entire shell in plain CSS or utility-authored Tailwind while keeping the primitive slots.
Headless codeblock (plain CSS)
app.config.ts
ts
const config = { mode: 'preview' };export function buildLabel(name: string): string { return `${name}:${config.mode}`;Headless codeblock (Tailwind)
review.ts
ts
const result = await loadProfile();if (result.status !== 'ready') { return 'retry';Accessibility baseline
- Keep the semantic
<pre>and<code>elements in your final markup. - Mark purely decorative line-number gutters with
aria-hidden="true". - Give owner-authored copy buttons explicit labels because the primitive does not add one for you.