Skip to main content

Components

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>

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>
Theme copied