MUI Docs Infra

Warning

This is an internal project, and is not intended for public use. No support or stability guarantees are provided.

Code Highlighter

The CodeHighlighter component provides a powerful and flexible way to display interactive code examples with syntax highlighting, multiple variants, and live previews. It supports both static code blocks and interactive demos with component previews.

The component uses the Props Context Layering pattern to work seamlessly across server and client boundaries, allowing progressive enhancement from static code to interactive demos.

Features

  • Syntax highlighting with support for multiple languages using Starry Night
  • Live component previews alongside code
  • Multiple Variant support for showing different implementation styles
  • Automatic Transformations from TypeScript to JavaScript
  • Lazy loading with fallback content
  • Lazy syntax highlighting for performance optimization
  • Customizable content renderers
  • Hybrid rendering support for build, server, or client-time loading, parsing, and transforming
  • Webpack integration for build-time pre-computation

Basic Usage

Let's start with the fundamentals. CodeHighlighter can display simple code blocks with syntax highlighting, perfect for documentation where you just need to show code examples:

Simple Code Block

We can use it to highlight code snippets in various languages, like JavaScript, TypeScript, or even CSS.

hello.js
console.log('Hello, world!');
import * as React from 'react';
import { Code } from './CodeBlock';

export function BasicCode() {
  return (
    <Code fileName="hello.js">{`console.log('Hello, world!');`}</Code>
  );
}

But CodeHighlighter really shines when you want to combine working React components with their source code. This creates an interactive experience where users can see both the rendered output and the implementation.

Interactive Demo

CheckboxBasic.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

export function CheckboxBasic() {
  return (
    <Checkbox defaultChecked />
  );
}
import { CheckboxBasic } from './CheckboxBasic';
import { createDemo } from './createDemo';

export const DemoCheckboxBasic = createDemo(import.meta.url, CheckboxBasic, {
  slug: 'interactive-demo-basic',
});

Demo Factory Pattern

Tip

New to the overall approach? See the broader Built Factories Pattern for why factories use import.meta.url, how variants are derived, and the server vs client split.

Note

Before you can use createDemo() in your demos, you must first create this factory function in your repo (see the abstractCreateDemo docs for details).

To unlock CodeHighlighter's full potential—especially build-time optimization—you'll need to use the factory pattern. This isn't just a convention; it's required for precomputation to work.

The factory pattern uses createDemo() to structure your demos in a way that the webpack loader can process and cache at build time. You implement createDemo within your app using abstractCreateDemo to define the structure and behavior of your demos.

Factory Structure

All demos must use this structure in an index.ts file:

// app/components/checkbox/demos/basic/index.ts
import { createDemo } from '../createDemo';
import { Checkbox } from './Checkbox';

export const DemoCheckboxBasic = createDemo(import.meta.url, Checkbox);

For multiple variants:

// app/components/checkbox/demos/basic/index.ts
import { createDemoWithVariants } from '../createDemo';
import { Checkbox as CssModules } from './css-modules/Checkbox';
import { Checkbox as Tailwind } from './tailwind/Checkbox';

export const DemoCheckboxBasic = createDemoWithVariants(import.meta.url, { CssModules, Tailwind });

Demo File Structure

When using the factory pattern with precomputation, organize your demo files like this:

app/components/checkbox/demos/
  basic/
    index.ts             # Factory file (processed by webpack loader)
    Checkbox.tsx         # Component implementation
    Checkbox.module.css  # Dependencies (auto-loaded)

This follows Next.js' file based routing conventions, similar to how app/components/checkbox/page.tsx is built as a "page", app/components/checkbox/demos/basic/index.ts is built as a "demo".

This also allows demo components to follow internal naming conventions, like CheckboxBasic.tsx that has a named export of CheckboxBasic, while the demo itself can be loaded by importing ./demos/basic (without needing to specify the index file).

It allows imports to remain the same when variants are added, e.g. import { DemoCheckboxBasic } from './demos/basic' will still work even if the demo is split into multiple variants.

app/components/checkbox/demos/
  basic/
    index.ts               # Factory file (processed by webpack loader)
    tailwind/
      index.ts             # Simple re-export of the implementation (optional)
      Checkbox.tsx         # Component implementation
    css-modules/
      index.ts             # Simple re-export of the implementation (optional)
      Checkbox.tsx         # Component implementation
      Checkbox.module.css  # Dependencies (auto-loaded)

Webpack Loader Integration

The precomputation is handled by a webpack loader that processes demo files at build time, enabling caching by the contents of the demo index file and all of its dependencies.

Note

For detailed information about the webpack loader implementation, configuration, and advanced usage, see the Precompute Loader Documentation.

Tip

Client-Side Implementation: For client-side loading, highlighting, and transforms, see the Code Provider Documentation which provides detailed examples of runtime processing.

