Data
Card
Surface, subtle, ghost and interactive. Subtle cards are quieter: a fainter hairline and no shadow. Interactive cards lift a pixel on hover with a spring settle; render them as links or buttons. Flush cards add no padding: divided rows, or a panel the content pads. ItemRow is an item in such a card (icon tile, name, detail, controls) with ItemRowSkeleton for loading; CardRow is the setting-row inset alone. ClampedText cuts long prose to a number of rendered lines with Show more.
Live example
Import
Each family is its own entry point, so a page loads only what it uses.
import { Avatar, AvatarGroup } from "@nibapp/ui/components/avatar";import { Badge } from "@nibapp/ui/components/badge";import { Button, IconButton } from "@nibapp/ui/components/button";import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardRow, CardTitle } from "@nibapp/ui/components/card";import { ClampedText } from "@nibapp/ui/components/clamped-text";import { ItemRow, ItemRowSkeleton } from "@nibapp/ui/components/item-row";import { ProgressRing } from "@nibapp/ui/components/progress";import { Switch } from "@nibapp/ui/components/switch";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.
Avatar
Image avatar with deterministic tinted initials as fallback, plus optional presence dot.
| Prop | Type | Default | Description |
|---|---|---|---|
| shape | "circle" | "square" | "circle" | |
| name (required) | string | — | The person's (or a bot's) name: the accessible label, the initials and the tint. |
| src | string | undefined | — | |
| size | AvatarSize | — | |
| status | AvatarStatus | undefined | — | Presence dot. Announced in the accessible label, not just shown in color. |
| persona | Persona | — | Override the hashed persona tint. |
| fallback | ReactNode | — | Replace the initials, e.g. with an icon for a bot or a team. |
| description | string | — | Optional role/descriptor appended to the label, e.g. "CEO". |
Also takes the props of a <span> element, except children.
AvatarGroup
Overlapping stack of avatars. Set `--avatar-ring` to the surface color when the group sits on anything other than the page background (e.g. `[--avatar-ring:var(--surface)]` inside a Card).
| Prop | Type | Default | Description |
|---|---|---|---|
| size | AvatarSize | "md" | |
| max | number | — | Show at most this many avatars, then a "+N" chip. |
Also takes .
Badge
Small, calm label: subtle tint + matching foreground. Never loud.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "neutral" | "outline" | "success" | "warning" | "danger" | "info" | "neutral" |
|
| size | "sm" | "md" | "md" | |
| dot | boolean | false | Leading status dot. Pair with text — the dot alone never carries meaning. |
| icon | ReactNode | 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 .
Button
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "ghost" | "quiet" | "danger" | "danger-ghost" | "link" | "secondary" |
|
| size | "xs" | "sm" | "md" | "lg" | "md" | |
| block | boolean | — | |
| truncate | boolean | — | The button may shrink below its label's width; the label then truncates with an ellipsis. |
| wrap | boolean | — | 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. |
| loading | boolean | false | Shows a spinner, keeps the button's width, and blocks interaction. |
| leading | ReactNode | — | Icon rendered before the label. |
| trailing | ReactNode | — | Icon or hint (e.g. <Kbd>) rendered after the label. |
| disabledReason | string | 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).
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "xs" | "sm" | "md" | "lg" | "md" | |
| aria-label (required) | string | — | Required: icon-only controls must be named for assistive tech. |
| children (required) | ReactNode | — | |
| loading | boolean | false | |
| disabledReason | string | 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.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "surface" | "subtle" | "ghost" | "inset" | "interactive" | "surface" |
|
| size | "sm" | "md" | "flush" | "md" |
|
| divided | boolean | — | A hairline between the card's children: a list of rows (settings, accounts, devices). |
Also takes .
CardAction
Trailing slot in the header (a menu button, badge, …). Spans the title + description rows.
Also takes the props of a <div> element.
CardContent
Also takes the props of a <div> element.
CardDescription
Also takes the props of a <p> element.
CardFooter
| Prop | Type | Default | Description |
|---|---|---|---|
| divided | boolean | false | Hairline above the footer, for cards with a distinct action bar. |
Also takes .
CardHeader
Also takes the props of a <div> element.
CardRow
One padded row of a flush card (`size="flush"`, `divided` between rows): a setting, a field, a "Load more". The setting row's inset, 16 · 14; the row lays out its own content. An item with an icon, a name and a detail is an `ItemRow` (item-row.tsx).
Also takes the props of a <div> element.
CardTitle
Also takes the props of a <h3> element.
ClampedText
Text cut to `lines` rendered rows with a "Show more" toggle — prose of any script and length, Markdown included. Whether it overflows is measured from the layout (and again when the width changes), never guessed from the string; content that fits gets no toggle.
| Prop | Type | Default | Description |
|---|---|---|---|
| lines (required) | number | — | Rows shown before "Show more", at the content's own line height. |
| children (required) | ReactNode | — | |
| contentClassName | string | undefined | — | Classes of the clamped box itself (its type sets the line height the clamp counts in). |
| expanded | boolean | undefined | — | Controlled expansion, for a host that owns it (a long list that keeps every row's state). |
| onExpandedChange | ((expanded: boolean) => void) | undefined | — |
Also takes the props of a <div> element, except children.
ItemRow
One item in a flush, divided card (`Card size="flush" divided`): an icon tile, its name and a muted detail, its controls at the end. A device, a key, a member, an invoice. `CardRow` is the padding alone, for a row that lays out its own content.
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | ReactNode | — | Leading glyph in a tile; an icon in it is sized and muted for you. |
| title (required) | ReactNode | — | The item's name, with any badge after it. Wrap a long name in a `truncate` span. |
| detail | ReactNode | — | One muted line under the name: cut with an ellipsis when it doesn't fit, whole in a tooltip. |
| trailing | ReactNode | — | Its controls. On a narrow card they drop under the text rather than squeeze it. |
| children | ReactNode | — | More under the detail, wrapping: a status note, a reason. |
Also takes the props of a <div> element, except title.
ItemRowSkeleton
`ItemRow`s while a list loads: the tile, a name and a detail line, `rows` times.
| Prop | Type | Default | Description |
|---|---|---|---|
| rows | number | 1 |
ProgressRing
Tiny circular meter for token / context-window usage. Escalates at warning & danger thresholds.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "xl" | "md" |
|
| value (required) | number | — | |
| warningAt | number | 75 | Percentage at which the ring turns amber. |
| dangerAt | number | 90 | Percentage at which the ring turns red. |
| level | ProgressRingLevel | — | Force a level instead of deriving it from the thresholds. |
| showValue | boolean | false | Show the formatted value next to the ring — keeps the state legible without color. |
| aria-label (required) | string | — | Required accessible name, e.g. "Context window". |
Also takes ComponentProps<typeof Meter.Root>, except children and render.
Switch
Ink toggle with a springy thumb that stretches while pressed.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "md" | "md" |
|
| label | ReactNode | — | Visible label to the right of the switch. For settings rows prefer <Field orientation="horizontal">. |
| description | ReactNode | — |
Also takes the props of Base UI's Switch.Root, except children.