UnflowUI
Components

Data Table Cells

The pre-built cell renderer library for DataTable — CellText, CellCheckOption, CellActions, CellTags, CellAvatar, CellProgress, CellAmount, CellPaymentMethod, CellReviews, CellDate, CellDescription, CellFiles, and CellHeader.

Overview

Every Cell* component receives the exact same fixed shape — CellRenderProps<Row>: { row, rowIndex, value, formatted, column, tabIndex, loading }. There's no per-cell custom-props channel. Richer cell types get their configuration by having the column's accessor return a shaped value object — each cell normalizes that shape at the top of its render (a plain string/number/boolean value is always accepted as a fallback too).

{
  field: 'amount',
  accessor: (row) => ({ amount: row.total, currency: 'USD' }), // shaped value, matches CellAmountValue
  cell: CellAmount,
}

When loading is true, every cell renders its own shape-matched Skeleton rather than a generic placeholder box.

Import

import { CellText } from '@unflowio/ui/components/CellText';
// ...same pattern for every Cell* below

CellText

Primary + optional secondary line — the default text cell, and the composition base a few other cells (Payment Method) reuse.

Value fieldType
primaryReactNode
secondary?ReactNode

Ava Carter

Ava Carter

ava.carter@example.com

CellCheckOption

A checkbox/switch/radio for a boolean (or tri-state, checkbox-only) data field — distinct from DataTable's row-selection column. Omit onToggle for a read-only display.

Value fieldType
checkedboolean
indeterminate?boolean (checkbox only)
variant?'checkbox' | 'switch' | 'radio' (default 'checkbox')
onToggle?(next: boolean) => void
disabled?boolean

CellActions

Row-level actions — 'menu' (default) collapses behind a kebab trigger; 'inline' spreads each out as its own icon button.

Value fieldType
actionsActionsDropdownItem[] ({ label, icon?, onClick?, disabled? })
variant?'menu' | 'inline'

CellTags

Categorical chips with "+N" overflow.

Value fieldType
tags{ label, startIcon?, endIcon?, variant? }[]
max?number (default 2)

Remote

Team lead

CellAvatar

A single avatar, avatar + name, or a group of avatars — whichever the value asks for. A plain string value is treated as name.

Value fieldType
name?string
src?string
status?IAvatar['status']
label?string — shows avatar + name via UserTag
group?IAvatar[] — renders via AvatarGroup instead

Ava Carter

CellProgress

A thin wrapper over Progress — always rendered as a linear bar (the circular type isn't exposed here; this cell is one fixed layout).

Value fieldType
valuenumber
max?number
status?'success' | 'error'

62%

CellAmount

A formatted monetary value (via Intl.NumberFormat) with an optional delta chip and tooltip.

Value fieldType
amountnumber
currency?string (ISO 4217)
locale?string
delta?{ label, direction?: 'up' | 'down' }
tooltip?string
$1,240.50
$1,240.50

+12%

CellPaymentMethod

A card-brand icon (reuses the same brand→icon lookup CardInput uses) + label/subtitle.

Value fieldType
brand?string (a credit-card-type brand id, e.g. 'visa')
labelstring
subtitle?string

•••• 4242

Expires 08/27

•••• 8890

CellReviews

A read-only Rating plus an optional review count.

Value fieldType
valuenumber
max?number
count?number
(128)
(12)

CellDate

A formatted date, or a date range when endDate is provided. Display-only — editing isn't implemented yet (it will reuse the existing DatePicker family when it lands).

Value fieldType
dateDate | string | number
endDate?Date | string | number
formatOptions?Intl.DateTimeFormatOptions (default { dateStyle: 'medium' })
locale?string

Mar 1, 2026

Mar 1, 2026 – Mar 16, 2026

CellDescription

Long-form text, clamped to a fixed number of lines with a click-to-expand popover.

Value fieldType
textstring
lines?number (default 3)

CellFiles

A file/attachment list — icon-type mapping (shared with Upload) + filename + size + download action, collapsing into overflow for multiple files, with an async "uploading" sub-state.

Value fieldType
files{ name, size?, mimeType?, url?, status?: 'uploading' | 'error' | 'done' }[]
max?number (default 1)

invoice.pdf

239 KB

receipt.png

80 KB

CellHeader

Not a data cell — the composed header-cell content (checkbox + startIcon + label + sort indicator + info tooltip + count badge), meant to be mounted as a dumb TableHead's children rather than baked into the primitive itself:

<TableHead>
  <CellHeader
    label="Amount"
    sort={{ direction: sortDirection, onToggle: handleSort }}
    description="Total invoice amount, including tax"
  />
</TableHead>

DataTable already renders this for every column header automatically — you'd reach for CellHeader directly only when building a fully custom toolbar/header outside DataTable.