Important: Precomputation only works:

  • ✓ In files matching the webpack loader pattern (default: ./app/**/demos/*/index.ts)
  • ✓ Using createDemo()
  • ✓ In both main demos and nested demo examples
  • × Not in direct CodeHighlighter usage
  • × Not in files outside the configured loader pattern

Advanced Features

Once you've mastered the basics, CodeHighlighter offers several powerful features for more sophisticated use cases.

Demo Variants

Sometimes you want to show different approaches to the same problem: CSS Modules versus Tailwind, Hooks or Blocks pattern, or different implementation strategies. CodeHighlighter makes this seamless with variant switching. Your components can even appear differently, but we recommend keeping them as similar as possible to avoid confusion.

import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

import styles from './CheckboxRed.module.css';

export function CheckboxRed() {
  return (
    <Checkbox defaultChecked className={styles.root} />
  );
}
import { CheckboxRed as CssModules } from './css-modules/CheckboxRed';
import { CheckboxRed as Tailwind } from './tailwind/CheckboxRed';
import { createDemoWithVariants } from './createDemo';

export const DemoCheckboxRed = createDemoWithVariants(import.meta.url, { CssModules, Tailwind });

Code Transformed

One of CodeHighlighter's most powerful features is automatic code transformation. Write your examples in TypeScript, and users can instantly see the JavaScript equivalent:

UserList.tsx
import * as React from 'react';

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

interface UserListProps {
  users: User[];
  onSelect: (user: User) => void;
}

export function UserList({ users, onSelect }: UserListProps) {
  const [query, setQuery] = React.useState<string>('');

  const filtered = users.filter((user: User) =>
    user.name.toLowerCase().includes(query.toLowerCase()),
  );

  return (
    <ul>
      {filtered.map((user: User) => (
        <li key={user.id} onClick={() => onSelect(user)}>
          {user.name}
        </li>
      ))}
    </ul>
  );
}
import * as React from 'react';
import { Code } from './Code';

const source = `import * as React from 'react';

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

interface UserListProps {
  users: User[];
  onSelect: (user: User) => void;
}

export function UserList({ users, onSelect }: UserListProps) {
  const [query, setQuery] = React.useState<string>('');

  const filtered = users.filter((user: User) =>
    user.name.toLowerCase().includes(query.toLowerCase()),
  );

  return (
    <ul>
      {filtered.map((user: User) => (
        <li key={user.id} onClick={() => onSelect(user)}>
          {user.name}
        </li>
      ))}
    </ul>
  );
}`;

export function BasicCode() {
  return (
    <Code fileName="UserList.tsx">{source}</Code>
  );
}

Code Transformed Addition

Transformers can also add lines. Marking each new line with a @expanding comment — or bracketing a contiguous run with paired @expanding-start / @expanding-end comments — in the returned comments map tells the runtime to animate those lines' heights during the swap, mirroring how transformer-removed lines collapse. Toggle the switch to see a randomly generated API key constant slide in at the top of the snippet:

example.tsx
const API_KEY = '33mvsrdomij';

import { ApiClient } from './client';

export function App() {
  return <ApiClient apiKey={API_KEY} />;
}
import * as React from 'react';
import { Code } from './Code';

export function CredentialsCode() {
  return (
    // @focus
    <Code fileName="example.tsx">{`import { ApiClient } from './client';\n\nexport function App() {\n  return <ApiClient apiKey={API_KEY} />;\n}`}</Code>
  );
}

Code Highlight Idle

For pages with many code examples, you can defer syntax highlighting until the browser is idle, keeping your initial page loads fast:

greeting.js
console.log('Hello, world!');
import * as React from 'react';
import { Code } from './Code';

export function BasicCode() {
  return (
    <Code fileName="greeting.js">{`console.log('Hello, world!');`}</Code>
  );
}

Demo Fallback

Good user experience means showing meaningful feedback during loading. The fallback content is also what search engines and AI bots see in the initial HTML, making it crucial for SEO and content discovery. CodeHighlighter supports custom loading components and skeleton loaders:

CheckboxRed.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';
import styles from './CheckboxRed.module.css';

export function CheckboxRed() {
  return (
    <Checkbox className={styles.root} defaultChecked />
  );
}

Writing a ContentLoading component. Call useCodeFallback(props) to read the fallback source (and, for multi-file or multi-variant fallbacks, extraSource / extraVariants), render it with hastToJsx, and wrap each file in semantic markup — a <dl> with the filename in <dt> and the code in <dd> — so crawlers and transformHtmlCodeBlock can read every file from the initial HTML. useCodeFallback also hoists the fallback up to the client, where its text is the DEFLATE dictionary used to decompress the hastCompressed source; a ContentLoading component that doesn't call it will throw. See the demo above for the full pattern.

Demo Fallback All Files

When fallbackUsesExtraFiles is enabled, the fallback content receives all extra files from the selected variant. This means search engines and AI bots will see all the component's related files (CSS, utilities, etc.) in the initial HTML, improving content discoverability. Note that the complete list of filenames is always available for navigation, regardless of this setting:

CheckboxRed.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';
import styles from './CheckboxRed.module.css';

export function CheckboxRed() {
  return (
    <Checkbox className={styles.root} defaultChecked />
  );
}
CheckboxRed.module.css
.root {
  background-color: #e5484d !important;
  border-color: #e5484d !important;
}

Demo Fallback All Variants

When fallbackUsesAllVariants is enabled, the fallback content receives data for all available variants. This ensures that search engines and AI bots can see all implementation approaches (CSS Modules, Tailwind, etc.) in the initial HTML, making your documentation more comprehensive for automated indexing. Note that the complete list of filenames is always available for navigation, regardless of this setting:

CssModules variant
CheckboxRed.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

import styles from './CheckboxRed.module.css';

export function CheckboxRed() {
  return (
    <Checkbox defaultChecked className={styles.root} />
  );
}
CheckboxRed.module.css
.root {
  background-color: #e5484d !important;
  border-color: #e5484d !important;
}
Tailwind variant
CheckboxRed.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

export function CheckboxRed() {
  return (
    <Checkbox defaultChecked className="bg-red-500" />
  );
}
Default variant
index.ts
import { CheckboxRed as CssModules } from './css-modules/CheckboxRed';
import { CheckboxRed as Tailwind } from './tailwind/CheckboxRed';
import { createDemoWithVariants } from './createDemo';

export const DemoCheckboxRed = createDemoWithVariants(import.meta.url, { CssModules, Tailwind });
css-modules/CheckboxRed.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

import styles from './CheckboxRed.module.css';

export function CheckboxRed() {
  return (
    <Checkbox defaultChecked className={styles.root} />
  );
}
tailwind/CheckboxRed.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

export function CheckboxRed() {
  return (
    <Checkbox defaultChecked className="bg-red-500" />
  );
}
createDemo.ts
import 'server-only';

import {
  createDemoFactory,
  createDemoWithVariantsFactory,
} from '@mui/internal-docs-infra/abstractCreateDemo';

import { DemoContentLoading } from './DemoContentLoading';
import { DemoContent } from './DemoContent';

const projectDir = process.env.SOURCE_CODE_ROOT_DIR;
const projectUrl = process.env.SOURCE_CODE_ROOT_URL;

/**
 * Creates a demo component for displaying code examples with syntax highlighting.
 * @param url Depends on `import.meta.url` to determine the source file location.
 * @param component The component to be rendered in the demo.
 * @param meta Additional meta for the demo.
 */
export const createDemo = createDemoFactory({
  DemoContentLoading,
  DemoContent,
  fallbackUsesAllVariants: true,
  projectDir,
  projectUrl,
});

/**
 * Creates a demo component for displaying code examples with syntax highlighting.
 * A variant is a different implementation style of the same component.
 * @param url Depends on `import.meta.url` to determine the source file location.
 * @param variants The variants of the component to be rendered in the demo.
 * @param meta Additional meta for the demo.
 */
export const createDemoWithVariants = createDemoWithVariantsFactory({
  DemoContentLoading,
  DemoContent,
  fallbackUsesAllVariants: true,
  projectDir,
  projectUrl,
});
css-modules/CheckboxRed.module.css
.root {
  background-color: #e5484d !important;
  border-color: #e5484d !important;
}
DemoContentLoading.tsx
'use client';

import * as React from 'react';
import type { ContentLoadingProps } from '@mui/internal-docs-infra/CodeHighlighter/types';
import { useCodeFallback } from '@mui/internal-docs-infra/CodeHighlighter';
import { hastToJsx } from '@mui/internal-docs-infra/pipeline/hastUtils';
import {
  generateFileSlug,
  getLanguageFromExtension,
} from '@mui/internal-docs-infra/pipeline/loaderUtils';
import { Tabs } from '@/components/Tabs';
import { CodeActionsMenu } from './CodeActionsMenu';
import { CodeBlockHeader, CodeBlockHeaderLabel } from './CodeBlockHeader';
import { DemoVariantBar } from './DemoVariantBar';
import styles from './DemoContent.module.css';
import loadingStyles from './DemoContentLoading.module.css';

import './syntax.css';

const variantNames: Record<string, string | undefined> = {
  CssModules: 'CSS Modules',
};

/** Derive a `language-*` hint from a file name's extension (e.g. `.tsx` → `tsx`). */
function languageForFile(fileName: string | undefined): string | undefined {
  if (!fileName) {
    return undefined;
  }
  const dot = fileName.lastIndexOf('.');
  return dot >= 0 ? getLanguageFromExtension(fileName.slice(dot)) : undefined;
}

export function DemoContentLoading(props: ContentLoadingProps<object>) {
  // `useCodeFallback` decodes the compact per-file fallbacks (and hoists them as
  // the DEFLATE dictionary). The semantic `<section><figure><dl>` markup keeps
  // every file/variant in the DOM for crawlers; CSS shows only the initial
  // variant's main file.
  const { source, extraSource, extraVariants } = useCodeFallback(props);
  const mainSlug = props.slug ?? '';
  const mainVariant = props.initialVariant ?? 'Default';
  const tabs = React.useMemo(
    () =>
      props.fileNames?.map((name) => ({
        id: name || '',
        name: name || '',
        slug: generateFileSlug(mainSlug, name || '', mainVariant),
      })),
    [props.fileNames, mainSlug, mainVariant],
  );
  const variants = React.useMemo(
    () =>
      Object.keys(props.components || {}).map((variant) => ({
        value: variant,
        label: variantNames[variant] || variant,
      })),
    [props.components],
  );

  const onTabSelect = React.useCallback(() => {
    // No-op while loading.
  }, []);

  const firstFileName = props.fileNames?.[0];
  const showTabs = !!tabs && tabs.length > 1;
  const { language } = props;

  return (
    <div>
      {(props.fileNames || []).map((name) => {
        const slug = generateFileSlug(mainSlug, name, mainVariant);
        return <span key={slug} id={slug} className={styles.fileRefs} />;
      })}
      {Object.keys(extraVariants || {}).flatMap((variantName) =>
        (extraVariants?.[variantName]?.fileNames || []).map((name) => {
          const slug = generateFileSlug(mainSlug, name, variantName);
          return <span key={slug} id={slug} className={styles.fileRefs} />;
        }),
      )}
      <div className={styles.container}>
        <div className={styles.demoSection}>
          <DemoVariantBar variants={variants} selectedVariant={variants[0]?.value} disabled />
          <div className={styles.demoSurface}>{props.component}</div>
        </div>
        <div className={styles.codeSection}>
          <CodeBlockHeader menu={<CodeActionsMenu loading inline={!showTabs} />}>
            {showTabs && (
              <Tabs tabs={tabs} selectedTabId={firstFileName} onTabSelect={onTabSelect} disabled />
            )}
            {!showTabs && firstFileName && (
              <CodeBlockHeaderLabel>{firstFileName}</CodeBlockHeaderLabel>
            )}
          </CodeBlockHeader>
          <section className={loadingStyles.variants}>
            <figure className={loadingStyles.variant}>
              <figcaption>{mainVariant} variant</figcaption>
              <dl>
                {source && (
                  <React.Fragment>
                    <dt>
                      <code>{firstFileName}</code>
                    </dt>
                    <dd>
                      <pre className={styles.codeBlock}>
                        <code className={language ? `language-${language}` : undefined}>
                          {hastToJsx(source)}
                        </code>
                      </pre>
                    </dd>
                  </React.Fragment>
                )}
                {Object.entries(extraSource || {}).map(([fileName, hast]) => {
                  const fileLanguage = languageForFile(fileName);
                  return (
                    <React.Fragment key={fileName}>
                      <dt>
                        <code>{fileName}</code>
                      </dt>
                      <dd>
                        <pre className={styles.codeBlock}>
                          <code className={fileLanguage ? `language-${fileLanguage}` : undefined}>
                            {hastToJsx(hast)}
                          </code>
                        </pre>
                      </dd>
                    </React.Fragment>
                  );
                })}
              </dl>
            </figure>
            {Object.keys(extraVariants || {}).map((variantName) => {
              const variant = extraVariants?.[variantName];
              if (!variant) {
                return null;
              }
              const variantMainFile = variant.fileNames?.[0];
              const variantLanguage = languageForFile(variantMainFile);
              return (
                <figure key={variantName} className={loadingStyles.variant}>
                  <figcaption>{variantName} variant</figcaption>
                  <dl>
                    {variant.source && (
                      <React.Fragment>
                        <dt>
                          <code>{variantMainFile}</code>
                        </dt>
                        <dd>
                          <pre className={styles.codeBlock}>
                            <code
                              className={
                                variantLanguage ? `language-${variantLanguage}` : undefined
                              }
                            >
                              {hastToJsx(variant.source)}
                            </code>
                          </pre>
                        </dd>
                      </React.Fragment>
                    )}
                    {Object.entries(variant.extraSource || {}).map(([fileName, hast]) => {
                      const fileLanguage = languageForFile(fileName);
                      return (
                        <React.Fragment key={fileName}>
                          <dt>
                            <code>{fileName}</code>
                          </dt>
                          <dd>
                            <pre className={styles.codeBlock}>
                              <code
                                className={fileLanguage ? `language-${fileLanguage}` : undefined}
                              >
                                {hastToJsx(hast)}
                              </code>
                            </pre>
                          </dd>
                        </React.Fragment>
                      );
                    })}
                  </dl>
                </figure>
              );
            })}
          </section>
        </div>
      </div>
    </div>
  );
}
DemoContent.tsx
'use client';

import * as React from 'react';
import type { ContentProps } from '@mui/internal-docs-infra/CodeHighlighter/types';
import { useDemo } from '@mui/internal-docs-infra/useDemo';
import { useScrollAnchor } from '@mui/internal-docs-infra/useScrollAnchor';
import { Tabs } from '@/components/Tabs';
import { CodeActionsMenu } from './CodeActionsMenu';
import { CodeBlockHeader, CodeBlockHeaderLabel } from './CodeBlockHeader';
import { DemoVariantBar } from './DemoVariantBar';
import styles from './DemoContent.module.css';

import './syntax.css';

const variantNames: Record<string, string | undefined> = {
  CssModules: 'CSS Modules',
};

export function DemoContent(props: ContentProps<object>) {
  const demo = useDemo(props, {
    preClassName: styles.codeBlock,
    transformDelay: 350,
    variantSwapDelay: 350,
  });

  const hasJsTransform = demo.availableTransforms.includes('js');
  const isJsSelected = demo.selectedTransform === 'js';

  // Scroll-anchor session for the JS/TS transform swap. Keeps the toggle
  // (or the action-menu trigger that fronts it) pinned under the user's
  // pointer while the code height changes during the swap.
  const { containerRef: transformAnchorRef, anchorScroll: anchorTransformScroll } =
    useScrollAnchor<HTMLDivElement>();

  const toggleJs = React.useCallback(
    (enabled: boolean, anchorEl: HTMLElement | null) => {
      if (anchorEl) {
        anchorTransformScroll(anchorEl, 700);
      }
      demo.selectTransform(enabled ? 'js' : null);
    },
    [demo, anchorTransformScroll],
  );

  // Scroll-anchor session for variant swaps. Keeps the variant selector
  // pinned while the side-by-side demo/code panels reflow.
  const { containerRef: variantAnchorRef, anchorScroll: anchorVariantScroll } =
    useScrollAnchor<HTMLDivElement>();

  const selectVariant = React.useCallback(
    (variant: string | null, anchorEl: HTMLElement | null) => {
      if (anchorEl) {
        anchorVariantScroll(anchorEl, 700);
      }
      demo.selectVariant(variant);
    },
    [demo, anchorVariantScroll],
  );

  const tabs = React.useMemo(
    () => demo.files.map(({ name, slug }) => ({ id: name, name, slug })),
    [demo.files],
  );
  const variants = React.useMemo(
    () =>
      demo.variants.map((variant) => ({ value: variant, label: variantNames[variant] || variant })),
    [demo.variants],
  );

  const hasTabs = tabs.length > 1;

  return (
    <div>
      {demo.allFilesSlugs.map(({ slug }) => (
        <span key={slug} id={slug} className={styles.fileRefs} />
      ))}
      <div ref={variantAnchorRef} className={styles.container}>
        <div className={styles.demoSection}>
          <DemoVariantBar
            variants={variants}
            selectedVariant={demo.selectedVariant}
            onVariantChange={selectVariant}
          />
          <div className={styles.demoSurface}>{demo.component}</div>
        </div>
        <div ref={transformAnchorRef} className={styles.codeSection}>
          <CodeBlockHeader
            pending={demo.pendingTransform}
            menu={
              <CodeActionsMenu
                inline={!hasTabs}
                onCopy={demo.copy}
                onCopyMarkdown={hasTabs ? demo.copyMarkdown : undefined}
                fileUrl={demo.selectedFileUrl}
                fileName={demo.selectedFileName}
                fileSlug={demo.selectedFileSlug}
                jsTransform={
                  hasJsTransform ? { enabled: isJsSelected, onToggle: toggleJs } : undefined
                }
              />
            }
          >
            {hasTabs ? (
              <Tabs
                tabs={tabs}
                selectedTabId={demo.selectedFileName}
                onTabSelect={demo.selectFileName}
              />
            ) : (
              <CodeBlockHeaderLabel>{demo.selectedFileName}</CodeBlockHeaderLabel>
            )}
          </CodeBlockHeader>
          <div className={styles.code}>{demo.selectedFile}</div>
        </div>
      </div>
    </div>
  );
}
CodeActionsMenu.tsx
'use client';

import * as React from 'react';
import { Menu } from '@base-ui/react/menu';
import { Select } from '@/components/Select';
import { LabeledSwitch } from '@/components/LabeledSwitch';
import styles from './CodeActionsMenu.module.css';

export interface CodeActionsMenuProps {
  onCopy?: (event: React.MouseEvent<Element>) => void | Promise<void>;
  /**
   * Copies all files in the current variant as a Markdown snippet (heading
   * + per-file fenced code blocks). Provide only on multi-file demos and
   * code blocks; single-file callers should leave this `undefined`.
   */
  onCopyMarkdown?: (event: React.MouseEvent<Element>) => void | Promise<void>;
  fileUrl?: string;
  fileName?: string;
  /**
   * Slug used to build a deep link to this file inside the current page.
   * When provided, a "Copy link" action is shown that copies
   * `${location.origin}${location.pathname}#${fileSlug}` to the clipboard.
   */
  fileSlug?: string;
  /**
   * Resets edits made to the source. When provided, a "Reset edits" action is
   * shown. Pass `undefined` (the typical case for non-editable demos and code
   * blocks) to hide the action.
   */
  onReset?: () => void;
  jsTransform?: {
    enabled: boolean;
    /**
     * Called when the user toggles the JS transform. `anchorEl` is the DOM
     * node that should be used as the scroll-anchor for the resulting
     * layout shift: the inline `LabeledSwitch` wrapper when actions render
     * inline, or the popup `Menu.Trigger` button when the toggle lives
     * inside the action menu (the `CheckboxItem` itself is unmounted as
     * soon as the menu closes, so it can't anchor the post-swap scroll).
     */
    onToggle: (enabled: boolean, anchorEl: HTMLElement | null) => void;
  };
  variants?: {
    items: { label: string; value: string }[];
    selected?: string;
    onChange: (value: string) => void;
  };
  /**
   * Render actions as a row of icon buttons in the header instead of as a
   * popup menu. Use for single-file code blocks where there's plenty of
   * horizontal room. The same icons are used in both modes.
   */
  inline?: boolean;
  loading?: boolean;
}

export function CodeActionsMenu({
  onCopy,
  onCopyMarkdown,
  fileUrl,
  fileName,
  fileSlug,
  onReset,
  jsTransform,
  variants,
  inline,
  loading,
}: CodeActionsMenuProps) {
  const handleCopyLink = React.useCallback(() => {
    if (!fileSlug || typeof window === 'undefined') {
      return;
    }
    const link = `${window.location.origin}${window.location.pathname}#${fileSlug}`;
    void navigator.clipboard?.writeText(link);
  }, [fileSlug]);
  // Refs to the JS-transform toggle's stable scroll anchor. In inline
  // mode, the `LabeledSwitch` wrapper stays mounted across the swap. In
  // popup mode, the `Menu.CheckboxItem` unmounts when the menu closes, so
  // we anchor on the `Menu.Trigger` button instead.
  const inlineSwitchRef = React.useRef<HTMLDivElement | null>(null);
  const menuTriggerRef = React.useRef<HTMLButtonElement | null>(null);
  const handleInlineJsToggle = React.useCallback(
    (enabled: boolean) => {
      jsTransform?.onToggle(enabled, inlineSwitchRef.current);
    },
    [jsTransform],
  );
  const handlePopupJsToggle = React.useCallback(
    (enabled: boolean) => {
      jsTransform?.onToggle(enabled, menuTriggerRef.current);
    },
    [jsTransform],
  );
  // Hide the GitHub link when the URL is a local `file://` URL — that means
  // the build-time URL rewrite was skipped (e.g. for server-loaded demos) and
  // the link wouldn't be navigable from the browser.
  const externalFileUrl = fileUrl && !fileUrl.startsWith('file://') ? fileUrl : undefined;
  if (inline) {
    if (loading) {
      return (
        <div className={styles.inlineActions}>
          {jsTransform && (
            <button
              type="button"
              className={styles.inlineIconButton}
              aria-label="Toggle JavaScript"
              disabled
            >
              <CheckIcon />
            </button>
          )}
          <button type="button" className={styles.inlineIconButton} aria-label="Copy code" disabled>
            <CopyIcon />
          </button>
        </div>
      );
    }
    return (
      <div className={styles.inlineActions}>
        {variants && variants.items.length > 1 && (
          <Select
            items={variants.items}
            value={variants.selected}
            onValueChange={(value) => value && variants.onChange(value)}
          />
        )}
        {jsTransform && (
          <div ref={inlineSwitchRef} className={styles.inlineSwitchAnchor}>
            <LabeledSwitch
              checked={jsTransform.enabled}
              onCheckedChange={handleInlineJsToggle}
              labels={{ false: 'TS', true: 'JS' }}
            />
          </div>
        )}
        {onCopy && (
          <InlineIconButton
            onClick={onCopy}
            label={fileName ? `Copy ${fileName} source` : 'Copy source'}
            icon={<CopyIcon />}
          />
        )}
        {fileSlug && (
          <InlineIconButton
            onClick={handleCopyLink}
            label={fileName ? `Copy ${fileName} link` : 'Copy link'}
            icon={<LinkIcon />}
          />
        )}
        {onReset && <InlineIconButton onClick={onReset} label="Reset edits" icon={<ResetIcon />} />}
        {externalFileUrl && (
          <a
            className={styles.inlineIconButton}
            href={externalFileUrl}
            target="_blank"
            rel="noreferrer noopener"
            aria-label={fileName ? `Open ${fileName} in GitHub` : 'Open in GitHub'}
          >
            <GitHubIcon />
          </a>
        )}
        {onCopyMarkdown && (
          <InlineIconButton
            onClick={onCopyMarkdown}
            label="Copy all files as Markdown"
            icon={<MarkdownIcon />}
          />
        )}
      </div>
    );
  }

  const handleCopy = (event: React.MouseEvent<Element>) => {
    onCopy?.(event);
  };

  const handleCopyMarkdown = (event: React.MouseEvent<Element>) => {
    onCopyMarkdown?.(event);
  };

  if (loading) {
    return (
      <button type="button" className={styles.menuTrigger} aria-label="More actions" disabled>
        <span className={styles.menuTriggerInner}>
          <MoreIcon />
        </span>
      </button>
    );
  }

  return (
    <Menu.Root>
      <Menu.Trigger
        ref={menuTriggerRef}
        className={styles.menuTrigger}
        aria-label="More actions"
        type="button"
      >
        <span className={styles.menuTriggerInner}>
          <MoreIcon />
        </span>
      </Menu.Trigger>
      <Menu.Portal>
        <Menu.Positioner sideOffset={8} align="end" alignOffset={2} arrowPadding={3}>
          <Menu.Popup className={styles.menuPopup}>
            <Menu.Arrow className={styles.menuArrow}>
              <ArrowIcon />
            </Menu.Arrow>
            {onCopy && (
              <Menu.Item className={styles.menuItem} onClick={handleCopy}>
                <span className={styles.menuItemIcon} aria-hidden>
                  <CopyIcon />
                </span>
                {fileName ? `Copy ${fileName} source` : 'Copy source'}
              </Menu.Item>
            )}
            {fileSlug && (
              <Menu.Item className={styles.menuItem} onClick={handleCopyLink}>
                <span className={styles.menuItemIcon} aria-hidden>
                  <LinkIcon />
                </span>
                {fileName ? `Copy ${fileName} link` : 'Copy link'}
              </Menu.Item>
            )}
            {onReset && (
              <Menu.Item className={styles.menuItem} onClick={onReset}>
                <span className={styles.menuItemIcon} aria-hidden>
                  <ResetIcon />
                </span>
                Reset edits
              </Menu.Item>
            )}
            {externalFileUrl && (
              <Menu.Item
                className={styles.menuItem}
                render={
                  <a href={externalFileUrl} target="_blank" rel="noreferrer noopener">
                    <span className={styles.menuItemIcon} aria-hidden>
                      <GitHubIcon />
                    </span>
                    {fileName ? `Open ${fileName} in GitHub` : 'Open in GitHub'}
                  </a>
                }
                closeOnClick
              />
            )}
            {onCopyMarkdown && (
              <Menu.Item className={styles.menuItem} onClick={handleCopyMarkdown}>
                <span className={styles.menuItemIcon} aria-hidden>
                  <MarkdownIcon />
                </span>
                Copy all files as Markdown
              </Menu.Item>
            )}
            {jsTransform && (
              <React.Fragment>
                <div className={styles.menuSeparator} role="separator" />
                <Menu.CheckboxItem
                  className={styles.menuItem}
                  checked={jsTransform.enabled}
                  onCheckedChange={handlePopupJsToggle}
                  closeOnClick={false}
                >
                  <span className={styles.menuItemIcon} aria-hidden>
                    {jsTransform.enabled ? <CheckIcon /> : null}
                  </span>
                  Transpile to JavaScript
                </Menu.CheckboxItem>
              </React.Fragment>
            )}
            {variants && variants.items.length > 1 && (
              <React.Fragment>
                <div className={styles.menuSeparator} role="separator" />
                <Menu.RadioGroup value={variants.selected} onValueChange={variants.onChange}>
                  {variants.items.map((item) => (
                    <Menu.RadioItem
                      key={item.value}
                      value={item.value}
                      className={styles.menuItem}
                      closeOnClick
                    >
                      <span className={styles.menuItemIcon} aria-hidden>
                        <Menu.RadioItemIndicator>
                          <CheckIcon />
                        </Menu.RadioItemIndicator>
                      </span>
                      {item.label}
                    </Menu.RadioItem>
                  ))}
                </Menu.RadioGroup>
              </React.Fragment>
            )}
          </Menu.Popup>
        </Menu.Positioner>
      </Menu.Portal>
    </Menu.Root>
  );
}

function InlineIconButton({
  onClick,
  label,
  icon,
}: {
  onClick: (event: React.MouseEvent<HTMLButtonElement>) => void | Promise<void>;
  label: string;
  icon: React.ReactNode;
}) {
  return (
    <button type="button" className={styles.inlineIconButton} onClick={onClick} aria-label={label}>
      {icon}
    </button>
  );
}

function MoreIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="16" height="20" viewBox="0 0 16 20" fill="currentColor" {...props}>
      <circle cx="8" cy="2" r="2" />
      <circle cx="8" cy="10" r="2" />
      <circle cx="8" cy="18" r="2" />
    </svg>
  );
}

function CopyIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" {...props}>
      <path
        d="M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1ZM19 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H19C20.1 23 21 22.1 21 21V7C21 5.9 20.1 5 19 5ZM19 21H8V7H19V21Z"
        fill="currentColor"
      />
    </svg>
  );
}

function LinkIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" {...props}>
      <path
        d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"
        fill="currentColor"
      />
    </svg>
  );
}

function ResetIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" {...props}>
      <path
        d="M12 5V2L7 7l5 5V8c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"
        fill="currentColor"
      />
    </svg>
  );
}

function MarkdownIcon(props: React.ComponentProps<'svg'>) {
  // GitHub's Markdown mark, simplified.
  return (
    <svg width="16" height="12" viewBox="0 0 208 128" fill="currentColor" {...props}>
      <path
        fillRule="evenodd"
        clipRule="evenodd"
        d="M193 0H15C6.7 0 0 6.7 0 15v98c0 8.3 6.7 15 15 15h178c8.3 0 15-6.7 15-15V15c0-8.3-6.7-15-15-15zM30 98V30h20l20 25 20-25h20v68H90V59L70 84 50 59v39H30zm125 0l-30-33h20V30h20v35h20l-30 33z"
      />
    </svg>
  );
}

function GitHubIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" {...props}>
      <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
    </svg>
  );
}

function CheckIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="12" height="12" viewBox="0 0 10 10" fill="currentColor" {...props}>
      <path d="M9.1603 1.12218C9.50684 1.34873 9.60427 1.81354 9.37792 2.16038L5.13603 8.66012C5.01614 8.8438 4.82192 8.96576 4.60451 8.99384C4.3871 9.02194 4.1683 8.95335 4.00574 8.80615L1.24664 6.30769C0.939709 6.02975 0.916013 5.55541 1.19372 5.24822C1.47142 4.94102 1.94536 4.91731 2.2523 5.19524L4.36085 7.10461L8.12299 1.33999C8.34934 0.993152 8.81376 0.895638 9.1603 1.12218Z" />
    </svg>
  );
}

function ArrowIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg width="20" height="10" viewBox="0 0 20 10" fill="none" {...props}>
      <path
        d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
        className={styles.arrowFill}
      />
      <path
        d="M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z"
        className={styles.arrowOuterStroke}
      />
      <path
        d="M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z"
        className={styles.arrowInnerStroke}
      />
    </svg>
  );
}
CodeBlockHeader.tsx
import * as React from 'react';
import styles from './CodeBlockHeader.module.css';

export interface CodeBlockHeaderProps {
  /**
   * Main header content (typically a `<Tabs>` element or a filename label).
   */
  children?: React.ReactNode;
  /**
   * Right-aligned action slot — typically a `<CodeActionsMenu>`.
   */
  menu?: React.ReactNode;
  /**
   * When true, the side decoration lines start 8px below the top edge so they
   * clear a rounded container corner. Use for standalone code blocks where the
   * header sits at the top of a rounded container; leave false for demo code
   * sections that have a sibling above.
   */
  roundedTop?: boolean;
  /**
   * Forward `useCode().pendingTransform` (or `useDemo().pendingTransform`)
   * here to render a built-in loading indicator inside the header while a
   * cross-demo transform swap is waiting on slow peers past the coordinator's
   * grace window. `undefined` (the default) keeps the indicator hidden; a
   * `string` or `null` fades it in and announces the target via a visually
   * hidden live region. The spinner stays mounted at all times so layout
   * doesn't reflow when it toggles.
   */
  pending?: string | null | undefined;
}

/**
 * Shared 48px-tall header used at the top of code blocks and demo code sections.
 * Renders the border chrome and an optional menu slot that overflows 8px past
 * the right edge of the container.
 */
