@generative-dom/plugin-code-actions
v0.2.0
Published
Generative DOM plugin — decorate code blocks with a language label and copy button
Downloads
182
Maintainers
Readme
@generative-dom/plugin-code-actions
Decorate every code block Generative DOM renders with a language label and a copy-to-clipboard button — the affordance every LLM chat UI bolts on by hand.
Install
pnpm add @generative-dom/plugin-code-actionsUsage
import { GenerativeDom } from '@generative-dom/core';
import { markdownCode } from '@generative-dom/plugin-markdown-code';
import { codeActions } from '@generative-dom/plugin-code-actions';
const container = document.getElementById('chat')!;
const actions = codeActions(); // defaults: 'Copy' / 'Copied!' / 1.5s
const md = new GenerativeDom({ container, plugins: [markdownCode(), actions] });
actions.attach(container); // begin decorating rendered code blocksThe plugin watches the container with a MutationObserver, so every
<pre><code> the renderer emits (now or later) is wrapped exactly once.
Options
codeActions({
copyLabel: 'Copy', // idle button text
copiedLabel: 'Copied!', // post-click flash
copiedDuration: 1500, // flash duration in ms
hideLanguage: false, // hide the left-side language label
wrapperClass: 'ce-code-actions-wrapper', // outer div class
actionsClass: 'ce-code-actions', // action-bar div class
});Rendered shape
For a fenced block with \``ts`:
<div class="ce-code-actions-wrapper">
<div class="ce-code-actions">
<span class="ce-code-language">ts</span>
<button type="button" class="ce-code-copy">Copy</button>
</div>
<pre><code class="language-ts">...</code></pre>
</div>Minimal CSS
A starter stylesheet — override freely:
.ce-code-actions-wrapper { position: relative; margin: 1em 0; }
.ce-code-actions {
display: flex; justify-content: space-between; align-items: center;
padding: 6px 10px; font: 12px/1 ui-sans-serif, system-ui, sans-serif;
background: #1f2430; color: #9aa0ab; border-radius: 6px 6px 0 0;
}
.ce-code-language { text-transform: uppercase; letter-spacing: 0.08em; }
.ce-code-copy {
background: transparent; color: inherit; border: 1px solid currentColor;
border-radius: 4px; padding: 3px 8px; cursor: pointer; font: inherit;
}
.ce-code-copy:hover { color: #fff; }
.ce-code-actions-wrapper > pre { margin: 0; border-radius: 0 0 6px 6px; }API
codeActions(options?)— returns anGenerativeDomPluginaugmented with:attach(container)— start observing and decorate matched code blocksdetach()— stop observing; existing decorations stay in place
The copy button calls navigator.clipboard.writeText(code.textContent) on
click and temporarily swaps its label to copiedLabel. In environments that
lack the clipboard API (older browsers, jsdom tests) the label still flashes
so the UX stays predictable.
