Components/DataTable

DataTable

A data table with semantic cells, column filtering, sorting, selection, and expandable rows.

VerifiedSince 0.3.4

Usage

Basic

Semantic type values provide numeric sorting, tag pills, and local calendar dates; filter: true adds the matching header filter.

Loading demo...

Row Selection

selectable adds a selection column; v-model:selected-keys syncs the selected rows.

Loading demo...

Skeleton Loading

loadingVariant="skeleton" draws placeholder rows while there are none; a refresh of existing rows shows only a bar under the header.

Loading demo...

Expandable Rows

expandable adds a leading toggle column; the #expanded slot renders the detail under a row.

Loading demo...

Records Table

A wide layout with a pinned header and footer, a frozen first column, and selection highlighting; cells compose TxTag, TxDotIndicator, and TxCellLink.

Loading demo...

Data Operations Panel

TxPagination pages the list, and TxSkeleton / TxLayoutSkeleton preview the loading state.

Loading demo...

Best Practices

  • Pass a stable rowKey for business lists; to keep selection across pages, drive selectedKeys with business ids, not default indexes.
  • For server-loaded lists, use loadingVariant="skeleton" with skeletonRows set to the page size; keep the default overlay for short local waits.
  • Give fixed columns numeric px width / minWidth, and keep one horizontal scroller: scrollX, or an outer overflow-x: auto.
  • A pinned header or footer needs maxHeight or a scrolling ancestor; don't nest the table in TxScroll's default mode, whose transform scrolling disables sticky.
  • Sort on comparable fields such as timestamps or ranks, never on formatted relative-time text.
  • Use filterOnClient=false for remote filtering and handle filterChange alongside pagination; controlled filter remains the parent's state.
  • A date column interprets YYYY-MM-DD as a local calendar day. A datetime column preserves the instant of timezone-qualified values; today ends at the next local midnight, including daylight-saving transitions.

API Reference

Props

NameTypeDefaultDescription
columnsDataTableColumn[][]Column config.
dataany[][]Data source.
rowKeykeyof T | (row: T, index: number) => string | numberindexUnique row key.
loadingbooleanfalseLoading state.
loadingVariant'overlay' | 'skeleton''overlay'overlay veils the table with a spinner; skeleton draws placeholder rows, or only a bar when rows exist.
skeletonRowsnumber5Placeholder rows before the first data lands; match the page size so nothing moves.
emptyTextstring'No data'Empty text.
stripedbooleanfalseZebra rows.
borderedbooleanfalseShow borders.
hoverbooleantrueHover highlight.
interactiveRowsbooleanfalseMakes rows focusable so Enter / Space fire rowClick; on automatically with a rowClick listener.
selectablebooleanfalseAdds a selection column.
selectedKeysArray<string | number>[]Keys of the selected rows.
expandablebooleanfalseAdds a leading toggle column; an expanded row renders a detail row beneath it.
defaultExpandedKeysArray<string | number>[]Initial expanded rows when uncontrolled; expandedKeys wins if both are passed.
expandedKeysArray<string | number>-Controlled expanded rows, bound with v-model:expanded-keys.
rowExpandable(row, index) => boolean-Per-row gate for expanding; a rejected row keeps an empty leading cell.
expandLabelstring'Expand row'Accessible name of a closed toggle.
collapseLabelstring'Collapse row'Accessible name of an open toggle.
defaultSort{ key: string; order: 'asc' | 'desc' | null }nullInitial sort when uncontrolled; pass either this or sort.
sort{ key: string; order: 'asc' | 'desc' | null } | null-Controlled sort; null means unsorted.
sortOnClientbooleantrueSorts locally; set false for remote sorting, which only emits.
sortCycle'tri' | 'bi''tri'tri: ascending → descending → unsorted; bi alternates and never unsorts.
tableLayout'auto' | 'fixed''auto'Native table-layout; use fixed when column widths must stay stable.
nowrapbooleanfalsePrevents wrapping in every header and cell.
maxHeightstring | number-Caps the height and scrolls the table vertically; what sticky rows stick to.
scrollXbooleanfalseScrolls horizontally inside the component; for wide tables with fixed columns.
stickyHeaderbooleanfalsePins the header row.
stickyFooterbooleanfalsePins the summary row.
rowClass(row, index) => string | string[] | Record<string, boolean>-Extra classes per row, such as a tint by state.
highlightSelectedbooleanfalseTints selected rows.
defaultFilterDataTableFilterState{}Initial filter values in uncontrolled mode.
filterDataTableFilterState-Controlled values by column key; bind with v-model:filter.
filterOnClientbooleantrueFilters rows locally; false delegates row retrieval to the caller.
autoStickyActionsbooleantrueDefaults action columns to the right fixed edge; an explicit column fixed takes precedence.