export function CodeBlockHeader({ children, menu, roundedTop, pending }: CodeBlockHeaderProps) {
  const isPending = pending !== undefined;
  return (
    <div className={styles.header}>
      <div
        className={`${styles.headerContainer} ${roundedTop ? styles.headerContainerRoundedTop : ''}`}
      >
        <span
          className={styles.pendingIndicator}
          data-pending={isPending ? '' : undefined}
          aria-hidden={!isPending}
        >
          <PendingSpinner />
          <span className={styles.srOnly} role="status" aria-live="polite">
            {isPending ? `Switching to ${pending ?? 'original'}…` : ''}
          </span>
        </span>
        <div className={styles.tabContainer}>{children}</div>
        {menu}
      </div>
    </div>
  );
}

function PendingSpinner() {
  return (
    <svg className={styles.spinner} viewBox="0 0 16 16" aria-hidden="true" focusable="false">
      <circle cx="8" cy="8" r="6" />
    </svg>
  );
}

/**
 * A filename / static label rendered inside `<CodeBlockHeader>` when there
 * are no tabs. Matches the typography of the tab labels.
 */
export function CodeBlockHeaderLabel({ children }: { children: React.ReactNode }) {
  return <span className={styles.label}>{children}</span>;
}
DemoVariantBar.tsx
import * as React from 'react';
import { Select } from '@/components/Select';
import styles from './DemoVariantBar.module.css';

export interface DemoVariantBarProps {
  variants: { label: string; value: string }[];
  selectedVariant?: string;
  onVariantChange?: (value: string | null, anchorEl: HTMLElement | null) => void;
  disabled?: boolean;
}

/**
 * Variant selector pinned to the top-left of a demo section.
 * Renders nothing when there are fewer than two variants.
 */
export function DemoVariantBar({
  variants,
  selectedVariant,
  onVariantChange,
  disabled,
}: DemoVariantBarProps) {
  const rootRef = React.useRef<HTMLDivElement | null>(null);

  const handleVariantChange = React.useCallback(
    (value: string | null) => {
      onVariantChange?.(value, rootRef.current);
    },
    [onVariantChange],
  );

  if (variants.length < 2) {
    return null;
  }
  return (
    <div ref={rootRef} className={styles.variantBar}>
      <Select
        items={variants}
        value={selectedVariant}
        onValueChange={handleVariantChange}
        disabled={disabled}
        className={styles.variantSelect}
      />
    </div>
  );
}
DemoContent.module.css
.container {
  border: 1px solid #d0cdd7;
  border-radius: 8px;
}

.demoSection {
  position: relative;
  border-radius: 7px 7px 0 0;
}

.demoSurface {
  padding: 24px;
}

.codeSection {
  border-top: 1px solid #d0cdd7;
}

.code {
  padding: 10px 0;
}

.codeBlock {
  tab-size: 2;
  margin: 0;
  padding: 6px 0;
  overflow-x: auto;
}

/* Code element inside pre — block so frames stretch to the widest line */
.codeBlock :global(code) {
  display: block;
  min-width: fit-content;
}

.codeBlock :global(.frame) {
  display: block;
  padding: 0 12px;
}

.codeBlock :global(.frame[data-lined]) {
  display: block;
  white-space: normal;
  line-height: 0;
}

.codeBlock :global(.frame[data-lined] .line) {
  display: block;
  white-space: pre;
  line-height: initial;
}

/* Highlighted frames get rounded corners and background */
.codeBlock :global(.frame[data-frame-type='highlighted']),
.codeBlock :global(.frame[data-frame-type='highlighted-unfocused']) {
  background: #ebe4ff;
  border-radius: 8px;
  margin: 0 6px;
  padding: 0 6px;
}

/* Line-level highlight inside a frame (nested emphasis) */
.codeBlock :global(.line[data-hl]) {
  background: #ebe4ff;
  margin: 0 -6px;
  padding: 0 6px;
}

.codeBlock :global(mark) {
  background: #ebe4ff;
  border-radius: 4px;
}

.codeBlock :global(mark[data-hl]) {
  background: #e1d9ff;
}

.codeBlock :global(mark[data-hl='strong']) {
  background: #d4c8ff;
}

.codeBlock :global(.line[data-hl='strong']) {
  background: #e1d9ff;
  margin: 0 -6px;
  padding: 0 6px;
}

/* Only strong lines bordering a regular highlight line need to stack above
   it (so the regular line's extended background sits underneath the strong
   line's rounded corners). */
.codeBlock :global(.line[data-hl='strong'][data-hl-position='single']),
.codeBlock :global(.line[data-hl='strong'][data-hl-position='end']) {
  position: relative;
  z-index: 1;
}

/* Visually merge a regular highlighted line into an adjacent strong block by
   extending its background through the gap between lines. */
.codeBlock :global(.line[data-hl='']:has(+ .line[data-hl='strong'])) {
  padding-bottom: 6px;
  margin-bottom: -6px;
}

.codeBlock :global(.line[data-hl='strong'] + .line[data-hl='']) {
  padding-top: 6px;
  margin-top: -6px;
}

.codeBlock :global(.line[data-hl-position='single']) {
  border-radius: 8px;
}

.codeBlock :global(.line[data-hl-position='start']) {
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}

.codeBlock :global(.line[data-hl-position='end']) {
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}

.codeBlock :global(.line[data-hl-description])::after {
  content: attr(data-hl-description);
  float: right;
  background: #8145b5;
  border-radius: 8px;
  color: white;
  padding: 2px 4px;
  margin-right: -6px;
}

.codeBlock :global(.frame[data-frame-description])::before {
  content: attr(data-frame-description);
  float: right;
  background: #8145b5;
  border-radius: 8px;
  color: white;
  padding: 2px 4px;
}

/* Invisible in-flow anchor so native fragment links can scroll to a file slug
   and clear the sticky header — pure CSS, no scroll script. A `display: none`
   anchor has no layout box, so the browser cannot scroll to it. */
.fileRefs {
  display: block;
  height: 0;
  scroll-margin-top: 16px;
}
DemoContentLoading.module.css
/*
 * Only the initial variant's main file is visible; the rest is kept in the
 * DOM so search crawlers can index every file/variant the demo ships.
 * The visible filename is rendered by the surrounding CodeBlockHeader / Tabs.
 */

.variants,
.variants figure,
.variants dl,
.variants dd {
  margin: 0;
  padding: 0;
}

.variants > figure:first-of-type > dl > dd:first-of-type {
  padding: 10px 0;
}

.variants > figure > figcaption,
.variants > figure > dl > dt {
  display: none;
}

/* Hide extra files inside the initial variant (keep only the first dd). */
.variants > figure:first-of-type > dl > dd ~ dd {
  display: none;
}

/* Hide every variant beyond the initial one. */
.variants > figure ~ figure {
  display: none;
}
syntax.css
@import '@wooorm/starry-night/style/light' layer(starry-night);

:root {
  --color-docs-infra-syntax-number: #0550ae;
  --color-docs-infra-syntax-boolean: #0550ae;
  --color-docs-infra-syntax-nullish: #59636e;
  --color-docs-infra-syntax-attr-key: #0550ae;
  --color-docs-infra-syntax-attr-value: #0a3069;
  --color-docs-infra-syntax-attr-equals: #24292f;
  --color-docs-infra-syntax-data-attr: #0550ae;
  --color-docs-infra-syntax-css-property: #0550ae;
  --color-docs-infra-syntax-css-value: #0550ae;
  --color-docs-infra-syntax-this: #cf222e;
  --color-docs-infra-syntax-builtin-type: #0550ae;
  --color-docs-infra-syntax-jsx: #116329;
  --color-docs-infra-syntax-html-tag: #0550ae;
  --color-docs-infra-syntax-jsx-tag: #116329;
  --docs-infra-syntax-line-height: 18.5px;
}

.di-num {
  color: var(--color-docs-infra-syntax-number);
}

.di-bool {
  color: var(--color-docs-infra-syntax-boolean);
}

.di-n {
  color: var(--color-docs-infra-syntax-nullish);
}

.di-ak {
  color: var(--color-docs-infra-syntax-attr-key);
}

.di-av {
  color: var(--color-docs-infra-syntax-attr-value);
}

.di-ae {
  color: var(--color-docs-infra-syntax-attr-equals);
}

.di-da {
  color: var(--color-docs-infra-syntax-data-attr);
}

.di-cp {
  color: var(--color-docs-infra-syntax-css-property);
}

.di-cv {
  color: var(--color-docs-infra-syntax-css-value);
}

.di-this {
  color: var(--color-docs-infra-syntax-this);
}

.di-bt {
  color: var(--color-docs-infra-syntax-builtin-type);
}

.di-jsx {
  color: var(--color-docs-infra-syntax-jsx);
}

.di-ht {
  color: var(--color-docs-infra-syntax-html-tag);
}

.di-jt {
  color: var(--color-docs-infra-syntax-jsx-tag);
}

code[data-inline] .pl-smi {
  color: inherit;
}

/* ----------------------------------------------------------------------
 * Collapsed-lines placeholder
 *
 * `<span class="collapse" data-lines={n}>` is emitted wherever a source
 * transform deleted a run of lines (e.g. the type-stripping path
 * replaces type-only lines with empty strings, which the runtime then
 * folds into a single placeholder). `<Pre>` also injects a single
 * bridge `.collapse` placeholder into the shorter side of a variant
 * swap (see `useCode({ variantSwapDelay })`) so the line-count delta
 * between the outgoing and incoming variants animates instead of
 * snapping. While either swap kind is in flight, `<Pre>` sets
 * `data-transforming="expand"` or `data-transforming="collapse"` on
 * the rendered `<pre>` so the placeholder can animate in the correct
 * direction:
 *
 *   - `expand`   the OUTGOING tree's placeholders should expand back
 *                to their original height (the lines being kept by the
 *                new transform/variant are about to reappear). Fired
 *                during the pre-swap window for `transform → null`,
 *                the first half of `transform → transform`, and the
 *                pre-swap window of any variant swap.
 *   - `collapse` the INCOMING tree's placeholders should collapse from
 *                their original height down to 0 (the lines just
 *                removed by the new transform/variant). Fired during
 *                the post-swap window for `null → transform`, the
 *                second half of `transform → transform`, and the
 *                post-swap window of any variant swap.
 *
 * We use a CSS `@keyframes` rule (rather than a transition + the
 * `@starting-style` at-rule) because React typically reuses the same
 * `<span>` DOM node when a `.line` is replaced by a `.collapse` at the
 * same position — only the `class` and `data-*` attributes change. That
 * isn't an element insertion, so `@starting-style` would never fire;
 * but a new `animation-name` starts as soon as the rule begins applying
 * to the element, which is exactly what we want.
 *
 * `--docs-infra-syntax-line-height` should match the rendered line height
 * of the code block so the entry height lines up with the lines being
 * removed.
 * ------------------------------------------------------------------- */

pre .frame .collapse {
  display: block;
  overflow: hidden;
}

/* One empty `<span/>` per collapsed source line. Each child takes up
 * exactly one line-height, so the placeholder's intrinsic height is
 * `count * line-height` with no `data-lines` lookup, custom property,
 * or per-count fallback rules. Animating each child independently is
 * marginally more work than a single group animation but trades that
 * for portable behavior across every engine and removes the upper
 * bound on supported runs. */
pre .frame .collapse > span {
  display: block;
  height: 0;
  overflow: hidden;
}

/* Paused post-swap state (`data-transforming="expanded"`): the new
 * tree just committed but the active animation hasn't started yet.
 * Hold each bridge child at the expanded height so the structure
 * matches the start of the upcoming collapse animation. */
pre[data-transforming='expanded'] .frame .collapse > span {
  height: var(--docs-infra-syntax-line-height);
}

/* Active post-swap entry animation: the new tree just committed and
 * any `.collapse` placeholders it contains should collapse from their
 * children's expanded height down to 0. Gated on
 * `data-transforming="collapsing"` so initial renders and unrelated
 * re-renders stay silent. */
pre[data-transforming='collapsing'] .frame .collapse > span {
  animation: docs-infra-collapse-enter 350ms ease both;
}

@keyframes docs-infra-collapse-enter {
  from {
    height: var(--docs-infra-syntax-line-height);
  }
  to {
    height: 0;
  }
}

/* ----------------------------------------------------------------------
 * Pre-swap exit animation
 *
 * When `useCode({ transformDelay })` or `useCode({ variantSwapDelay })`
 * is set, switching away from the current transform/variant doesn't
 * commit the new tree synchronously — the hook first flips
 * `data-transforming="collapsed"` (paused) so the rendered `<pre>` can
 * settle into the animation start state, then flips to
 * `data-transforming="expanding"` once the next paint is ready and
 * runs the configured delay ms before dropping the attribute and
 * committing the new tree (which may then immediately get a
 * `data-transforming="expanded"` → `"collapsing"` handshake of its
 * own for the entry animation; the full swap thus runs
 * collapsed → expanding → swap → expanded → collapsing back-to-back).
 * During the expanding window, any `.collapse` placeholders in the
 * CURRENT tree run the exit animation below (each child 0 →
 * line-height) so the removed lines visually reappear before the real
 * `.line` spans replace them.
 * ------------------------------------------------------------------- */

