Patterns

Data table — people

UserCell (avatar with status, name, email) · role as a dot badge · RowActions: quick icons on hover, ⋯ for the rest, danger last.

KA
Karim Ahmed
karim@gulshanparking.com
—now
NJ
Nusrat Jahan
nusrat.j@gulshanparking.com
$182,4002 min ago
SI
Shahidul Islam
shahidul@gulshanparking.com
$96,35018 min ago
FA
Farhana Akter
farhana.akter@gmail.com
$74,120on shift
RH
Rafiq Hasan
rafiq.h@gulshanparking.com
$51,800yesterday
TS
Tania Sultana
tania@gulshanparking.com
—5 min ago
MR
Mahmud Rana
mahmud.rana@gmail.com
$38,9003 days ago
SC
Sabrina Chowdhury
sabrina.c@gulshanparking.com
$88,240now
1–8 of 8
1 / 1

Import#

Everything comes from the package root. The example above uses:

your-component.tsx
import {
  Avatar,
  Button,
  ConfirmDialog,
  Dialog,
  DialogBody,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  FormField,
  Input,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  type ColumnDef,
  DataTable,
  Money,
  RowActions,
  UserCell,
  StatusBadge,
} from "@waveinno/ui";

Props#

Read from the source of this version, so they match the code exactly.

<Avatar>

src/components/ui/avatar.tsx
PropTypeDefaultDescription
namerequiredstring—
srcstring | null—
sizekeyof typeof sizes"md"
statuskeyof typeof STATUS—
verifiedboolean—
ring"gradient"—
shape"circle" | "square""circle"
classNamestring—

<Button>

src/components/ui/button.tsx
PropTypeDefaultDescription
asChildbooleanfalse
loadingboolean—

Also takes ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>.

<ConfirmDialog>

src/components/ui/confirm-dialog.tsx
PropTypeDefaultDescription
openrequiredboolean—
onOpenChangerequired(open: boolean) => void—
titlerequiredReact.ReactNode—
descriptionReact.ReactNode—
itemsstring[]—What is affected: names shown in a list (first `previewCount`, then "+ n more").
previewCountnumber3
confirmWordstring—Require typing this word (e.g. "DELETE") before the button unlocks.
holdboolean | number—Press and hold the button to confirm; a number sets the hold in ms (default 1200).
confirmLabelrequiredReact.ReactNode—
cancelLabelReact.ReactNode"Cancel"
tone"danger" | "warning" | "primary""danger"
variant"center" | "split" | "banner" | "sheet""center"
iconReact.ReactNode—
onConfirmrequired() => void | Promise<void>—Runs on confirm; the button spins until it settles, the dialog closes on success.
labels{ typeToConfirm?: (word: string) => string; more?: (n: number) => string; hold?: string }—

<DialogBody>

src/components/ui/dialog.tsx

Also takes HTMLAttributes<HTMLDivElement> (passed through).

<DialogContent>

src/components/ui/dialog.tsx
PropTypeDefaultDescription
widthstring—Maximum width, e.g. "max-w-[560px]". The drawer is full width on phones.
sizekeyof typeof SIZES"md"Width preset; `width` wins when both are given.
resizablebooleantrueDrawer only: show the widen / full-width buttons. On by default.
hideCloseboolean—
variant"drawer" | "center""drawer"

Also takes ComponentPropsWithoutRef<typeof DialogPrimitive.Content>.

<DialogDescription>

src/components/ui/dialog.tsx

Also takes ComponentPropsWithoutRef<typeof DialogPrimitive.Description> (passed through).

<DialogFooter>

src/components/ui/dialog.tsx

Also takes HTMLAttributes<HTMLDivElement> (passed through).

<DialogHeader>

src/components/ui/dialog.tsx
PropTypeDefaultDescription
iconReact.ReactNode—A lucide icon (or any node) in a tinted tile beside the title.
eyebrowReact.ReactNode—One short line above the title: the object or step, e.g. "Rate plan" or "Step 2 of 3".

Also takes HTMLAttributes<HTMLDivElement>.

<DialogTitle>

src/components/ui/dialog.tsx

Also takes ComponentPropsWithoutRef<typeof DialogPrimitive.Title> (passed through).

<FormField>

