Copy Button
Add copy buttons to code blocks in your markdown.
Problem
Users can't easily copy code from your markdown code blocks. They have to manually select the text, which is especially difficult on mobile devices.
Solution
Create a custom pre
component that automatically adds copy buttons to all code blocks.
Implementation
1. Create the Copy Button Component
<script lang="ts">
import type { Snippet } from 'svelte';
let { code, children }: { code: string; children: Snippet } = $props();
let copied = $state(false);
let buttonText = $derived(copied ? 'Copied!' : 'Copy');
async function copyToClipboard() {
try {
await navigator.clipboard.writeText(code);
copied = true;
setTimeout(() => {
copied = false;
}, 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
}
</script>
<div class="group relative">
<button
onclick={copyToClipboard}
class="absolute right-2 top-2 rounded bg-gray-700 px-2 py-1 text-xs text-white opacity-0 transition-opacity hover:bg-gray-600 group-hover:opacity-100"
>
{buttonText}
</button>
{@render children?.()}
</div>
2. Create the Custom Pre Component
<script lang="ts">
import type { Snippet } from 'svelte';
import CopyButton from './copy-button.svelte';
let { children, ...restProps }: { children: Snippet } & Record<string, any> = $props();
let codeContent = $state('');
</script>
<CopyButton {codeContent}>
<pre
class="relative"
{...restProps}
{@attach (node) => {
codeContent = node.textContent;
}}>
{@render children?.()}
</pre>
</CopyButton>
3. Export from Blueprint
<script lang="ts" module>
export { default as pre } from '$lib/blueprints/default/pre.svelte';
</script>
{@render children?.()}
4. Configure MDSX
import { defineConfig } from 'mdsx';
export const mdsxConfig = defineConfig({
extensions: ['.md'],
blueprints: {
default: {
path: 'src/lib/blueprints/default/blueprint.svelte',
},
},
});
Usage
Now all your code blocks will automatically have copy buttons:
# My Documentation
Here's some JavaScript code:
```js
function greet(name) {
return `Hello, ${name}!`;
}
```
And some CSS:
```css
.button {
background: blue;
color: white;
padding: 10px;
}
```