Kumo Svelte
  • Home
  • Installation
  • Colors
  • Accessibility
  • Changelog
  • Autocomplete
  • Badge
  • Banner
  • Breadcrumbs
  • Button
  • Checkbox
  • Clipboard Text
  • Cloudflare Logo
  • CodeHighlighted
  • Collapsible
  • Combobox
  • Command Palette
  • Date Picker
  • Dialog
  • Dropdown
  • Empty
  • Flow
  • Grid
  • Input
  • InputArea
  • InputGroup
  • Label
  • Layer Card
  • Link
  • Loader
  • MenuBar
  • Meter
  • Pagination
  • Popover
  • Radio
  • Select
  • Sensitive Input
  • Sidebar
  • Skeleton Line
  • Switch
  • Table
  • Table of Contents
  • Tabs
  • Text
  • Toast
  • Toolbar
  • Tooltip
  • Charts
  • Colors
  • Timeseries
  • Maps
  • Sankey
  • Custom Chart
  • Page Header
  • Resource List
  • Delete Resource
CodeHighlighted
kumo-svelte

CodeHighlighted

Shiki-powered syntax highlighting with Kumo themes, lazy loading, line highlighting, line numbers, and copy buttons.

const greeting = "Hello, World!";
console.log(greeting);
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `const greeting = "Hello, World!";
console.log(greeting);`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="typescript" />
</ShikiDemoProvider>

Overview

A Shiki-powered syntax highlighter. It supports a curated set of bundled languages with TextMate grammars, Kumo light/dark themes, lazy loading, line highlighting, line numbers, and copy buttons.

Import CodeHighlighted and ShikiProvider from kumo-svelte/components/code.

Import

Import the highlighting components from the code component subpath.

import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";

Basic Usage

Wrap the relevant part of your app with ShikiProvider to configure Shiki once. All CodeHighlighted components inside share the same Shiki instance.

<script lang="ts">
  import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";
</script>

<ShikiProvider engine="javascript" languages={["typescript", "bash", "json"]}>
  <CodeHighlighted code="const x = 1;" lang="typescript" />
</ShikiProvider>

Examples

Languages

CodeHighlighted supports the languages listed in the API reference. Only load the languages you need in ShikiProvider.

TypeScript

interface User {
  id: string;
  name: string;
  email: string;
}

async function fetchUser(id: string): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `interface User {
  id: string;
  name: string;
  email: string;
}

async function fetchUser(id: string): Promise<User> {
  const response = await fetch(\`/api/users/\${id}\`);
  return response.json();
}`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="typescript" />
</ShikiDemoProvider>

Svelte markup

Use lang="html" for Svelte snippets because the Svelte package exposes the curated Shiki language list in the API reference.

<script lang="ts">
  let count = $state(0);
</script>

<button onclick={() => count += 1}>
  Count: {count}
</button>
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `<script lang="ts">
  let count = $state(0);
<\/script>

<button onclick={() => count += 1}>
  Count: {count}
</button>`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="html" />
</ShikiDemoProvider>

Bash / shell

# Install Kumo Svelte
pnpm add kumo-svelte

# Start development server
pnpm dev
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `# Install Kumo Svelte
pnpm add kumo-svelte

# Start development server
pnpm dev`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="bash" />
</ShikiDemoProvider>

JSON

{
  "name": "kumo-svelte-app",
  "dependencies": {
    "kumo-svelte": "latest",
    "shiki": "^4.0.0"
  }
}
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `{
  "name": "kumo-svelte-app",
  "dependencies": {
    "kumo-svelte": "latest",
    "shiki": "^4.0.0"
  }
}`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="json" />
</ShikiDemoProvider>

CSS

.button {
  background: var(--color-brand);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;

  &:hover {
    background: var(--color-brand-hover);
  }
}
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `.button {
  background: var(--color-brand);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;

  &:hover {
    background: var(--color-brand-hover);
  }
}`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="css" />
</ShikiDemoProvider>

Highlight Lines

Emphasize specific lines with highlightLines. Line numbers are 1-indexed.

