CodeHighlighted
@photon-ai/kumo-solid

New in v1.10: Shiki-powered syntax highlighting with lazy loading. Import from @photon-ai/kumo-solid/code to use.

const greeting = "Hello, World!";
console.log(greeting);
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** Basic syntax highlighting demo */
export function CodeHighlightedBasicDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`const greeting = "Hello, World!";
console.log(greeting);`}
        lang="typescript"
      />
    </DemoProvider>
  );
}

Overview

A Shiki-powered syntax highlighter with TextMate grammars, dual light/dark themes, and lazy loading. Exported from a separate entry point ( @photon-ai/kumo-solid/code ) to avoid bundling Shiki for apps that don’t need it.

Installation

CodeHighlighted is exported from a separate entry point to avoid bundling Shiki for apps that don’t need it.

import { ShikiProvider, CodeHighlighted } from "@photon-ai/kumo-solid/code";

Important: Do not import from the main @photon-ai/kumo-solid entry. That would pull Shiki into your bundle even if you don’t use it.

Basic Usage

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

import { ShikiProvider, CodeHighlighted } from "@photon-ai/kumo-solid/code";

export function App() {
  return (
    <ShikiProvider
      engine="javascript"
      languages={["tsx", "typescript", "bash", "json"]}
    >
      {/* All CodeHighlighted components share the same Shiki instance */}
      <CodeHighlighted code="const x = 1;" lang="typescript" />
    </ShikiProvider>
  );
}

Examples

Languages

CodeHighlighted ships a curated set of common Shiki languages. Only load the languages you need.

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();
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** TypeScript with interface */
export function CodeHighlightedTypeScriptDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        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();
}`}
        lang="typescript"
      />
    </DemoProvider>
  );
}

SolidJS / TSX

import { createSignal } from "solid-js";

export function Counter() {
  const [count, setCount] = createSignal(0);
  
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count()}
    </button>
  );
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** SolidJS/TSX code example */
export function CodeHighlightedSolidDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`import { createSignal } from "solid-js";

export function Counter() {
  const [count, setCount] = createSignal(0);
  
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count()}
    </button>
  );
}`}
        lang="tsx"
      />
    </DemoProvider>
  );
}

Bash / Shell

# Install Kumo for SolidJS
npm install @photon-ai/kumo-solid solid-js

# Or with pnpm
pnpm add @photon-ai/kumo-solid solid-js

# Start development server
pnpm dev
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** Bash/shell commands */
export function CodeHighlightedBashDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`# Install Kumo for SolidJS
npm install @photon-ai/kumo-solid solid-js

# Or with pnpm
pnpm add @photon-ai/kumo-solid solid-js

# Start development server
pnpm dev`}
        lang="bash"
      />
    </DemoProvider>
  );
}

JSON

{
  "name": "kumo-solid-app",
  "private": true,
  "dependencies": {
    "@photon-ai/kumo-solid": "^0.1.0",
    "solid-js": "^1.9.0",
    "shiki": "^4.0.0"
  }
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** JSON configuration */
export function CodeHighlightedJsonDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`{
  "name": "kumo-solid-app",
  "private": true,
  "dependencies": {
    "@photon-ai/kumo-solid": "^0.1.0",
    "solid-js": "^1.9.0",
    "shiki": "^4.0.0"
  }
}`}
        lang="json"
      />
    </DemoProvider>
  );
}

CSS

.button {
  background: var(--color-brand);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  
  &:hover {
    background: var(--color-brand-hover);
  }
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** CSS code example */
export function CodeHighlightedCssDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`.button {
  background: var(--color-brand);
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;
  
  &:hover {
    background: var(--color-brand-hover);
  }
}`}
        lang="css"
      />
    </DemoProvider>
  );
}

Highlight Lines

Emphasize specific lines with highlightLines (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();
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** With highlighted lines */
export function CodeHighlightedHighlightLinesDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        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();
}`}
        lang="typescript"
        highlightLines={[5, 6]}
      />
    </DemoProvider>
  );
}

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)

