Server shell + client leaf

Code Block

A compound multi-line code container with header, copy button and editor chrome.

App.tsx
import { AstralisProvider } from "astralis-ui";
import "astralis-ui/styles.css";

export function App({ children }) {
  return <AstralisProvider>{children}</AstralisProvider>;
}

Import#

import { CodeBlock } from "astralis-ui";
// CodeBlock.Root, .Header, .Title, .Control, .CopyTrigger,
// .WindowControls, .Content, .Code

Anatomy#

Root holds the source string via code and hands it to its parts during server render: Code renders it when given no children, and CopyTrigger — the compound's only client part — copies the rendered code to the clipboard. Header is an optional top row for Title, WindowControls (the macOS traffic lights) and a trailing Control slot; Content is the scrollable <pre> wrapping Code.

<CodeBlock.Root variant="solid" code={source}>
  <CodeBlock.Header>
    <CodeBlock.WindowControls />
    <CodeBlock.Title>App.tsx</CodeBlock.Title>
    <CodeBlock.Control>
      <CodeBlock.CopyTrigger />
    </CodeBlock.Control>
  </CodeBlock.Header>
  <CodeBlock.Content>
    <CodeBlock.Code />
  </CodeBlock.Content>
</CodeBlock.Root>

Variants#

The same three-variant family as Code; solid is the strongest surface — it tracks the active theme (dark block in dark mode, light in light) — and pairs well with WindowControls.

pnpm add astralis-ui  # subtle
pnpm add astralis-ui  # outline
pnpm add astralis-ui  # solid

Syntax highlighting#

Code Block renders plain text by itself — bring your own highlighter and pass its output as highlightedHtml on Code. The blocks on this very site are Shiki output rendered this way:

import { codeToHtml } from "shiki";

const html = await codeToHtml(source, { lang: "tsx", theme: "github-dark" });

<CodeBlock.Root variant="solid" code={source}>
  <CodeBlock.Content>
    <CodeBlock.Code highlightedHtml={html} />
  </CodeBlock.Content>
</CodeBlock.Root>

Keep passing the raw string as code on Root so CopyTrigger copies the unhighlighted source.

Props#

CodeBlock.Root:

PropTypeDefaultDescription
variant"subtle" | "solid" | "outline""subtle"Container style. Every variant follows the active light or dark theme.
size"sm" | "md" | "lg""md"Font size and padding of the content.
codestring—The source. Code renders it when given no children, and CopyTrigger copies it.

Parts#

Every part also takes its element's native attributes and className.

PropTypeDefaultDescription
CodeBlock.Headerdiv props—Optional top row for Title, WindowControls and a trailing Control slot.
CodeBlock.Titlespan props—File name or caption in the header.
CodeBlock.WindowControlsspan props—Three decorative window dots, hidden from assistive technology.
CodeBlock.Controldiv props—Trailing header slot, usually holding the CopyTrigger.
CodeBlock.CopyTriggercode?: string · children?: ReactNode | ((copied: boolean) => ReactNode)—Copies the Root's code, or its own code override. A render function replaces the default copy and check glyphs.
CodeBlock.Contentpre props—The scrollable pre element that wraps Code.
CodeBlock.CodehighlightedHtml?: string—Renders the Root's code as plain text, or your highlighter's HTML when highlightedHtml is set.