Noctis

Code

A fenced code block on the Noctis well surface: a header band carrying the language logo, a caption, and a copy button, over a horizontally scrollable code body. It owns its code typography — monospace family, size, line-height, and padding — so a plain <pre> reads as a properly-set block; syntax highlighting only colours the tokens. Opt into a tabbed group of samples by composing CodeBlock.Tabs.

Basic

A bare <CodeBlock> renders the default composition. Give it a label (a filename caption) or a language (used for the brand logo and, absent a label, the header text), and it draws the header band with a copy button over the code body. The copy button writes the rendered code's textContent to the clipboard unless you set copyText explicitly.

Save.tsx
import { Button } from "@stridge/noctis";

export function Save() {
    return <Button variant="primary">Save</Button>;
}

Language & copy text

Pass language alone for a header titled by the language name with its brand logo, and set copyText when the on-screen markup isn't the exact text to copy — for a highlighted <pre>, omitting it copies the visible code's text content, which is usually right. Override copyLabel / copiedLabel to translate the affordance.

Bash
pnpm add @stridge/noctis

Tabs

Tabbing is opt-in by composition: wrap one <CodeBlock> per sample in CodeBlock.Tabs and you get a tab strip — one tab per child, captioned and logo'd from each child's label (or language) — over a flush code body, with a single copy button that always copies whichever sample is showing. Name the strip with aria-label. The package-manager install block is the archetype.

npm install @stridge/noctis

Each tab can carry a language for its brand logo and a label for the caption, so a group can switch between a component, its styles, and its usage.

import { Button } from "@stridge/noctis";

export const Save = () => <Button>Save</Button>;

Anatomy

A bare <CodeBlock> renders the default composition; compose the parts for full control. Both the default block and the explicit CodeBlock.Tabs group own the copy context internally, so CodeBlock.Body / CodeBlock.CopyButton are composed within one of them, not standalone.

  • CodeBlock (Root) — the well-surface chassis. Props: label, language, icon (override the brand logo), copyText, copyLabel, copiedLabel. With children only, renders the header (or a floating copy button when there's no header) over the body.
  • CodeBlock.Header — the header band; holds the title, logo, and copy button.
  • CodeBlock.Title — the filename / language caption, treated as code rather than prose.
  • CodeBlock.CopyButton — the copy affordance; reads the copy target and labels from context.
  • CodeBlock.Body — the horizontally scrollable code body, pinned dir="ltr" so tokens never reorder on an RTL page, and registered as the copy target. Owns the monospace type metrics and padding.
  • CodeBlock.Tabs — the tab-group frame on the well surface (opt-in). Props: aria-label (names the strip), copyLabel / copiedLabel, className. Each child is a <CodeBlock> (or a raw <pre> carrying label / language).
  • CodeBlock.Tab — one language tab: a brand logo plus its label, addressed by value; the logo de-dims when the tab is active or hovered. Pass language, label, or an icon override.
  • CodeBlock.Panel — the active sample's panel, flattening a nested CodeBlock's frame so the sample sits flush.

The chassis stamps data-slot="noctis-code-block" on the frame and data-codeblock for the app stylesheet to attach a line-number gutter. The tab-group frame stamps noctis-code-tabs and the panel noctis-code-tabs-panel; the strip carries data-code-tabs-strip, each tab's logo data-code-tabs-logo, and the active tab and its panel carry Base UI's data-active.

Keyboard

The tab strip is fully keyboard-operable (a plain <CodeBlock> has no interactive chrome beyond its copy button).

KeyAction
TabMove focus onto the active tab in the strip.
/ Move between tabs and switch the shown sample; arrows mirror under RTL.
Home / EndJump to the first / last tab.

On surfaces

The same control re-tuned across the elevation scopes — the root canvas, an elevated panel, a menu, and a sunken well. It stays legible on every layer.

root
pnpm add @stridge/noctis
elevated
pnpm add @stridge/noctis
menu
pnpm add @stridge/noctis
sunken
pnpm add @stridge/noctis

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every code block in that region retunes — e.g. .docs { --noctis-code-block-header-height: 2.75rem; } raises every header band beneath it. Knobs that aren't minted are reached through the part's data-slot. See Customization for the full override ladder and Tokens for the whole graph.

Token

The tab strip carries its own metrics — the tab height, strip padding, and per-tab insets.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table; the Root carries the label / language / copyText chrome props while the parts forward their native element attributes. Expand a row for the full type and description.

CodeBlock.Header

Prop

CodeBlock.Title

Prop

CodeBlock.Body

Prop

AttributeDescription
data-slotMarks each rendered element with its slot for styling and testing hooks.
data-codeblockHook the app stylesheet reads to attach the line-number gutter to the highlighted lines.
data-activePresent on the active tab and its panel.

The tabbed parts — the opt-in CodeBlock.Tabs group and its Tabs and Panels.

CodeBlock.Tabs

Prop

CodeBlock.Tab

Prop

CodeBlock.Panel

Prop