Line Numbers

Display line numbers with showLineNumbers .

import { createSignal, onCleanup, onMount } from "solid-js";

export function useWindowSize() {
  const [size, setSize] = createSignal({ width: 0, height: 0 });
  
  onMount(() => {
    function handleResize() {
      setSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }
    
    handleResize();
    window.addEventListener("resize", handleResize);
    onCleanup(() => window.removeEventListener("resize", handleResize));
  });
  
  return size;
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** With line numbers */
export function CodeHighlightedLineNumbersDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`import { createSignal, onCleanup, onMount } from "solid-js";

export function useWindowSize() {
  const [size, setSize] = createSignal({ width: 0, height: 0 });
  
  onMount(() => {
    function handleResize() {
      setSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }
    
    handleResize();
    window.addEventListener("resize", handleResize);
    onCleanup(() => window.removeEventListener("resize", handleResize));
  });
  
  return size;
}`}
        lang="typescript"
        showLineNumbers
      />
    </DemoProvider>
  );
}

Copy Button

Add a copy-to-clipboard button with showCopyButton .

npm install @photon-ai/kumo-solid solid-js
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** With copy button */
export function CodeHighlightedCopyButtonDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`npm install @photon-ai/kumo-solid solid-js`}
        lang="bash"
        showCopyButton
      />
    </DemoProvider>
  );
}

Combine all features for a complete code display experience.

import { ShikiProvider, CodeHighlighted } from "@photon-ai/kumo-solid/code";

export function CodeExample({ code, language }: Props) {
  return (
    <ShikiProvider
      engine="javascript"
      languages={["tsx", "typescript", "bash", "json"]}
    >
      <CodeHighlighted
        code={code}
        lang={language}
        showCopyButton
      />
    </ShikiProvider>
  );
}
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** Full featured example */
export function CodeHighlightedFullFeaturedDemo() {
  return (
    <DemoProvider>
      <CodeHighlighted
        code={`import { ShikiProvider, CodeHighlighted } from "@photon-ai/kumo-solid/code";

export function CodeExample({ code, language }: Props) {
  return (
    <ShikiProvider
      engine="javascript"
      languages={["tsx", "typescript", "bash", "json"]}
    >
      <CodeHighlighted
        code={code}
        lang={language}
        showCopyButton
      />
    </ShikiProvider>
  );
}`}
        lang="tsx"
        showCopyButton
        highlightLines={[6, 7, 8, 9]}
      />
    </DemoProvider>
  );
}

Shared Provider

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

const config = { theme: "dark" };
npm run build
{ "success": true }
import { CodeHighlighted } from "@photon-ai/kumo-solid/code";

/** Multiple code blocks sharing a provider */
export function CodeHighlightedSharedProviderDemo() {
  return (
    <DemoProvider>
      <div class="space-y-4">
        <CodeHighlighted
          code={`const config = { theme: "dark" };`}
          lang="typescript"
        />
        <CodeHighlighted code={`npm run build`} lang="bash" />
        <CodeHighlighted code={`{ "success": true }`} lang="json" />
      </div>
    </DemoProvider>
  );
}

Themes

CodeHighlighted uses hardcoded themes for consistent styling across all Kumo applications:

  • Light mode: github-light

  • Dark mode: vesper

Theme customization is not supported. This ensures visual consistency across all code blocks in your application.

Server-Side Usage

For SSR frameworks such as SolidStart and Astro, use the server utilities to highlight at build time.

One-off highlighting

// SolidStart server component
import { highlightCode } from "@photon-ai/kumo-solid/code/server";

export default async function Page() {
  const html = await highlightCode(`const x = 1;`, "typescript");

  return <pre innerHTML={html} />;
}

Reusable highlighter

// For multiple highlights, reuse the highlighter
import { createServerHighlighter } from "@photon-ai/kumo-solid/code/server";

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

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

highlighter.dispose(); // Clean up when done

Custom Hook

Use useShikiHighlighter for custom implementations.