pre[data-transforming='expanding'] .frame .collapse > span {
  animation: docs-infra-collapse-exit 350ms ease forwards;
}

@keyframes docs-infra-collapse-exit {
  from {
    height: 0;
  }
  to {
    height: var(--docs-infra-syntax-line-height);
  }
}

/* ----------------------------------------------------------------------
 * Transformer-added lines (single-line `data-expanding`)
 *
 * The symmetric case of the `.collapse` placeholder. Source transformers
 * that *insert* lines (e.g. the api-key injector) mark each new line
 * with `data-expanding=""` via paired `@expanding-start`/`@expanding-end`
 * markers in their returned comments map. Each line animates
 * independently — there is no equivalent of the multi-line placeholder
 * here, since deletions can be folded into a placeholder ahead of the
 * diff but insertions cannot be folded after one without losing the
 * highlighted content the viewer wants to reveal.
 *
 *   - During the post-swap `data-transforming="collapsing"` window
 *     (incoming tree just committed), each added line expands from
 *     0 to one line-height — the new lines visually slide in. The
 *     paired `data-transforming="expanded"` paused state holds each
 *     line at 0 so the start position is in place before the active
 *     animation begins.
 *   - During the pre-swap `data-transforming="expanding"` window
 *     (outgoing tree about to be replaced by one without these lines),
 *     each added line collapses from one line-height to 0 — the lines
 *     visually slide out before the new tree commits. The paired
 *     `data-transforming="collapsed"` paused state holds each line at
 *     its natural height (matching the inert base state) so the start
 *     position is in place before the active animation begins.
 *
 * Outside those windows the attribute is inert: the line renders at its
 * natural height like any other `.line`. This means initial loads
 * (where a transform may already be applied from URL/localStorage)
 * show the added lines at full height with no animation, which is the
 * correct behavior — there is no "before" state to animate from.
 * ------------------------------------------------------------------- */

pre .frame .line[data-expanding] {
  display: block;
  overflow: hidden;
}

/* Paused post-swap state (`data-transforming="expanded"`): the new
 * tree just committed but the active animation hasn't started yet.
 * Hold each added line at 0 so the start position matches the
 * upcoming entry animation. */
pre[data-transforming='expanded'] .frame .line[data-expanding] {
  height: 0;
}

pre[data-transforming='collapsing'] .frame .line[data-expanding] {
  animation: docs-infra-line-collapse-enter 350ms ease both;
}

@keyframes docs-infra-line-collapse-enter {
  from {
    height: 0;
  }
  to {
    height: var(--docs-infra-syntax-line-height);
  }
}

pre[data-transforming='expanding'] .frame .line[data-expanding] {
  animation: docs-infra-line-collapse-exit 350ms ease forwards;
}

@keyframes docs-infra-line-collapse-exit {
  from {
    height: var(--docs-infra-syntax-line-height);
  }
  to {
    height: 0;
  }
}
CodeActionsMenu.module.css
.menuTrigger {
  flex: 0 0 28px;
  box-sizing: border-box;
  /* The visible 20px ellipse keeps its position; 4px of padding overflows
     into surrounding space on each side to grow the tap target to 28px,
     and the negative margins absorb that padding so layout is unchanged. */
  margin-top: -1px;
  margin-right: -24px;
  margin-left: -4px;
  width: 28px;
  height: 49px;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  z-index: 10;
  color: #65636d;
  cursor: pointer;
}

.menuTriggerInner {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border: 1px solid transparent;
  border-radius: 0 4px 4px 0;
  background: transparent;
  transition:
    background-color 0.2s ease,
    border-color 0.2s ease;
}

.menuTrigger:hover:not(:disabled) .menuTriggerInner {
  background-color: #f2eff3;
  border-color: #d0cdd7;
}

.menuTrigger:active:not(:disabled) .menuTriggerInner,
.menuTrigger[data-popup-open] .menuTriggerInner {
  background-color: #eae7ef;
  border-color: #d0cdd7;
}

.menuTrigger:focus-visible {
  outline: 0;
}

.menuTrigger:focus-visible .menuTriggerInner {
  outline: 2px solid #8e4ec6;
  outline-offset: 0;
}

.menuTrigger:disabled {
  cursor: default;
  opacity: 0.6;
}

.menuPopup {
  box-sizing: border-box;
  min-width: 160px;
  padding: 4px;
  border-radius: 4px;
  background-color: canvas;
  outline: 1px solid #d0cdd7;
  box-shadow:
    0 10px 15px -3px #d0cdd7,
    0 4px 6px -4px #d0cdd7;
  color: #65636d;
  font-size: 0.875rem;
  transform-origin: var(--transform-origin);
  transition:
    transform 150ms,
    opacity 150ms;
}

.menuPopup[data-starting-style],
.menuPopup[data-ending-style] {
  opacity: 0;
  transform: scale(0.95);
}

.menuArrow {
  display: flex;
}

.menuArrow[data-side='top'] {
  bottom: -8px;
  rotate: 180deg;
}

.menuArrow[data-side='bottom'] {
  top: -8px;
  rotate: 0deg;
}

.menuArrow[data-side='left'] {
  right: -13px;
  rotate: 90deg;
}

.menuArrow[data-side='right'] {
  left: -13px;
  rotate: -90deg;
}

.arrowFill {
  fill: canvas;
}

.arrowOuterStroke {
  fill: #d0cdd7;
}

.arrowInnerStroke {
  fill: none;
}

.menuItem,
.menuItem:link,
.menuItem.menuItem:visited {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 6px;
  outline: 0;
  cursor: default;
  user-select: none;
  color: inherit;
  text-decoration: none;
}

.menuItem[data-highlighted] {
  background-color: #f2eff3;
}

.menuItemIcon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  color: #65636d;
}

.menuSeparator {
  height: 1px;
  margin: 4px 6px;
  background-color: #d0cdd7;
}

/* Inline mode — row of icon buttons in the header */
.inlineActions {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-right: 8px;
  height: 48px;
}

/* Stable wrapper around the inline JS/TS switch so the transform's
   scroll anchor has a DOM node to latch onto across the swap. */
.inlineSwitchAnchor {
  display: inline-flex;
  align-items: center;
}

.inlineIconButton,
.inlineIconButton:link,
.inlineIconButton.inlineIconButton:visited {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 4px;
  background: transparent;
  color: #65636d;
  cursor: pointer;
  text-decoration: none;
  transition:
    background-color 0.2s ease,
    border-color 0.2s ease;
}

.inlineIconButton:hover {
  background-color: #f2eff3;
  border-color: #d0cdd7;
}

.inlineIconButton:active {
  background-color: #eae7ef;
  border-color: #d0cdd7;
}

.inlineIconButton:focus-visible {
  outline: 2px solid #8e4ec6;
  outline-offset: 1px;
}
CodeBlockHeader.module.css
.header {
  border-bottom: 1px solid #d0cdd7;
  height: 48px;
  position: relative;
}

.headerContainer {
  position: absolute;
  width: 100%;
  display: flex;
}

/* 1px vertical lines that overlap the parent container's border so the
   tabContainer can extend `margin: -1px` past the rounded corners without
   exposing a gap. */
.headerContainer::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 1px;
  margin: -1px;
  background-color: #d0cdd7;
}

.headerContainer::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 1px;
  margin: -1px;
  background-color: #d0cdd7;
}

.headerContainerRoundedTop::before,
.headerContainerRoundedTop::after {
  top: 8px;
  margin-top: 0;
}

.tabContainer {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: -1px;
  margin-right: -1px;
  padding-bottom: 2px;
  overflow-x: auto;
}

/* Filename / label inside the header (when no tabs are rendered). */
.label {
  display: flex;
  align-items: center;
  height: 48px;
  padding: 0 12px;
  color: #65636d;
  font-size: 12px;
  font-family: var(--font-code);
}

/* Loading indicator for cross-demo transform swaps. Always mounted to keep
   layout stable; fades in only when the originating demo's
   `useCode().pendingTransform` is defined (i.e. the coordinator has crossed
   its grace window and is still waiting on slow peers), then fades back out
   once every peer acks or the safety-net timeout force-resolves.

   Sits to the left of the tabs, offset with negative margins so it overflows
   past the left chrome (mirroring how `<CodeActionsMenu>` overflows past the
   right chrome) and contributes zero width to the flex layout. */
.pendingIndicator {
  align-self: center;
  flex: 0 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  margin-left: -24px;
  margin-right: 8px;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 160ms ease 120ms,
    visibility 0s linear 280ms;
}

.pendingIndicator[data-pending] {
  opacity: 1;
  visibility: visible;
  transition:
    opacity 160ms ease,
    visibility 0s linear;
}

.spinner {
  width: 14px;
  height: 14px;
  color: #7f56d9;
}

/* Only animate when the indicator is actually visible to avoid burning CPU
   on a hidden, always-mounted spinner. */
.pendingIndicator[data-pending] .spinner {
  animation: spin 700ms linear infinite;
}

.spinner circle {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 40;
  stroke-dashoffset: 12;
  opacity: 0.85;
}

