Code Block
A compound multi-line code container with header, copy button and editor chrome.
import { AstralisProvider } from "astralis-ui";
import "astralis-ui/styles.css";
export function App({ children }) {
return <AstralisProvider>{children}</AstralisProvider>;
}"use client";
import { Box, CodeBlock } from "astralis-ui";
const example = `import { AstralisProvider } from "astralis-ui";
import "astralis-ui/styles.css";
export function App({ children }) {
return <AstralisProvider>{children}</AstralisProvider>;
}`;
export function CodeBlockDemo() {
return (
<Box w="full">
<CodeBlock.Root variant="solid" code={example}>
<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>
</Box>
);
}Import#
import { CodeBlock } from "astralis-ui";
// CodeBlock.Root, .Header, .Title, .Control, .CopyTrigger,
// .WindowControls, .Content, .CodeAnatomy#
Root holds the source string via code and provides it to the parts
through context: Code renders it when given no children, and CopyTrigger
copies it 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 # subtlepnpm add astralis-ui # outlinepnpm add astralis-ui # solid"use client";
import { CodeBlock, VStack } from "astralis-ui";
const variants = ["subtle", "outline", "solid"] as const;
export function CodeBlockVariants() {
return (
<VStack gap="4" alignItems="stretch" w="full" maxW="md">
{variants.map((variant) => (
<CodeBlock.Root key={variant} variant={variant} size="sm" code={`pnpm add astralis-ui # ${variant}`}>
<CodeBlock.Content>
<CodeBlock.Code />
</CodeBlock.Content>
</CodeBlock.Root>
))}
</VStack>
);
}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:
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "subtle" | "solid" | "outline" | "subtle" | Container style; all variants track the active theme. |
size | "sm" | "md" | "lg" | "md" | Font size and padding step for Content. |
code | string | — | The source string; rendered by Code and copied by CopyTrigger. |
CodeBlock.Code:
| Prop | Type | Default | Description |
|---|---|---|---|
highlightedHtml | string | — | Pre-tokenized HTML from your highlighter; replaces children and the context code. |
CodeBlock.CopyTrigger additionally takes code: string to override what is
copied, and its children may be a (copied: boolean) => ReactNode render
function to replace the default copy/check glyphs. Every part accepts its
native HTML attributes and className.