Core
Import from astro-pigment/components:
Layout
Main page shell. Renders sticky header with navigation, both sidebar slots, content area, footer, and code copy buttons. Includes ThemeToggle, ThemeScript, CodeBlockWrapper, and Search (when search: true, the default) automatically.
---
import { Layout } from "astro-pigment/components";
---
<Layout
title="Page Title"
navLinks={[
{ href: "", label: "Home" },
{ href: "api", label: "API" },
]}
>
<MyLogo slot="logo" />
<meta slot="head-extra" name="robots" content="noindex" />
<TableOfContents slot="sidebar-right" headings={headings} />
<article class="prose"><slot /></article>
<span slot="footer-extra">& Additional Credit</span>
</Layout>
Props: title (required), navLinks? (array of { href, label, attrs? }, where attrs is spread onto the rendered <a>), alternate? (array of { type, title, href } — renders <link rel="alternate"> tags in <head> plus a visually-hidden hint at the top of main content when a text/markdown entry is present).
Slots: default, sidebar, sidebar-right, logo, head-extra, footer-extra. Each sidebar is rendered only when its slot produces content, so a conditionally-passed sidebar ({cond && <Toc slot="sidebar" />}) collapses the column when the condition is false.
Below the laptop breakpoint the rails collapse into popovers. Layout scans the rendered sidebars for those popovers and renders their triggers as one floating ButtonGroup in the bottom-right corner — a hamburger for the menu, a dotted-list icon for the table of contents, or just the one that exists.
TableOfContents
Scroll-spy outline plus its mobile popover, both rendered from a single component. Goes in the sidebar-right slot — the outline owns the right rail, and the left one is reserved for navigation between pages. Layout supplies the popover’s floating trigger.
---
import { TableOfContents } from "astro-pigment/components";
const headings = await getHeadings(); // from Astro content render
---
<TableOfContents slot="sidebar-right" headings={headings} />
Default itemsSelector is "#content :is(h2, h3)[id]", targeting the id="content" article injected by the default page. Pass a custom selector if your layout differs:
<TableOfContents
slot="sidebar-right"
headings={headings}
itemsSelector="#my-content :is(h2, h3)[id]"
/>
Button
Styled <button> with an optional square prop for icon-only buttons.
---
import { Button } from "astro-pigment/components";
---
<Button>Click me</Button>
<Button square aria-label="Settings"><Icon name="hamburger" /></Button>
ButtonGroup
Joins adjacent Buttons into one segmented control: shared borders collapse and only the outer corners stay rounded. Pass aria-label to name the group.
---
import { Button, ButtonGroup, Icon } from "astro-pigment/components";
---
<ButtonGroup aria-label="Page actions">
<Button square aria-label="Copy page"><Icon name="copy" /></Button>
<Button square aria-label="View as markdown"><Icon name="markdown" /></Button>
</ButtonGroup>
Icon
Built-in SVG icons: check, chevron-left, close, copy, github, hamburger, markdown, search, toc, x. Use name="custom" with a slot for your own SVG.
---
import { Icon } from "astro-pigment/components";
---
<Icon name="github" />
<Icon name="github" size={32} />
<Icon name="custom" label="Mastodon">
<svg viewBox="0 0 24 24"><path d="..."></path></svg>
</Icon>
Footer
Site footer with license, GitHub, and author links. Read from the virtual config automatically. Renders credits from config as & Name links after the author. Has an extra slot for additional content beyond config-driven credits. Included in Layout by default.
---
import { Footer } from "astro-pigment/components";
---
<Footer />
ThemeToggle
Three-state theme switcher (auto/light/dark) with sun/moon/split icons.
---
import { ThemeToggle } from "astro-pigment/components";
---
<ThemeToggle />
ThemeScript
Inline script that prevents FOUC by setting data-theme before first paint. Included in Layout automatically.
ThemePicker
Floating hue + saturation picker for dialling in theme colors interactively. Layout renders it when the integration’s themePicker: true is set, so you only import it directly in a custom layout. Closing it copies { hue, saturation } to the clipboard — put those in theme config and drop the flag. ThemePickerScript is the inline script applying the picked values before paint; Layout includes it alongside the picker.
---
import { ThemePicker } from "astro-pigment/components";
---
<ThemePicker />
CodeBlockWrapper
Adds copy-to-clipboard buttons to all .prose pre blocks. Included in Layout automatically.
InstallPackage
Tabbed package manager switcher (pnpm/npm/yarn/bun). Selection persists to localStorage.
---
import { InstallPackage } from "astro-pigment/components";
---
<InstallPackage pkg="nanotags nanostores" />
<InstallPackage pkg="typescript" dev />
PrevNextNav
Previous/next page navigation links.
---
import { PrevNextNav } from "astro-pigment/components";
---
<PrevNextNav
prev={{ title: "Getting Started", href: "/getting-started" }}
next={{ title: "API Reference", href: "/api" }}
/>
PageHeading
Heading row with an optional “view as markdown” icon link. Omit href to hide the icon on pages without a .md twin.
---
import { PageHeading } from "astro-pigment/components";
import { getMarkdownAlternate } from "astro-pigment/utils/urls";
const alt = getMarkdownAlternate("api"); // { type, title, href: "/api.md" }
---
<PageHeading title="API Reference" href={alt.href} />
Props: title (required), href?, back? ({ href, label }), class?.
Pair with Layout’s alternate prop so the same URL is announced in <head> and (visually-hidden) at the top of main content:
---
import { Layout, PageHeading } from "astro-pigment/components";
import { getMarkdownAlternate } from "astro-pigment/utils/urls";
const alt = getMarkdownAlternate("api");
---
<Layout title="API Reference" alternate={[alt]}>
<PageHeading title="API Reference" href={alt.href} />
<article class="prose"><slot /></article>
</Layout>
Playground
Import from astro-pigment/components/playground:
CodeEditor
CodeMirror 6 editor with Catppuccin themes that sync with dark mode. Supports JavaScript, HTML, CSS, and JSON.
---
import { CodeEditor } from "astro-pigment/components/playground";
---
<CodeEditor lang="javascript" />
LivePreview
Sandboxed iframe execution. Captures console output and posts it back to the parent.
---
import { LivePreview } from "astro-pigment/components/playground";
---
<LivePreview />
CodeExample
Full interactive playground: tabbed editor + live preview + collapsible logs.
---
import { CodeExample } from "astro-pigment/components/playground";
const files = [
{ name: "index.html", type: "html", lang: "html", content: "<h1>Hello</h1>" },
{ name: "app.js", type: "javascript", lang: "javascript", content: "console.log('hi')" },
];
---
<CodeExample files={files} />
CodePanels
Multiple code snippets with Shiki highlighting and tab switching.
---
import { CodePanels } from "astro-pigment/components/playground";
const items = [
{ id: "pnpm", content: "pnpm add my-lib" },
{ id: "npm", content: "npm install my-lib" },
];
---
<CodePanels items={items} defaultValue="pnpm" lang="shellscript" />
ResizablePanes / ResizablePane
Draggable split-pane layout with keyboard support. Supports horizontal and vertical directions.
---
import { ResizablePanes, ResizablePane } from "astro-pigment/components/playground";
---
<ResizablePanes direction="horizontal">
<ResizablePane>Left content</ResizablePane>
<ResizablePane>Right content</ResizablePane>
</ResizablePanes>
CollapsiblePane
Expandable/collapsible section with an optional resize handle.
---
import { CollapsiblePane } from "astro-pigment/components/playground";
---
<CollapsiblePane expanded expandedSize={30}>
<span slot="header">Details</span>
<p>Collapsible content here</p>
</CollapsiblePane>
Tabs / Tab
Accessible tabs with roving focus, scroll arrows for overflow, and keyboard navigation.
---
import { Tabs, Tab } from "astro-pigment/components/playground";
---
<Tabs value="one">
<Tab value="one">First</Tab>
<Tab value="two">Second</Tab>
<Tab value="three">Third</Tab>
</Tabs>