function processData(items: string[]) {
  // Filter out empty items
  const filtered = items.filter(Boolean);

  // Transform to uppercase (highlighted)
  const transformed = filtered.map((item) => item.toUpperCase());

  // Return sorted result
  return transformed.toSorted();
}
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `function processData(items: string[]) {
  // Filter out empty items
  const filtered = items.filter(Boolean);

  // Transform to uppercase (highlighted)
  const transformed = filtered.map((item) => item.toUpperCase());

  // Return sorted result
  return transformed.toSorted();
}`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="typescript" highlightLines={[5, 6]} />
</ShikiDemoProvider>

Custom Highlight Color

Customize the highlight color with the --kumo-code-highlight-bg CSS variable.

function greet(name: string) {
  // This line is highlighted
  console.log(`Hello, ${name}!`);

  return name.toUpperCase();
}
CSS Variable --kumo-code-highlight-bg: hsla(220, 80%, 50%, 0.1)
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  let hue = $state(220);
  let opacity = $state(10);

  let lightBg = $derived(`hsla(${hue}, 80%, 50%, ${opacity / 100})`);
  let darkBg = $derived(`hsla(${hue}, 60%, 70%, ${(opacity + 5) / 100})`);

  const code = `function greet(name: string) {
  // This line is highlighted
  console.log(\`Hello, \${name}!\`);

  return name.toUpperCase();
}`;

  let customHighlightStyles = $derived(`#custom-highlight-demo .kumo-shiki {
    --kumo-code-highlight-bg: ${lightBg};
  }
  [data-mode="dark"] #custom-highlight-demo .kumo-shiki {
    --kumo-code-highlight-bg: ${darkBg};
  }`);
</script>

<ShikiDemoProvider>
  <div class="space-y-4">
    {@html `<style>${customHighlightStyles}</style>`}

    <div id="custom-highlight-demo">
      <CodeHighlighted {code} lang="typescript" highlightLines={[2, 3]} />
    </div>

    <div class="flex flex-wrap gap-6 rounded-md border border-kumo-hairline bg-kumo-elevated p-4">
      <label class="flex flex-col gap-2">
        <span class="text-sm text-kumo-subtle">Hue: {hue}°</span>
        <input type="range" min="0" max="360" bind:value={hue} class="w-32" />
      </label>

      <label class="flex flex-col gap-2">
        <span class="text-sm text-kumo-subtle">Opacity: {opacity}%</span>
        <input type="range" min="2" max="30" bind:value={opacity} class="w-32" />
      </label>

      <div class="flex flex-col gap-2">
        <span class="text-sm text-kumo-subtle">CSS Variable</span>
        <code class="rounded bg-kumo-control px-2 py-1 font-mono text-xs">
          --kumo-code-highlight-bg: {lightBg}
        </code>
      </div>
    </div>
  </div>
</ShikiDemoProvider>

Line Numbers

Display line numbers with showLineNumbers.

1
2
3
4
5
6
7
8
9
const statusLabels = {
  active: "Active",
  paused: "Paused",
  errored: "Errored",
};

export function getStatusLabel(status: keyof typeof statusLabels) {
  return statusLabels[status];
}
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `const statusLabels = {
  active: "Active",
  paused: "Paused",
  errored: "Errored",
};

export function getStatusLabel(status: keyof typeof statusLabels) {
  return statusLabels[status];
}`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="typescript" showLineNumbers />
</ShikiDemoProvider>

Copy Button

Add a copy-to-clipboard button with showCopyButton.

pnpm add kumo-svelte
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = "pnpm add kumo-svelte";
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="bash" showCopyButton />
</ShikiDemoProvider>

Full Featured

Combine copy buttons and highlighted lines for a complete code display.

<script lang="ts">
  import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";

  const code = "const answer = 42;";
</script>

<ShikiProvider engine="javascript" languages={["typescript", "bash"]}>
  <CodeHighlighted
    {code}
    lang="typescript"
    showCopyButton
    highlightLines={[1]}
  />
