CodeSnippet

A component for rendering code.

Props

A CodeSnippet component has the following properties:

PropRequiredDescription
srcyesThe source code to render.
langyesThe language for syntax highlighting.

Examples

TypeScript

// This is the `default` entry point for the package (not including Svelte components).

export * from '$lib/schemas/index.js';
export * from '$lib/utils/index.js';
export * from '$lib/types.js'; // Export types.
<script lang="ts">
	import { CodeSnippet } from '$lib/components/index.js';
	import src from '$lib/index.ts?raw';
</script>

<CodeSnippet {src} lang="typescript" />

Svelte

<script module lang="ts">
	import { createHighlighterCore } from 'shiki/core';
	import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';

	export const highlighter = await createHighlighterCore({
		langs: [
			import('@shikijs/langs/bash'),
			import('@shikijs/langs/html'),
			import('@shikijs/langs/javascript'),
			import('@shikijs/langs/json'),
			import('@shikijs/langs/markdown'),
			import('@shikijs/langs/svelte'),
			import('@shikijs/langs/typescript'),
			import('@shikijs/langs/yaml'),
			import('@shikijs/langs/xml')
		],
		themes: [import('@shikijs/themes/github-light'), import('@shikijs/themes/github-dark')],
		engine: createJavaScriptRegexEngine()
	});
</script>

<script lang="ts">
	import { Check, Copy } from '@lucide/svelte';
	import Button from './Button.svelte';

	interface Props {
		src: string;
		lang: string;
	}

	const { src, lang = 'txt' }: Props = $props();

	let copied = $state(false);
	let timeoutId: ReturnType<typeof setTimeout> | null = null;

	const generatedHtml = $derived(
		highlighter.codeToHtml(src, {
			lang,
			themes: {
				light: 'github-light',
				dark: 'github-dark'
			}
		})
	);

	async function handleCopy() {
		// Clear existing timeout.
		if (timeoutId !== null) {
			clearTimeout(timeoutId);
		}

		await navigator.clipboard.writeText(src);
		copied = true;
		timeoutId = setTimeout(() => {
			copied = false;
			timeoutId = null;
		}, 2000);
	}

	// Cleanup timeout on unmount.
	$effect(() => {
		return () => {
			if (timeoutId !== null) {
				clearTimeout(timeoutId);
			}
		};
	});
</script>

<div
	data-component="CodeSnippet"
	class="relative overflow-hidden rounded-container [&>pre]:overflow-x-auto [&>pre]:p-4 [&>pre]:text-sm"
>
	<!-- eslint-disable-next-line svelte/no-at-html-tags -->
	{@html generatedHtml}
	<Button
		onclick={handleCopy}
		aria-label={copied ? 'Copied!' : 'Copy code'}
		class="absolute right-4 bottom-4"
	>
		{#snippet icon()}
			{#if copied}
				<Check />
			{:else}
				<Copy />
			{/if}
		{/snippet}
	</Button>
</div>

<style>
	:global([data-component='Example'] [data-component='CodeSnippet']) {
		border-start-start-radius: 0;
		border-start-end-radius: 0;
	}
</style>
<script lang="ts">
	import src from '$lib/components/CodeSnippet.svelte?raw';
	import { CodeSnippet } from '$lib/components/index.js';
</script>

<CodeSnippet {src} lang="svelte" />