src/components/ui/form-field.tsx
PropTypeDefaultDescription
labelReact.ReactNode—
htmlForstring—The control's id, so clicking the label focuses it.
requiredboolean—
hintReact.ReactNode—
errorReact.ReactNode—
warningReact.ReactNode—
successReact.ReactNode—
count{ value: number; max: number }—Character counter, e.g. { value: note.length, max: 240 }.
classNamestring—
childrenrequiredReact.ReactNode—

<Input>

src/components/ui/input.tsx
PropTypeDefaultDescription
state"default" | "error" | "warning" | "success""default"
leadingReact.ReactNode—Icon or text inside the box, before the value (a search icon, "৳", "+880").
trailingReact.ReactNode—After the value: a unit, a clear button, a status icon.

Also takes InputHTMLAttributes<HTMLInputElement>.

<SelectContent>

src/components/ui/select.tsx

Also takes ComponentPropsWithoutRef<typeof SelectPrimitive.Content> (passed through).

<SelectItem>

src/components/ui/select.tsx

Also takes ComponentPropsWithoutRef<typeof SelectPrimitive.Item> (passed through).

<SelectTrigger>

src/components/ui/select.tsx

Also takes ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> (passed through).

<DataTable>

src/components/patterns/data-table.tsx
PropTypeDefaultDescription
columnsrequiredColumnDef<T, unknown>[]—
datarequiredT[]—
getRowIdrequired(row: T) => string—
onRowClick(row: T) => void—
activeIdstring | null—Row currently shown in the drawer — highlighted, not navigated to.
searchPlaceholderstring"Search…"
pageSizenumber12
footerReact.ReactNode—Rendered in <tfoot>: totals turn a table into a report (§8).
emptyStateReact.ReactNode—
savedViewsSavedView[][]
toolbarExtraReact.ReactNode—
exportNamestring"waveinno-export"
defaultFiltersFilterStateEMPTY_FILTERSFilters to start with (e.g. from the URL).
onFiltersChange(filters: FilterState) => void—Told every time the filters change — save them, or send them to the API.
manualFilteringbooleanfalseThe server filters: rules are shown and reported but rows are not filtered here.
filterLabelsPartial<FilterLabels>—
variant"default" | "striped" | "bordered" | "cards" | "minimal""default"The look: `default` (hairline rows), `striped` (zebra, for long scans), `bordered` (a spreadsheet grid — the one for editing), `cards` (every row a floating card, for few, rich rows), `minimal` (no frame, inside cards and drawers).
onCellEdit(row: T, columnId: string, value: string) => void | Promise<void>—Save an edited cell. Return a promise to show a spinner; reject to keep the editor open.
onBulkEdit(rows: T[], columnId: string, value: string) => void | Promise<void>—Save one value into many rows (the bulk bar's Edit). Without it, the table calls `onCellEdit` once per selected row.
getRowLabel(row: T) => string—Name of a row in confirmations ("Delete these 3: …"). Defaults to the row id.
onBulkDelete(rows: T[]) => void | Promise<void>—Delete the selected rows (the bulk bar's Delete, after a confirmation).
bulkActions(rows: T[], clear: () => void) => React.ReactNode—Extra buttons in the bulk bar, e.g. Assign or Archive. `clear` empties the selection.
classNamestring—

<Money>

src/components/patterns/money.tsx
PropTypeDefaultDescription
valuerequirednumber | null | undefined—
compactboolean—
classNamestring—
decimalsnumber—Override the currency's decimals — whole-number prices read cleaner.
symbolstring—Escape hatch for a figure explicitly stated in another currency.

<RowActions>

src/components/patterns/data-table-cells.tsx
PropTypeDefaultDescription
actionsrequiredRowAction[]—
labelstring"Row actions"

<UserCell>

src/components/patterns/data-table-cells.tsx
PropTypeDefaultDescription
namerequiredstring—
secondaryReact.ReactNode—Second line: email, phone or role.
srcstring | null—
status"online" | "away" | "busy" | "offline"—
badge{ label: string; tone?: Tone }—
verifiedboolean—

<StatusBadge>

src/components/ui/badge.tsx
PropTypeDefaultDescription
labelrequiredstring—
toneTone"neutral"
variant"soft" | "solid" | "outline" | "dot" | "gradient" | "live"—
classNamestring—

Install#

If the project does not have the package yet, add it, then follow the setup for Next.js or Vite once.

$ npm install @waveinno/ui