.srOnly {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
DemoVariantBar.module.css
.variantBar {
  display: flex;
}

/* Variant trigger inside the demo bar — strips its top and left borders so
   the demo container's border doubles as the selector's top and left edges.
   The top-left corner is rounded to match the container's outer rounding,
   and the bottom-right is rounded so the trigger reads as its own chip. */
.variantSelect {
  border-top: 0;
  border-left: 0;
  border-radius: 7px 0 8px;
  padding-top: 2px;
}

Demo Server Loaded

For more dynamic use cases, you can load code content from external sources or APIs at runtime:

Note

This example uses React Server Components (RSC) to load and parse files at request time instead of relying on the webpack loader for build-time precomputation. This approach is recommended when rendering based on dynamic routes (like app/components/[component].tsx) where the content isn't known at build time. In these scenarios, you'd typically use the <CodeHighlighter> component directly rather than the factory pattern with createDemo().

CheckboxBasic.tsx
import * as React from 'react';
import { Checkbox } from '@/components/Checkbox';

export function CheckboxBasic() {
  return (
    // @focus
    <Checkbox defaultChecked />
  );
}
import { createDemo } from './createDemo';
import { CheckboxBasic } from './CheckboxBasic';

export const DemoCheckboxBasic = createDemo(import.meta.url, CheckboxBasic, {
  skipPrecompute: true,
});

Client-Side Rendering

CodeHighlighter can also be used on the client side, allowing you to load and parse code dynamically without server-side rendering. This is useful for applications that fetch code from APIs or databases.

You can do so by using the CodeProvider component, which provides the necessary context for CodeHighlighter to function correctly on the client.

Controlled Code Scenarios

CodeHighlighter also supports controlled scenarios where you need to manage code state externally. This is useful for interactive demos where code changes affect other parts of your application or when you need to synchronize code across multiple components.

You can use the CodeControllerContext for this purpose, which provides a controlled environment for managing code state in interactive scenarios.

Authoring Recommendations

Component Name

Demos are exported as Demo${componentName}${demoName} e.g. DemoCheckboxBasic This makes it easy to import a demo by simply typing <DemoCheckbox, and your IDE should display a list of existing demos to auto-import.

Demo Titles

We recommend exporting a Title component attached within your createDemo() factory. This allows us to use an automatically generated title and slug from the URL of the demo index. This ensures that the link for the title is consistent with links to files within the demo itself.

e.g. ./app/components/checkbox/demos/advanced-keyboard/index.ts would generate a title of Advanced Keyboard and a slug of advanced-keyboard. The URL for this demo would be /components/checkbox#advanced-keyboard and a file within it could be /components/checkbox#advanced-keyboard:file.ts.

Also, when MDX is rendered in GitHub, <DemoCheckboxAdvancedKeyboard.Title /> will be visible on the page because it contains the dot. The import is also visible, so readers on GitHub will see this in the place of a demo:

import { DemoCheckboxAdvancedKeyboard } from './demos/advanced-keyboard';

<DemoCheckboxAdvancedKeyboard.Title />

Description of the demo.

If this convention isn't followed, URLs might deviate e.g. /components/checkbox#advanced-keyboard might not link to the correct demo.

// This is not recommended
import { DemoCheckboxAdvancedKeyboard } from './demos/advanced-keyboard'

### An Advanced Keyboard Demo

Description of the demo.

<DemoCheckboxAdvancedKeyboard />

This would result in the URL becoming /components/checkbox#an-advanced-keyboard-demo, and the file URL being /components/checkbox#advanced-keyboard:file.ts, which is not expected.

Descriptions

The description should be a short, concise explanation of what the demo does or why it shows a useful case. It is located directly in the component's docs because it can have rich contents like links, images, or other components. Try to avoid referring directly to the demo itself as when viewing the raw markdown, users won't see the code or renderings from the demo. Ideally, the reader can picture the demo in their mind without needing to see it.

Include a "See Demo" link after each demo component to allow users to navigate directly to the demo's source directory. This is especially useful when viewing the documentation in markdown editors or GitHub, where users can click the link to browse the demo files.

The link should point to the demo's directory using a relative path:

<DemoCheckboxBasic />

[See Demo](./demos/basic/)

This pattern makes it easy for developers to explore the demo's implementation, understand the file structure, and reference the source code when building their own components.

Separators

Use horizontal rules (---) to separate different sections of the demo. This allows the description of the previous demo to be visually distinct from the next demo.

import { DemoCheckboxBasic } from './demos/basic';

<DemoCheckboxBasic.Title />

Description of the basic demo.

<DemoCheckboxBasic />

[See Demo](./demos/basic/)

---

import { DemoCheckboxAdvanced } from './demos/second-demo';

<DemoCheckboxAdvanced.Title />

Description of the second demo.

<DemoCheckboxAdvanced />

[See Demo](./demos/second-demo/)

Within GitHub, it will display like this without rendering the demo and with See Demo underlined:

import { DemoCheckboxBasic } from './demos/basic';

<DemoCheckboxBasic.Title />

Description of the basic demo.

See Demo

---

import { DemoCheckboxAdvanced } from './demos/advanced';

<DemoCheckboxAdvanced.Title />

Description of the advanced demo.

See Demo

Tip

For Documentation Tooling: If you're building tooling to render these demos in a web interface, you can use a remark plugin to automatically remove the "See Demo" links and horizontal rule separators (---) from the rendered output, since the interactive demos provide their own navigation. See the transformMarkdownMetaLinks plugin documentation for implementation details.

Benchmarking

For performance benchmarks of the CodeHighlighter component, see the Benchmarking Code Highlighter page.

Build-Time vs Server Rendering vs Client Rendering

Note

The CodeControllerContext works with all three rendering methods.

When rendering a code block, the user should consider the following options based on their use case:

Use the factory pattern optimal performance:

Advantages:

  • ✓ Faster initial load times
  • ✓ Isomorphic rendering support
  • ✓ Automatic caching based on dependencies for each demo

Requirements:

  • Must use createDemo() in index.ts files
  • Must be in a demo directory structure

Server Rendering

Use direct CodeHighlighter for dynamic content:

Advantages:

  • ✓ Works with dynamic content
  • ✓ Flexible component structure
  • ✓ Can still benefit from the page level cache

Trade-offs:

  • × Slower initial rendering
  • × No per-demo build-time cache
  • × Can only be used within a Server Component

Client Rendering

Use CodeHighlighter on the client with CodeProvider:

Advantages:

  • ✓ Works with dynamic content fetched on the client
  • ✓ Doesn't require an API or server-side rendering
  • ✓ Can be used anywhere in the app
  • ✓ Flexible component structure

Trade-offs:

  • × Slower initial rendering
  • × Requires loading and highlighting functions to be bundled
  • x No automatic caching

Best Practices

  1. Use precompute for static content - Enables a per-demo cache for faster builds
  2. Implement proper loading states - Provide ContentLoading for quicker hydration
  3. Handle errors gracefully - Use ErrorHandler to display meaningful error messages
  4. Optimize highlight timing - Use highlightAfter: 'idle' for non-critical code blocks
  5. Group related variants - Keep related code variations together

Troubleshooting

Common Issues

Code not highlighting:

  • Ensure sourceParser is provided
  • Check that the code variant exists
  • Verify highlightAfter timing is appropriate

Loading states not showing:

  • Provide ContentLoading component
  • Use highlightAfter: 'stream' for loading states
  • Check fallbackUsesExtraFiles settings

Performance issues:

  • Use demo factory pattern for build-time optimization
  • Consider highlightAfter: 'idle' for non-critical code
  • Implement proper error boundaries
  • Remember: precomputation only works with createDemo() in index.ts files

Precomputation not working:

  • Ensure you're using createDemo() in an index.ts file
  • Verify the file is in the correct path pattern: './app/**/demos/*/index.ts'
  • Make sure the webpack loader is configured correctly

Variants not switching:

  • Verify variant names match between components and variants
  • Check that source transformers are configured correctly
  • Ensure controlled mode is set up properly if needed

Shape

CodeHighlighter

PropTypeDescription
name
string | undefined

Display name for the code example, used for identification and titles

Content
React.ComponentType<ContentProps<{}>>

Component to render the code content and preview

ContentLoading
| React.ComponentType<ContentLoadingProps<{}>>
| undefined

Component to show while code is being loaded or processed

code
Code | undefined

Static code content with variants and metadata

components
Components | undefined

React components for live preview alongside code

contentProps
{} | undefined

Additional props passed to the Content component

controlled
boolean | undefined

Enable controlled mode for external code state management

defaultVariant
string | undefined

Fallback variant when the requested variant is not available

deferParsing
'none' | 'json' | 'gzip' | undefined

Defer parsing and populating the AST into memory until the code is enhanced Applies only in production when RSC loading

enhanceAfter
| 'init'
| 'stream'
| 'hydration'
| 'idle'
| undefined

When to enhance the code display with interactivity

fallbackCollapsed
boolean | undefined

Paint only the collapsed window in the ContentLoading fallback and defer each file’s full fallback into the compressed payload. Shrinks the initial HTML of a collapsed block to its on-screen lines, but removes the hidden lines from the server-rendered markup — so it is only appropriate for content that will not be crawled (authenticated or internal pages). See the prop-compression pattern’s “Splitting the Fallback by Visibility”.

fallbackUsesAllVariants
boolean | undefined

Whether fallback content should include all variants

fallbackUsesExtraFiles
boolean | undefined

Whether fallback content should include extra files

fileName
string | undefined

Currently selected file name

forceClient
boolean | undefined

Force client-side rendering even when server rendering is available

globalsCode
(string | Code)[] | undefined

Global static code snippets to inject, typically for styling or tooling

highlightAfter
| 'init'
| 'stream'
| 'hydration'
| 'idle'
| undefined

When to perform syntax highlighting and code processing

initialVariant
string | undefined

Default variant to show on first load

language
string | undefined

Language for syntax highlighting (e.g., ‘tsx’, ‘css’). When provided, fileName is not required for parsing.

loadCodeMeta
LoadCodeMeta | undefined

Function to load code metadata from a URL

loadSource
LoadSource | undefined

Function to load raw source code and dependencies

loadVariantMeta
LoadVariantMeta | undefined

Function to load specific variant metadata

precompute
Code | undefined

Pre-computed code data from build-time optimization

slug
string | undefined

URL-friendly identifier for deep linking and navigation

sourceEnhancers
SourceEnhancers | undefined

Array of source enhancers that run after parsing to enhance the HAST tree

sourceParser
Promise<ParseSource> | undefined

Promise resolving to a source parser for syntax highlighting

sourceTransformers
SourceTransformers | undefined

Array of source transformers for code processing (e.g., TypeScript to JavaScript)

url
string | undefined

Source URL where the code content originates from

urlPrefix
{ from: string; to: string } | undefined

Optional URL-prefix rewrite forwarded to . Lets the demo factory translate local file:// URLs returned by loadSource into hosted URLs before they reach the client.

variant
string | undefined

Currently selected variant name

variantType
string | undefined

What type of variants are available (e.g., a type packageManager when variants npm and yarn are available)

variants
string[] | undefined

Static variant names that should be fetched at runtime

children
string | undefined

Raw code string for simple use cases

CodeHighlighter Types

These types are available by importing from @mui/internal-docs-infra/CodeHighlighter/types.

BaseContentLoadingProps
type BaseContentLoadingProps = {
  fileNames?: string[];
  source?: FallbackNode[];
  /**
   * Language hint for the rendered `source` (e.g. `'tsx'`, `'css'`). Derived
   * from the variant's explicit `language` when set, otherwise from the
   * selected file name's extension. Consumers typically forward this as a
   * `language-{language}` class on the fallback `<code>` element so it picks
   * up the same language-scoped styling as the post-load tree.
   */
  language?: string;
  extraSource?: Record<string, FallbackNode[]>;
  /** Display name for the code example, used for identification and titles */
  name?: string;
  /** URL-friendly identifier for deep linking and navigation */
  slug?: string;
  /** Source URL where the code content originates from */
  url?: string;
  extraVariants?: Record<string, ContentLoadingVariant>;
}
Code
type Code = { [key: string]: string | VariantCode | undefined }
CodeClientRenderingProps

Client-specific rendering props

type CodeClientRenderingProps = {
  /** The CodeContent component that renders the code display and syntax highlighting */
  children: React.ReactNode;
  /** Loading placeholder shown while code is being processed */
  fallback?: React.ReactNode;
  /** Skip showing fallback content entirely */
  skipFallback?: boolean;
}
CodeContentProps

Core code content and variant management props

type CodeContentProps = {
  /** Static code content with variants and metadata */
  code?: Code;
  /** React components for live preview alongside code */
  components?: Components;
  /** What type of variants are available (e.g., a type `packageManager` when variants `npm` and `yarn` are available) */
  variantType?: string;
  /** Static variant names that should be fetched at runtime */
  variants?: string[];
  /** Currently selected variant name */
  variant?: string;
  /** Currently selected file name */
  fileName?: string;
  /** Language for syntax highlighting (e.g., 'tsx', 'css'). When provided, fileName is not required for parsing. */
  language?: string;
  /** Default variant to show on first load */
  initialVariant?: string;
  /** Fallback variant when the requested variant is not available */
  defaultVariant?: string;
  /** Global static code snippets to inject, typically for styling or tooling */
  globalsCode?: (string | Code)[];
}
CodeFunctionProps

Function props for loading and transforming code

type CodeFunctionProps = {
  /** Function to load code metadata from a URL */
  loadCodeMeta?: LoadCodeMeta;
  /** Function to load specific variant metadata */
  loadVariantMeta?: LoadVariantMeta;
  /** Function to load raw source code and dependencies */
  loadSource?: LoadSource;
  /** Array of source transformers for code processing (e.g., TypeScript to JavaScript) */
  sourceTransformers?: SourceTransformers;
  /** Promise resolving to a source parser for syntax highlighting */
  sourceParser?: Promise<ParseSource>;
  /** Array of source enhancers that run after parsing to enhance the HAST tree */
  sourceEnhancers?: SourceEnhancers;
  /**
   * Optional URL-prefix rewrite forwarded to .
   * Lets the demo factory translate local `file://` URLs returned by
   * `loadSource` into hosted URLs before they reach the client.
   */
  urlPrefix?: { from: string; to: string };
}
CodeHighlighterBaseProps

Base props containing essential properties shared across CodeHighlighter components and helper functions. This serves as the foundation for other CodeHighlighter-related interfaces.

type CodeHighlighterBaseProps<T extends {}> = {
  /** Display name for the code example, used for identification and titles */
  name?: string;
  /** URL-friendly identifier for deep linking and navigation */
  slug?: string;
  /** Source URL where the code content originates from */
  url?: string;
  /** Static code content with variants and metadata */
  code?: Code;
  /** React components for live preview alongside code */
  components?: Components;
  /** What type of variants are available (e.g., a type `packageManager` when variants `npm` and `yarn` are available) */
  variantType?: string;
  /** Static variant names that should be fetched at runtime */
  variants?: string[];
  /** Currently selected variant name */
  variant?: string;
  /** Currently selected file name */
  fileName?: string;
  /** Language for syntax highlighting (e.g., 'tsx', 'css'). When provided, fileName is not required for parsing. */
  language?: string;
  /** Default variant to show on first load */
  initialVariant?: string;
  /** Fallback variant when the requested variant is not available */
  defaultVariant?: string;
  /** Global static code snippets to inject, typically for styling or tooling */
  globalsCode?: (string | Code)[];
  /** Pre-computed code data from build-time optimization */
  precompute?: Code;
  /** Whether fallback content should include extra files */
  fallbackUsesExtraFiles?: boolean;
  /** Whether fallback content should include all variants */
  fallbackUsesAllVariants?: boolean;
  /**
   * Paint only the collapsed window in the `ContentLoading` fallback and defer
   * each file's full fallback into the compressed payload. Shrinks the initial
   * HTML of a collapsed block to its on-screen lines, but removes the hidden
   * lines from the server-rendered markup — so it is **only** appropriate for
   * content that will not be crawled (authenticated or internal pages). See the
   * prop-compression pattern's "Splitting the Fallback by Visibility".
   * @default false
   */
  fallbackCollapsed?: boolean;
  /** Enable controlled mode for external code state management */
  controlled?: boolean;
  /** Raw code string for simple use cases */
  children?: string;
  /**
   * When to perform syntax highlighting and code processing
   * @default 'idle'
   */
  highlightAfter?: 'init' | 'stream' | 'hydration' | 'idle';
  /**
   * When to enhance the code display with interactivity
   * @default 'idle'
   */
  enhanceAfter?: 'init' | 'stream' | 'hydration' | 'idle';
  /** Force client-side rendering even when server rendering is available */
  forceClient?: boolean;
  /**
   * Defer parsing and populating the AST into memory until the code is enhanced
   * Applies only in production when RSC loading
   * @default 'gzip'
   */
  deferParsing?: 'none' | 'json' | 'gzip';
  /** Function to load code metadata from a URL */
  loadCodeMeta?: LoadCodeMeta;
  /** Function to load specific variant metadata */
  loadVariantMeta?: LoadVariantMeta;
  /** Function to load raw source code and dependencies */
  loadSource?: LoadSource;
  /** Array of source transformers for code processing (e.g., TypeScript to JavaScript) */
  sourceTransformers?: SourceTransformers;
  /** Promise resolving to a source parser for syntax highlighting */
  sourceParser?: Promise<ParseSource>;
  /** Array of source enhancers that run after parsing to enhance the HAST tree */
  sourceEnhancers?: SourceEnhancers;
  /**
   * Optional URL-prefix rewrite forwarded to .
   * Lets the demo factory translate local `file://` URLs returned by
   * `loadSource` into hosted URLs before they reach the client.
   */
  urlPrefix?: { from: string; to: string };
  /** Component to render the code content and preview */
  Content: React.ComponentType<ContentProps<T>>;
  /** Additional props passed to the Content component */
  contentProps?: T;
}
CodeHighlighterClientProps

Props for the client-side CodeHighlighter component. Used when rendering happens in the browser with lazy loading and interactive features.

type CodeHighlighterClientProps = {
  /**
   * When to perform syntax highlighting for performance optimization
   * @default 'hydration'
   */
  highlightAfter?: 'init' | 'hydration' | 'idle';
  enhanceAfter?: 'init' | 'hydration' | 'idle';
  /**
   * The variant/file fallbacks a `ContentLoading` component never renders,
   * consolidated into a single DEFLATE blob (see `compressResidualFallbacks`).
   * The rendered subset crosses plain on `ContentLoading` props; this carries
   * everything else compressed. Decompressed once on the client — using the
   * hoisted rendered text as its preset dictionary — and scattered back onto
   * `Code` before the content decodes. Absent when there is no residual worth
   * compressing.
   */
  residualFallbacks?: CompressedFallback;
  /** Display name for the code example, used for identification and titles */
  name?: string;
  /** URL-friendly identifier for deep linking and navigation */
  slug?: string;
  /** Source URL where the code content originates from */
  url?: string;
  /** Static code content with variants and metadata */
  code?: Code;
  /** React components for live preview alongside code */
  components?: Components;
  /** What type of variants are available (e.g., a type `packageManager` when variants `npm` and `yarn` are available) */
  variantType?: string;
  /** Static variant names that should be fetched at runtime */
  variants?: string[];
  /** Currently selected variant name */
  variant?: string;
  /** Currently selected file name */
  fileName?: string;
  /** Language for syntax highlighting (e.g., 'tsx', 'css'). When provided, fileName is not required for parsing. */
  language?: string;
  /** Default variant to show on first load */
  initialVariant?: string;
  /** Fallback variant when the requested variant is not available */
  defaultVariant?: string;
  /** Global static code snippets to inject, typically for styling or tooling */
  globalsCode?: (string | Code)[];
  /** Whether fallback content should include extra files */
  fallbackUsesExtraFiles?: boolean;
  /** Whether fallback content should include all variants */
  fallbackUsesAllVariants?: boolean;
  /** Pre-computed code data from build-time optimization */
  precompute?: Code;
  /**
   * Paint only the collapsed window in the `ContentLoading` fallback and defer
   * each file's full fallback into the compressed payload. Shrinks the initial
   * HTML of a collapsed block to its on-screen lines, but removes the hidden
   * lines from the server-rendered markup — so it is **only** appropriate for
   * content that will not be crawled (authenticated or internal pages). See the
   * prop-compression pattern's "Splitting the Fallback by Visibility".
   * @default false
   */
  fallbackCollapsed?: boolean;
  /** Enable controlled mode for external code state management */
  controlled?: boolean;
  /** Force client-side rendering even when server rendering is available */
  forceClient?: boolean;
  /**
   * Defer parsing and populating the AST into memory until the code is enhanced
   * Applies only in production when RSC loading
   * @default 'gzip'
   */
  deferParsing?: 'none' | 'json' | 'gzip';
  /** The CodeContent component that renders the code display and syntax highlighting */
  children: React.ReactNode;
  /** Loading placeholder shown while code is being processed */
  fallback?: React.ReactNode;
  /** Skip showing fallback content entirely */
  skipFallback?: boolean;
}
CodeHighlighterProps

Main props for the CodeHighlighter component. Supports both build-time precomputation and runtime code loading with extensive customization options. Generic type T allows for custom props to be passed to Content and ContentLoading components.

type CodeHighlighterProps<T extends {}> = {
  /** Component to show while code is being loaded or processed */
  ContentLoading?: React.ComponentType<ContentLoadingProps<T>>;
  /** Display name for the code example, used for identification and titles */
  name?: string;
  /** URL-friendly identifier for deep linking and navigation */
  slug?: string;
  /** Source URL where the code content originates from */
  url?: string;
  /** Static code content with variants and metadata */
  code?: Code;
  /** React components for live preview alongside code */
  components?: Components;
  /** What type of variants are available (e.g., a type `packageManager` when variants `npm` and `yarn` are available) */
  variantType?: string;
  /** Static variant names that should be fetched at runtime */
  variants?: string[];
  /** Currently selected variant name */
  variant?: string;
  /** Currently selected file name */
  fileName?: string;
  /** Language for syntax highlighting (e.g., 'tsx', 'css'). When provided, fileName is not required for parsing. */
  language?: string;
  /** Default variant to show on first load */
  initialVariant?: string;
  /** Fallback variant when the requested variant is not available */
  defaultVariant?: string;
  /** Global static code snippets to inject, typically for styling or tooling */
  globalsCode?: (string | Code)[];
  /** Pre-computed code data from build-time optimization */
  precompute?: Code;
  /** Whether fallback content should include extra files */
  fallbackUsesExtraFiles?: boolean;
  /** Whether fallback content should include all variants */
  fallbackUsesAllVariants?: boolean;
  /**
   * Paint only the collapsed window in the `ContentLoading` fallback and defer
   * each file's full fallback into the compressed payload. Shrinks the initial
   * HTML of a collapsed block to its on-screen lines, but removes the hidden
   * lines from the server-rendered markup — so it is **only** appropriate for
   * content that will not be crawled (authenticated or internal pages). See the
   * prop-compression pattern's "Splitting the Fallback by Visibility".
   * @default false
   */
  fallbackCollapsed?: boolean;
  /** Enable controlled mode for external code state management */
  controlled?: boolean;
  /** Raw code string for simple use cases */
  children?: string;
  /**
   * When to perform syntax highlighting and code processing
   * @default 'idle'
   */
  highlightAfter?: 'init' | 'stream' | 'hydration' | 'idle';
  /**
   * When to enhance the code display with interactivity
   * @default 'idle'
   */
  enhanceAfter?: 'init' | 'stream' | 'hydration' | 'idle';
  /** Force client-side rendering even when server rendering is available */
  forceClient?: boolean;
  /**
   * Defer parsing and populating the AST into memory until the code is enhanced
   * Applies only in production when RSC loading
   * @default 'gzip'
   */
  deferParsing?: 'none' | 'json' | 'gzip';
  /** Function to load code metadata from a URL */
  loadCodeMeta?: LoadCodeMeta;
  /** Function to load specific variant metadata */
  loadVariantMeta?: LoadVariantMeta;
  /** Function to load raw source code and dependencies */
  loadSource?: LoadSource;
  /** Array of source transformers for code processing (e.g., TypeScript to JavaScript) */
  sourceTransformers?: SourceTransformers;
  /** Promise resolving to a source parser for syntax highlighting */
  sourceParser?: Promise<ParseSource>;
  /** Array of source enhancers that run after parsing to enhance the HAST tree */
  sourceEnhancers?: SourceEnhancers;
  /**
   * Optional URL-prefix rewrite forwarded to .
   * Lets the demo factory translate local `file://` URLs returned by
   * `loadSource` into hosted URLs before they reach the client.
   */
  urlPrefix?: { from: string; to: string };
  /** Component to render the code content and preview */
  Content: React.ComponentType<ContentProps<T>>;
  /** Additional props passed to the Content component */
  contentProps?: T;
}
CodeIdentityProps

Basic identification and metadata props for code examples

type CodeIdentityProps = {
  /** Display name for the code example, used for identification and titles */
  name?: string;
  /** URL-friendly identifier for deep linking and navigation */
  slug?: string;
  /** Source URL where the code content originates from */
  url?: string;
}
CodeLoadingProps

Loading and processing configuration props

type CodeLoadingProps = {
  /** Pre-computed code data from build-time optimization */
  precompute?: Code;
  /** Whether fallback content should include extra files */
  fallbackUsesExtraFiles?: boolean;
  /** Whether fallback content should include all variants */
  fallbackUsesAllVariants?: boolean;
  /**
   * Paint only the collapsed window in the `ContentLoading` fallback and defer
   * each file's full fallback into the compressed payload. Shrinks the initial
   * HTML of a collapsed block to its on-screen lines, but removes the hidden
   * lines from the server-rendered markup — so it is **only** appropriate for
   * content that will not be crawled (authenticated or internal pages). See the
   * prop-compression pattern's "Splitting the Fallback by Visibility".
   * @default false
   */
  fallbackCollapsed?: boolean;
  /** Enable controlled mode for external code state management */
  controlled?: boolean;
  /** Raw code string for simple use cases */
  children?: string;
  /**
   * When to perform syntax highlighting and code processing
   * @default 'idle'
   */
  highlightAfter?: 'init' | 'stream' | 'hydration' | 'idle';
  /**
   * When to enhance the code display with interactivity
   * @default 'idle'
   */
  enhanceAfter?: 'init' | 'stream' | 'hydration' | 'idle';
  /** Force client-side rendering even when server rendering is available */
  forceClient?: boolean;
  /**
   * Defer parsing and populating the AST into memory until the code is enhanced
   * Applies only in production when RSC loading
   * @default 'gzip'
   */
  deferParsing?: 'none' | 'json' | 'gzip';
}
CodeRenderingProps

Component and rendering props

type CodeRenderingProps<T extends {}> = {
  /** Component to render the code content and preview */
  Content: React.ComponentType<ContentProps<T>>;
  /** Additional props passed to the Content component */
  contentProps?: T;
}
CollapseMap

Tracks comments that were collapsed onto a line when their original lines were deleted. Keyed by the line they collapsed onto; each entry records the original offset from the edit line so the collapse can be reversed.

type CollapseMap = { [key: number]: { offset: number; comments: string[] }[] }
Components
type Components = { [key: string]: React.ReactNode }
ContentLoadingProps
type ContentLoadingProps<T extends {}> = ContentLoadingVariant &
  CodeIdentityProps & { extraVariants?: Record<string, ContentLoadingVariant> } & T & {
    component: React.ReactNode;
    components?: Record<string, React.ReactNode>;
    initialFilename?: string;
    initialVariant?: string;
    fallbackCollapsed?: boolean;
  }
ContentLoadingVariant
type ContentLoadingVariant = {
  fileNames?: string[];
  source?: FallbackNode[];
  /**
   * Language hint for the rendered `source` (e.g. `'tsx'`, `'css'`). Derived
   * from the variant's explicit `language` when set, otherwise from the
   * selected file name's extension. Consumers typically forward this as a
   * `language-{language}` class on the fallback `<code>` element so it picks
   * up the same language-scoped styling as the post-load tree.
   */
  language?: string;
  extraSource?: Record<string, FallbackNode[]>;
}
ContentProps
type ContentProps<T extends {}> = CodeIdentityProps &
  Pick<CodeContentProps, 'code' | 'components' | 'variantType'> &
  T
ControlledCode
type ControlledCode = { [key: string]: ControlledVariantCode | null | undefined }
ControlledVariantCode
type ControlledVariantCode = {
  /** Name of the file (e.g., 'Button.tsx') */
  fileName?: string;
  /** Language for syntax highlighting (e.g., 'tsx', 'css'). When provided, fileName is not required. */
  language?: string;
  /** Flattened path for the file */
  path?: string;
  url?: string;
  source?: string | null;
  extraFiles?: ControlledVariantExtraFiles;
  filesOrder?: string[];
  comments?: SourceComments;
  collapseMap?: CollapseMap;
  totalLines?: number;
  emptyLines?: number[];
}
ControlledVariantExtraFiles
type ControlledVariantExtraFiles = {
  [fileName: string]: {
    source: string | null;
    comments?: SourceComments;
    collapseMap?: CollapseMap;
    totalLines?: number;
    emptyLines?: number[];
  };
}
ExternalImportItem
type ExternalImportItem = {
  name: string;
  type: 'named' | 'default' | 'namespace';
  isType?: boolean;
}
Externals
type Externals = { [key: string]: ExternalImportItem[] }
Fallbacks

Record of fileName → compact fallback extracted from variants. Used as the DEFLATE dictionary for hastCompressed decompression and as the visual fallback before full highlighting loads.

type Fallbacks = { [key: string]: FallbackNode[] }
HastRoot
type HastRoot = {
  data?: RootData & {
    totalLines?: number;
    focusedLines?: number;
    collapsible?: boolean;
    frameSize?: number;
    appliedEnhancers?: string[];
    transforms?: Transforms;
  };
}
LoadFallbackCodeOptions

Options for loading fallback code with various configuration flags

type LoadFallbackCodeOptions = {
  /** Flag to indicate if syntax highlighting should be performed */
  shouldHighlight?: boolean;
  /** Specific filename to initially display */
  initialFilename?: string;
  /** Array of global code to include (overrides LoadFileOptions.globalsCode with different type) */
  globalsCode?: (string | Code)[];
  /** Disable applying source transformers */
  disableTransforms?: boolean;
  /** Disable parsing source strings to AST */
  disableParsing?: boolean;
  /** Maximum recursion depth for loading nested extra files */
  maxDepth?: number;
  /** Set of already loaded file URLs to prevent circular dependencies */
  loadedFiles?: Set<string>;
  /**
   * Output format for the loaded file
   * @default 'hast'
   */
  output?: 'hast' | 'hastJson' | 'hastCompressed';
  /**
   * Optional URL-prefix rewrite applied to the loaded variant's `url` and any
   * string-form `extraFiles` entries. Useful for translating local `file://`
   * URLs (e.g. those returned by `loadServerCodeSource`) into hosted URLs (e.g.
   * `https://github.com/owner/repo/tree/<branch>/`) before they reach the
   * client.
   */
  urlPrefix?: { from: string; to: string };
  /** Function to load code metadata from a URL */
  loadCodeMeta?: LoadCodeMeta;
  /** Function to load specific variant metadata */
  loadVariantMeta?: LoadVariantMeta;
  /** Function to load raw source code and dependencies */
  loadSource?: LoadSource;
  /** Array of source transformers for code processing (e.g., TypeScript to JavaScript) */
  sourceTransformers?: SourceTransformers;
  /** Promise resolving to a source parser for syntax highlighting */
  sourceParser?: Promise<ParseSource>;
  /** Array of source enhancers that run after parsing to enhance the HAST tree */
  sourceEnhancers?: SourceEnhancers;
  /** Static variant names that should be fetched at runtime */
  variants?: string[];
  /** Whether fallback content should include extra files */
  fallbackUsesExtraFiles?: boolean;
  /** Whether fallback content should include all variants */
  fallbackUsesAllVariants?: boolean;
}
LoadFileOptions

Options for controlling file loading behavior

type LoadFileOptions = {
  /** Disable applying source transformers */
  disableTransforms?: boolean;
  /** Disable parsing source strings to AST */
  disableParsing?: boolean;
  /** Maximum recursion depth for loading nested extra files */
  maxDepth?: number;
  /** Set of already loaded file URLs to prevent circular dependencies */
  loadedFiles?: Set<string>;
  /** Side effects code to inject into extraFiles */
  globalsCode?: (string | VariantCode)[];
  /**
   * Output format for the loaded file
   * @default 'hast'
   */
  output?: 'hast' | 'hastJson' | 'hastCompressed';
  /**
   * Optional URL-prefix rewrite applied to the loaded variant's `url` and any
   * string-form `extraFiles` entries. Useful for translating local `file://`
   * URLs (e.g. those returned by `loadServerCodeSource`) into hosted URLs (e.g.
   * `https://github.com/owner/repo/tree/<branch>/`) before they reach the
   * client.
   */
  urlPrefix?: { from: string; to: string };
}
LoadVariantOptions

Options for the loadIsomorphicCodeVariant function, extending LoadFileOptions with required function dependencies

type LoadVariantOptions = {
  /** Disable applying source transformers */
  disableTransforms?: boolean;
  /** Disable parsing source strings to AST */
  disableParsing?: boolean;
  /** Maximum recursion depth for loading nested extra files */
  maxDepth?: number;
  /** Set of already loaded file URLs to prevent circular dependencies */
  loadedFiles?: Set<string>;
  /** Side effects code to inject into extraFiles */
  globalsCode?: (string | VariantCode)[];
  /**
   * Output format for the loaded file
   * @default 'hast'
   */
  output?: 'hast' | 'hastJson' | 'hastCompressed';
  /**
   * Optional URL-prefix rewrite applied to the loaded variant's `url` and any
   * string-form `extraFiles` entries. Useful for translating local `file://`
   * URLs (e.g. those returned by `loadServerCodeSource`) into hosted URLs (e.g.
   * `https://github.com/owner/repo/tree/<branch>/`) before they reach the
   * client.
   */
  urlPrefix?: { from: string; to: string };
  /** Promise resolving to a source parser for syntax highlighting */
  sourceParser?: Promise<ParseSource>;
  /** Function to load raw source code and dependencies */
  loadSource?: LoadSource;
  /** Function to load specific variant metadata */
  loadVariantMeta?: LoadVariantMeta;
  /** Array of source transformers for code processing (e.g., TypeScript to JavaScript) */
  sourceTransformers?: SourceTransformers;
  /** Array of source enhancers that run after parsing to enhance the HAST tree */
  sourceEnhancers?: SourceEnhancers;
}
SourceComments

Comments extracted from source code, keyed by line number. Each line number maps to an array of comment strings found on that line.

type SourceComments = { [key: number]: string[] }
SourceEnhancers

Array of source enhancer functions that run in order after parsing.

SourceTransformer
type SourceTransformer = { extensions: string[]; transformer: TransformSource }
SourceTransformers
Transforms

Records the transforms available for a source. Each entry can provide a jsondiffpatch delta (the patch to apply against the source’s parsed hast tree), an optional renamed fileName, and an optional comments map.

When comments is present, it represents the post-transform comment map (1-indexed by line number in the transformed source) and is used as-is by applyCodeTransformWithComments instead of auto-shifting the caller’s comments via the surviving dataLn mapping. Source transformers should only emit comments when they add or relocate lines; transforms that only wipe lines (replacing them with empty strings) are handled automatically.

hasDelta indicates whether the entry actually produced a code-level difference. When false (or omitted), the entry is rename-only — it carries a renamed fileName (and optionally comments) but the transformed source is structurally identical to the original. Rename-only entries are excluded from getAvailableTransforms (so the toggle stays hidden when nothing meaningful changes) but still apply the rename when the user has the matching transform preference selected.

hasCollapse indicates whether the inline delta (or the embedded delta matching this manifest entry) inserts a .collapse placeholder element. The runtime uses this flag to classify a transform swap as layout-affecting (phase 1: coordinated barrier so peers stay in lockstep) versus non-layout (phase 2: deferred until after phase 1 settles) without having to decompress the embedded hast payload on every selection change. Computed once during splitTransformsForEmbed and persisted on the manifest entry.

hasCollapseInFocus is the focus-region-aware counterpart: it is true only when at least one .collapse placeholder lands inside the source region that is visible when the surrounding code block is collapsed (the lines covered by data-frame-type'highlighted' | 'focus' | 'padding-top' | 'padding-bottom', falling back to the first frame when no emphasis frames exist — matching the runtime visibility rule in <Pre>). Consumers that opt into transformLayoutShift: 'focus' use this flag (instead of hasCollapse) while the block is collapsed, so a .collapse insertion outside the visible window doesn’t force a coordinated barrier swap that the user wouldn’t see anyway.

After serialization (output: 'hastJson' | 'hastCompressed'), the deltas are moved inside the source’s HastRoot.data.transforms so they ride along inside the compressed payload and never appear as plain JSON in the rendered HTML or in the demo module graph. In that mode the variant-level transforms field acts as a manifest — entries keep fileName, comments (when set), hasDelta, hasCollapse, and hasCollapseInFocus but delta is omitted. Consumers that need the delta should look it up inside the decompressed root.data.transforms.

type Transforms = {
  [key: string]: {
    delta?: Delta;
    fileName?: string;
    comments?: SourceComments;
    hasDelta?: boolean;
    hasCollapse?: boolean;
    hasCollapseInFocus?: boolean;
  };
}
VariantCode

Complete code variant definition with source, metadata, and configuration. Extends CodeMeta with all the information needed to display and process a code example.

type VariantCode = {
  /** Name of the file (e.g., 'Button.tsx') */
  fileName?: string;
  /** Language for syntax highlighting (e.g., 'tsx', 'css'). When provided, fileName is not required. */
  language?: string;
  /** Flattened path for the file */
  path?: string;
  /** Source URL where this variant originates */
  url?: string;
  /** Main source content for this variant */
  source?: VariantSource;
  /**
   * Compact fallback (highlighting spans removed) for the main source.
   * Converted from HAST via `hastToFallback` for smaller RSC payloads.
   * Used as the visual fallback before full highlighting loads, and its text
   * content (via `fallbackToText`) serves as the DEFLATE dictionary for
   * decompressing `hastCompressed` payloads.
   */
  fallback?: FallbackNode[];
  /** Additional files associated with this variant */
  extraFiles?: VariantExtraFiles;
  /** Prefix for metadata keys, e.g. /src */
  metadataPrefix?: string;
  /** External module dependencies */
  externals?: string[];
  /** The name of the export for this variant's entrypoint */
  namedExport?: string;
  /** Order in which files should be displayed */
  filesOrder?: string[];
  /** Transformations that can be applied to the source */
  transforms?: Transforms;
  /** Whether all files in the variant are explicitly listed */
  allFilesListed?: boolean;
  /** Skip generating source transformers for this variant */
  skipTransforms?: boolean;
  /** Comments extracted from source, stored when parsing is disabled for later use */
  comments?: SourceComments;
}
VariantExtraFiles

Additional files associated with a code variant. Can be either simple string content or objects with source and transformation options.

type VariantExtraFiles = {
  [fileName: string]:
    | string
    | {
        source?: VariantSource;
        fallback?: FallbackNode[];
        language?: string;
        transforms?: Transforms;
        skipTransforms?: boolean;
        metadata?: boolean;
        path?: string;
        relativeUrl?: string;
        comments?: SourceComments;
      };
}
VariantSource
type VariantSource = string | HastRoot | { hastJson: string } | { hastCompressed: string }
UseCodeFallbackResult
type UseCodeFallbackResult = {
  source?: HastRoot;
  fileNames?: string[];
  extraSource?: Record<string, HastRoot>;
  extraVariants?: Record<string, UseCodeFallbackVariantResult>;
  /**
   * `true` when the surrounding `CodeHighlighter` uses `fallbackCollapsed`, so
   * `source` is only the collapsed window. A `ContentLoading` should disable any
   * expand control while this is set — the hidden lines arrive with the full
   * content, not the fallback.
   */
  collapsed?: boolean;
}