Noctis

Button

Buttons trigger an action — submitting a form, opening a dialog, confirming a choice. Built on Base UI, with an emphasis level for every job and full keyboard and screen-reader support.

Variants

Seven emphasis levels. Use one neutral-white primary per view, reach for accent when a second action needs weight, and let secondary, outline, and ghost carry the rest; danger is reserved for destructive actions, and link sits inline with text.

Sizes

Four heights — extra-small through large — sharing one type and spacing rhythm.

With icons

Pair a leading or trailing glyph with the label. Icons are decorative; the label names the action.

Icon only

Square the button for a lone glyph. Always pass an aria-label — without visible text, assistive technology needs it to announce the action.

Loading

A loading button shows a centered spinner, blocks interaction, and keeps its size so the layout never jumps.

Disabled

A disabled button dims to the disabled opacity and ignores interaction.

Full width

Stretch the button to fill its container — common in narrow forms and on mobile.

For navigation, style a link with buttonVariants so it stays a real anchor while wearing the button's look; use the Button itself for in-place actions.

Scoped radius

Noctis is pill by default — controls go fully round — but RadiusScope is the escape hatch: wrap a region and every primitive inside re-rounds — sharp buttons for a dense dashboard, a subtler radius for a settings panel — without touching the app-wide setting. Surfaces stay capped, so cards never pill.

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
elevated
menu
sunken

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 button in that region retunes — e.g. .marketing { --noctis-button-border-radius: 9999px; } pills every button 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

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Button extends the Base UI Button props, so nativeButton and the native button attributes pass straight through; expand a row for the full type and description.

Prop

AttributeDescription
data-slotThe catalog slot that marks the rendered element as a Button for SLOTS.md and testing hooks.
data-buttonThe stable styling marker every `button.css` rule keys off — always present, independent of `data-slot`.
data-variantThe visual emphasis — `primary` | `accent` | `secondary` | `outline` | `ghost` | `danger` | `link`.
data-sizeThe size scale — `xs` | `sm` | `md` | `lg`; the generated layer keys the per-size internals off it.
data-icon-onlyPresent (`true`) when the button is squared for a single icon.
data-full-widthPresent (`true`) when the button stretches to its container's width.
data-loadingPresent (`true`) while loading — hides the content row in place behind the spinner overlay.
data-disabledPresent when the button is disabled (including while `loading`).