</ShikiProvider>
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";

  const code = `<script lang="ts">
  import { CodeHighlighted, ShikiProvider } from "kumo-svelte/components/code";

  const code = "const answer = 42;";
<\/script>

<ShikiProvider engine="javascript" languages={["typescript", "bash"]}>
  <CodeHighlighted
    {code}
    lang="typescript"
    showCopyButton
    highlightLines={[1]}
  />
</ShikiProvider>`;
</script>

<ShikiDemoProvider>
  <CodeHighlighted {code} lang="html" showCopyButton highlightLines={[7, 8, 9, 10, 11, 12]} />
</ShikiDemoProvider>

Shared Provider

Multiple code blocks can share a single ShikiProvider. Shiki loads once and is reused for all blocks.

const config = { theme: "dark" };
pnpm run build
{ "success": true }
<script lang="ts">
  import { CodeHighlighted } from "kumo-svelte/components/code";
  import ShikiDemoProvider from "./shiki-demo-provider.svelte";
</script>

<ShikiDemoProvider>
  <div class="space-y-4">
    <CodeHighlighted code={`const config = { theme: "dark" };`} lang="typescript" />
    <CodeHighlighted code="pnpm run build" lang="bash" />
    <CodeHighlighted code={`{ "success": true }`} lang="json" />
  </div>
</ShikiDemoProvider>

Themes

CodeHighlighted uses the Kumo theme pair for consistent styling across applications:

  • Light mode: github-light
  • Dark mode: vesper

Server-Side Usage

For SSR and static rendering, use the server utilities to highlight at build time.

One-off highlighting

import { highlightCode } from "kumo-svelte/components/code/server";

const html = await highlightCode(`const x = 1;`, "typescript");

Reusable highlighter

import { createServerHighlighter } from "kumo-svelte/components/code/server";

const highlighter = await createServerHighlighter({
  languages: ["typescript", "bash", "json"],
});

const html1 = highlighter.highlight(code1, "typescript");
const html2 = highlighter.highlight(code2, "bash");

highlighter.dispose();

Custom Hook

Use useShikiHighlighter inside components rendered under a ShikiProvider when you need custom code block rendering.

<script lang="ts">
  import { useShikiHighlighter } from "kumo-svelte/components/code";

  let { code, lang } = $props();
  const shiki = useShikiHighlighter();
  let html = $derived(shiki.highlight(code, lang));
</script>

{#if shiki.error}
  <p>Failed to load highlighter.</p>
{:else if shiki.isLoading || html === null}
  <pre><code>{code}</code></pre>
{:else}
  <pre>{@html html}</pre>
{/if}

Internationalization

Customize copy button labels at the provider level for all code blocks, or override them per component.

<ShikiProvider
  engine="javascript"
  languages={["typescript", "bash"]}
  labels={{ copy: "Copier", copied: "Copié!" }}
>
  <CodeHighlighted
    code={code}
    lang="typescript"
    showCopyButton
    labels={{ copy: "Copy code", copied: "Done!" }}
  />
</ShikiProvider>

SvelteKit Integration

Configure a shared provider in your root layout or in the route group that renders code examples.

<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { ShikiProvider } from "kumo-svelte/components/code";
  import type { Snippet } from "svelte";

  let { children }: { children: Snippet } = $props();
</script>

<ShikiProvider engine="javascript" languages={["typescript", "bash", "json"]}>
  {@render children()}
</ShikiProvider>

API Reference

CodeHighlighted

PropTypeDefault
classstring—
code*string—
highlightLinesnumber[]—
labelsCodeHighlightedLabels—
lang*SupportedLanguage—
showCopyButtonbooleanfalse
showLineNumbersbooleanfalse

On this page

  • Overview
  • Import
  • Basic Usage
  • Examples
    • Languages
    • Highlight Lines
    • Custom Highlight Color
    • Line Numbers
    • Copy Button
    • Full Featured
    • Shared Provider
  • Themes
  • Server-Side Usage
    • One-off highlighting
    • Reusable highlighter
  • Custom Hook
  • Internationalization
  • SvelteKit Integration
  • API Reference
    • CodeHighlighted