Events

EventPayloadDescription
update:selectedKeys(keys)Selection update.
selectionChange(keys)Selection change.
update:expandedKeys(keys)Expansion update; fires in controlled and uncontrolled modes.
expand({ row, index, expanded })A row was expanded or collapsed.
sortChange(sort)Sort change.
update:sort(sort)Sort change; fires in controlled and uncontrolled modes.
update:filter(filter)Filter values changed; fires in controlled and uncontrolled modes.
filterChange(filter)Filter changes for client or remote filtering.
rowClick({ row, index })Row click.

Slots

NameDescription
header-<columnKey>Custom header; receives { column, sorted, order, toggle }, where toggle advances the sort cycle.
cell-<columnKey>Custom cell; receives { row, column, value, index }.
filter-<columnKey>Custom filter; receives { column, filterValue, setFilter, clearFilter }.
expandedDetail of an expanded row, spanning every column; receives { row, index }.
footerThe whole summary row of your own <td>s, which can span columns. Any footer slot renders a <tfoot>.
footer-<columnKey>One summary cell per column; receives { column, data }. footer wins when both exist.
emptyEmpty state when there are no rows and loading=false.

DataTableColumn

FieldTypeDescription
keystringColumn key.
titlestringHeader title.
type'text' | 'number' | 'datetime' | 'date' | 'tag' | 'source' | 'actions'Semantic display, sort, and filter behavior; cell slots and format take precedence.
dataIndexstringData field.
widthstring | numberColumn width.
minWidthstring | numberMinimum column width.
maxWidthstring | numberMaximum column width.
autobooleanForces the column width to auto.
fixedboolean | 'left' | 'right'Sticky side; true means 'left'. Left offsets already include the toggle and selection columns.
nowrapbooleanPrevents wrapping in this column.
align'left' | 'center' | 'right'Alignment.
sortablebooleanSortable.
sorter(a, b) => numberCustom sorter.
filterbooleanAdds a type-aware header filter; off by default.
filterOptionsDataTableFilterOption[]Custom tag-filter options containing label, value, and optional tone.
format(value, row, index) => stringCell formatter.
headerClassstringHeader class.
cellClassstringCell class.

Overview

  • Passing sort or expandedKeys (even null or []) makes it controlled: the table only emits updates and renders what the parent sends back.
  • filter also makes filtering controlled. Tags accept one value or multiple values, numbers accept { min, max }, and dates accept today, 3d, 7d, 30d, or timestamp { start, end } values. Text filtering can be driven by a custom filter slot or controlled state.
  • Sortable headers carry scope="col" and aria-sort; click, Enter, and Space step through sortCycle.
  • On a partial selection the select-all box is indeterminate (aria-checked="mixed"); clicks in the selection and toggle cells never fire rowClick.
  • loading sets aria-busy on the <table>, and the empty state stays hidden while loading.
  • Placeholder rows are aria-hidden and as tall as a one-line row; the refresh bar holds still under reduced motion.
  • stickyHeader, stickyFooter, or maxHeight switches to border-collapse: separate. The last row has no bottom rule; the rule above a tfoot stays.

Technologies

  • The skeleton variant renders TxSkeleton. The on-demand style plugin loads its sheet; when importing styles by hand, add @talex-touch/tuffex/skeleton/style.css.
  • Semantic defaults, filtering, and sorting share the internal useDataTableData module. Filter panels use TxPopover; their teleported content keeps component-owned BEM styling.
  • Source: packages/tuffex/packages/components/src/data-table/.
查看源码
packages/tuffex/packages/components/src/data-table/index.ts

Customization

CSS variableUsed for
--tx-data-table-row-hover-bgRow hover fill.
--tx-data-table-row-selected-bgSelected-row fill under highlightSelected.
.records-shell {
  --tx-data-table-row-hover-bg: var(--tx-bui-hover);
  --tx-data-table-row-selected-bg: color-mix(in srgb, var(--tx-bui-accent) 7%, var(--tx-bui-surface));
}