Data

Badge

Subtle tint, matching ink, never loud. Dots always travel with a word. Info is neutral and leads with its Info icon.

Live example

Import

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

tsx
import { Badge, CountBadge } from "@nibapp/ui/components/badge";import { Button } from "@nibapp/ui/components/button";

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.

Badge

Small, calm label: subtle tint + matching foreground. Never loud.

PropTypeDefaultDescription
variant"neutral" | "outline" | "success" | "warning" | "danger" | "info""neutral"
neutral
Quiet gray — metadata, counts, model names.
outline
Hairline only — for dense lists where fills get noisy.
info
Neutral wash + fg-muted ink, like every info surface; its `Info` icon is what says "info".
size"sm" | "md""md"
dotbooleanfalse

Leading status dot. Pair with text — the dot alone never carries meaning.

iconReactNode | false—

Leading icon. The info variant defaults to lucide `Info`: info is neutral, not the accent, so the icon is what tells it apart from a plain neutral badge. Pass your own icon to replace it, or `false` to hide it. A `dot` takes the icon's place.

Also takes .

CountBadge

Numeric pill for unread/pending counts. The number rolls softly when it changes.

PropTypeDefaultDescription
tone"neutral" | "ink" | "warning" | "danger""neutral"
neutral
Gray pill — unread counts in sidebars.
ink
Ink pill — draws the eye without color.
warning
Something waits on the person (needs-you counts).
danger
Errors or blocking items only.
count (required)number—
maxnumber99

Values above `max` render as `max+`.

showZerobooleanfalse

Render a `0` instead of nothing.

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

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 .