import { Show, createMemo } from "solid-js";
import { useShikiHighlighter } from "@photon-ai/kumo-solid/code";

function CustomCodeBlock(props) {
  const { highlight, isLoading, error } = useShikiHighlighter();
  const html = createMemo(() => highlight(props.code, props.lang));

  return (
    <Show
      when={!error()}
      fallback={<div class="text-kumo-critical">Failed to load highlighter</div>}
    >
      <Show
        when={!isLoading()}
        fallback={
          <pre class="animate-pulse">
            <code>{props.code}</code>
          </pre>
        }
      >
        <Show
          when={html()}
          fallback={
            <pre>
              <code>{props.code}</code>
            </pre>
          }
        >
          {(highlighted) => <pre innerHTML={highlighted()} />}
        </Show>
      </Show>
    </Show>
  );
}

Internationalization

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

// Set labels at the provider level for all code blocks
<ShikiProvider
  engine="javascript"
  languages={["tsx", "bash"]}
  labels={{ copy: "Copier", copied: "Copié!" }}
>
  <App />
</ShikiProvider>

// Or override at the component level
<CodeHighlighted
  code={code}
  lang="tsx"
  showCopyButton
  labels={{ copy: "Copy code", copied: "Done!" }}
/>

Framework Integration

SolidStart

import { ShikiProvider } from "@photon-ai/kumo-solid/code";

export function App(props) {
  return (
    <ShikiProvider engine="javascript" languages={["tsx", "bash", "json"]}>
      {props.children}
    </ShikiProvider>
  );
}

Astro (Static)

For static sites, use server-side highlighting for zero client-side JavaScript.

---
// src/components/CodeBlock.astro
import { highlightCode } from "@photon-ai/kumo-solid/code/server";

const { code, lang } = Astro.props;
const html = await highlightCode(code, lang);
---

<div class="code-block" set:html={html} />

Bundle Size

Shiki is lazy-loaded on first render. The size depends on your configuration:

ScenarioLanguagesEngineLazy Load Size
Minimaltsx, jsonJS~75 KB
Standardtsx, ts, bash, json, css, yamlJS~95 KB
Full15+ languagesWASM~250 KB

Teams that don’t import from @photon-ai/kumo-solid/code pay 0 KB.

Migration from Code/CodeBlock

The legacy Code and CodeBlock components are deprecated. They will be removed in v2.0.

// Before (deprecated)
import { Code, CodeBlock } from "@photon-ai/kumo-solid";
<CodeBlock code="const x = 1;" lang="ts" />

// After
import { ShikiProvider, CodeHighlighted } from "@photon-ai/kumo-solid/code";

// Once at app root
<ShikiProvider engine="javascript" languages={["tsx"]}>
  <App />
</ShikiProvider>

// In components
<CodeHighlighted code="const x = 1;" lang="tsx" />

API Reference

ShikiProvider Props

PropTypeRequiredDescription
engine”javascript” | “wasm”Yes

JS is smaller (~50KB), WASM is more accurate (~180KB)

languagesstring[]YesLanguages to support (e.g., [“tsx”, “bash”])
labels{ copy?: string, copied?: string }NoLocalized labels for copy button
childrenJSX.ElementYesApp content

CodeHighlighted Props

PropTypeRequiredDescription
codestringYesSource code to display
langstringYes

Language identifier (must be in provider’s languages)

showLineNumbersbooleanNoDisplay line numbers
highlightLinesnumber[]NoLines to emphasize (1-indexed)
showCopyButtonbooleanNoShow copy-to-clipboard button
labels{ copy?: string, copied?: string }NoOverride provider labels for this instance
classNamestringNoAdditional CSS classes

useShikiHighlighter Return Value

PropertyTypeDescription
highlight(code, lang, options?) => string | nullReturns highlighted HTML, or null if not ready
isLoadingAccessor<boolean>True while Shiki is loading
isReadyAccessor<boolean>True when highlight() is safe to call
errorAccessor<Error | null>Error if Shiki initialization failed