Actions

Button

Primary actions are neutral ink; the accent is kept for focus, selection and progress. A slight press (none with reduced motion) and a loading state that stays focusable and shows its spinner only after a short delay. A disabled button can say why: it stays focusable and the reason is its tooltip.

Live example

Import

Each family is its own entry point, so a page loads only what it uses.

tsx
import { Button, IconButton } from "@nibapp/ui/components/button";import { Card } from "@nibapp/ui/components/card";import { Shortcut } from "@nibapp/ui/components/kbd";import { Tooltip } from "@nibapp/ui/components/tooltip";

Props

Each component's own props and variants, read from its source. What it also takes from an element or a Base UI part is named below its table.

Button

PropTypeDefaultDescription
variant"primary" | "secondary" | "ghost" | "quiet" | "danger" | "danger-ghost" | "link""secondary"
primary
Neutral ink: the main call to action. Actions are ink, never the accent.
secondary
Quiet surface with a hairline — the default for most actions.
ghost
No chrome until hovered — toolbars, inline actions.
quiet
Words that are also an action, in the text's own weight and laid out from the start, so they line up with the text around them: `xs` in a line (a header's crumbs, a title that renames), `sm` a toolbar's picker, `md` a row in a list or a popover ("Open settings", a sidebar's link).
danger
Destructive confirmation.
danger-ghost
Destructive but low emphasis.
link
Inline text action.
size"xs" | "sm" | "md" | "lg""md"
blockboolean—
truncateboolean—

The button may shrink below its label's width; the label then truncates with an ellipsis.

wrapboolean—

The label wraps onto more lines and the button grows, its `leading` icon on the first line: for words that are an action and may run long in another language (a tip). One line keeps the size.

loadingbooleanfalse

Shows a spinner, keeps the button's width, and blocks interaction.

leadingReactNode—

Icon rendered before the label.

trailingReactNode—

Icon or hint (e.g. <Kbd>) rendered after the label.

disabledReasonstring | undefined—

Disables the button and says why: the reason is its tooltip and its accessible description, and the button stays focusable (`aria-disabled`) so a keyboard reaches it.

Also takes .

IconButton

Square, icon-only button. Pair with <Tooltip> to surface the label visually (a `disabledReason` brings its own).

PropTypeDefaultDescription
size"xs" | "sm" | "md" | "lg""md"
aria-label (required)string—

Required: icon-only controls must be named for assistive tech.

children (required)ReactNode—
loadingbooleanfalse
disabledReasonstring | undefined—

Disables the button and says why, as Button's `disabledReason`.

Also takes the props of Base UI's Button, except aria-label and children.

Card

Container for grouped content. Compose with CardHeader / CardContent / CardFooter, or use `size="flush"` (with `divided` for rows) when the content brings its own padding. A kit part that draws a card on an element it already renders takes `cardStyles` instead.

PropTypeDefaultDescription
variant"surface" | "subtle" | "ghost" | "inset" | "interactive""surface"
surface
Default container: surface + hairline + whisper of shadow.
subtle
Quieter: a fainter hairline and no shadow, for lists and notes set into a page (a settings list, a usage summary, a notice). Usually `size="flush"`, `divided` for rows.
ghost
Structure without chrome — groups content on an existing surface.
inset
Sunken into the surface it sits on: a quoted message, a preview, a plan's step or a field's note inside a card or a drawer. Usually `size="sm"` or `flush` with the content's padding.
interactive
Clickable tile: lifts on hover. Render as <a>/<button> via `render`.
size"sm" | "md" | "flush""md"
flush
No padding or gap of its own: the card frames full-width rows (with `divided`), or one block the caller lays out and pads (a form, a stat, a checkbox).
dividedboolean—

A hairline between the card's children: a list of rows (settings, accounts, devices).

Also takes .

Shortcut

A key combination rendered as keycaps with platform-aware glyphs. The keycaps are always `aria-hidden`; at most one spoken form exists (the `spoken` words), never glyphs plus words.

PropTypeDefaultDescription
size"sm" | "md""md"
bareboolean—

`bare` drops the keycap chrome — for hints inside menus and buttons.

keys (required)readonly string[]—

Logical keys, e.g. `["mod", "k"]` → ⌘K on macOS, Ctrl K elsewhere.

spokenbooleanfalse

Announce the chord in words ("Command K"). Off by default: a shortcut inside a button, menu item or tooltip is announced through the control's `aria-keyshortcuts` (see `ariaKeyShortcuts`), so its name doesn't double up as "New document⌘N⌘N". Turn on for standalone hints and shortcut lists, where the keys are the content.

Also takes the props of a <span> element, except children.

Tooltip

Convenience wrapper: `<Tooltip content="Copy" shortcut={["mod","c"]}><IconButton …/></Tooltip>`. A `shortcut` also sets `aria-keyshortcuts` on the trigger; the keycaps in the popup are hidden.

PropTypeDefaultDescription
content (required)ReactNode—

Tooltip text.

actionstring—

The action this control triggers: its keys, from the host's keymap (`ShortcutProvider`), show after the text, and nothing shows when it has no binding. Prefer it to `shortcut`.

shortcutreadonly string[]—

Keys shown after the text when there is no `action` (keys the caller already read from the keymap).

children (required)ReactElement—

The trigger element; must accept a ref and DOM props (e.g. <IconButton>).

sideTooltipContentProps["side"]—
alignTooltipContentProps["align"]—
disabledboolean—