Data Table
A data-driven table component that renders rows from a JavaScript array. Declarative column definitions via `arc-column` children control which fields appear, their headers, widths, and sort behavior. Built-in support for column sorting, row selection with checkboxes, and an empty-state fallback.
<arc-data-table> Overview
Guidelines
When to use
- Use DataTable when your data is an array of objects with consistent keys
- Mark only the columns that benefit from sorting as sortable — not every column needs it
- Provide meaningful column labels that describe the data clearly
- Use the selectable attribute when users need to perform bulk actions on rows
- Set explicit column widths on columns that should remain fixed (e.g. status badges)
- Listen to arc-sort events to implement server-side sorting for large datasets
When not to use
- Do not use DataTable for layout purposes — it is designed for data display, not page structure
- Do not put more than 8-10 columns in a single table; consider splitting into multiple views
- Do not make every column sortable by default — this creates unnecessary cognitive load
- Do not nest complex interactive components (modals, drawers) inside table cells
- Do not forget to set a key attribute on each arc-column — the table cannot render data without it
- Do not use DataTable for very small datasets (2-3 items) where a simple list would suffice
Features
- Data-driven rendering from a rows array — no manual <tr>/<td> markup
- Declarative column definitions via `<arc-column>` children
- Client-side sorting with ascending/descending toggle per column
- Row selection with individual and select-all checkboxes
- Sticky table headers that remain visible during scroll
- Alternating row backgrounds for improved scanability
- Hover highlighting on rows for easy tracking
- Empty-state fallback when no data is available
- `arc-sort` and `arc-select` custom events
- Accessible ARIA attributes: `aria-sort` on headers, `aria-label` on checkboxes
- Configurable column widths via the width attribute
- CSS custom property theming via ARC design tokens
Preview
| No data available |
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<div style="width:100%">
<arc-data-table id="demo-dt-preview" sortable selectable>
<arc-column key="name" label="Name" sortable></arc-column>
<arc-column key="role" label="Role" sortable></arc-column>
<arc-column key="department" label="Department"></arc-column>
<arc-column key="status" label="Status" width="100px"></arc-column>
</arc-data-table>
</div>
<script type="module">
import '@arclux/arc-ui/data-table';
import '@arclux/arc-ui/column';
const dt = document.querySelector('#demo-dt-preview');
dt.rows = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
</script> import { DataTable, Column } from '@arclux/arc-ui-react';
const employees = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
export function EmployeeDirectory() {
return (
<DataTable rows={employees} sortable selectable>
<Column key="name" label="Name" sortable />
<Column key="role" label="Role" sortable />
<Column key="department" label="Department" />
<Column key="status" label="Status" width="100px" />
</DataTable>
);
} <script setup>
import { DataTable, Column } from '@arclux/arc-ui-vue';
const employees = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
</script>
<template>
<DataTable :rows="employees" sortable selectable>
<Column key="name" label="Name" sortable />
<Column key="role" label="Role" sortable />
<Column key="department" label="Department" />
<Column key="status" label="Status" width="100px" />
</DataTable>
</template> <script>
import { DataTable, Column } from '@arclux/arc-ui-svelte';
const employees = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
</script>
<DataTable rows={employees} sortable selectable>
<Column key="name" label="Name" sortable />
<Column key="role" label="Role" sortable />
<Column key="department" label="Department" />
<Column key="status" label="Status" width="100px" />
</DataTable> import { Component } from '@angular/core';
import { DataTable, Column } from '@arclux/arc-ui-angular';
@Component({
imports: [DataTable, Column],
template: `
<arc-data-table [rows]="employees" sortable selectable>
<arc-column key="name" label="Name" sortable></arc-column>
<arc-column key="role" label="Role" sortable></arc-column>
<arc-column key="department" label="Department"></arc-column>
<arc-column key="status" label="Status" width="100px"></arc-column>
</arc-data-table>
`,
})
export class EmployeeDirectoryComponent {
employees = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
} import { DataTable, Column } from '@arclux/arc-ui-solid';
const employees = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
export function EmployeeDirectory() {
return (
<DataTable rows={employees} sortable selectable>
<Column key="name" label="Name" sortable />
<Column key="role" label="Role" sortable />
<Column key="department" label="Department" />
<Column key="status" label="Status" width="100px" />
</DataTable>
);
} import { DataTable, Column } from '@arclux/arc-ui-preact';
const employees = [
{ name: 'Alice Chen', role: 'Senior Engineer', department: 'Engineering', status: 'Active' },
{ name: 'Bob Martinez', role: 'Product Designer', department: 'Design', status: 'Active' },
{ name: 'Charlie Kim', role: 'Engineering Manager', department: 'Engineering', status: 'Away' },
{ name: 'Diana Patel', role: 'Frontend Developer', department: 'Engineering', status: 'Active' },
{ name: 'Eve Johnson', role: 'UX Researcher', department: 'Design', status: 'Active' }
];
export function EmployeeDirectory() {
return (
<DataTable rows={employees} sortable selectable>
<Column key="name" label="Name" sortable />
<Column key="role" label="Role" sortable />
<Column key="department" label="Department" />
<Column key="status" label="Status" width="100px" />
</DataTable>
);
} API
-
rowsArray<Record<string, any>>[] - The data array that drives the table. Each object in the array becomes a row, and its keys are matched against the `key` attribute of each `arc-column` child. Set this property via JavaScript — it is not an HTML attribute. Changing this array triggers a re-render.
-
sortablebooleanfalse - Enables the sorting system at the table level. When true, columns that also have their own `sortable` attribute become clickable, toggling between ascending and descending order. The table performs client-side sorting by default and emits an `arc-sort` event with the active column key and direction.
-
selectablebooleanfalse - Adds a checkbox column to the left of the table for row selection. A "select all" checkbox appears in the header. Selected rows receive a visual highlight. The component emits `arc-select` with the current selection (detail.value) when any row or the header checkbox is toggled; detail.all marks header toggles.
-
sort-columnstring'' - The `key` of the currently sorted column. Set this attribute to pre-sort the table on a specific column when it first renders. Updated automatically when the user clicks a sortable column header.
-
sort-direction'asc' | 'desc''asc' - The current sort direction. Works in tandem with `sort-column` to control the initial sort state. Reflected as an attribute so it can be read from the DOM or targeted with CSS selectors.
-
virtualbooleanfalse - Enables virtual scrolling for large datasets. When true, only the visible rows plus an overscan buffer are rendered in the DOM, keeping performance constant regardless of row count.
-
row-heightnumber40 - Height in pixels of each row when virtual scrolling is enabled. Must match the actual rendered row height for correct scroll calculations.
Events
-
arc-sortdetail: { column: string, direction: 'asc' | 'desc' } - Fired when a sortable column header is clicked
-
arc-select - Fired when row selection changes. detail: { value, selected, row, index } — value is the sorted selected indices; detail.all is true for header select-all toggles
Column
<arc-column> Defines a single column within a DataTable. Each Column maps a data field key to a visible table column with a header label. Columns are invisible DOM elements that act as declarative configuration — they do not render any visible content themselves.
-
fieldName - The row property this column reads, from whichever alias was supplied. React and Preact strip `key` in the reconciler, so a React consumer can only ever reach this through `field`.
-
fieldstring'' - The property name on each row object whose value should be displayed in this column. Must match a key present in the objects passed to the parent DataTable's `rows` array. Prefer this over `key`, which React and Preact intercept before the component sees it.
-
keystring'' - Alias of `field`, kept for compatibility. Works in HTML, Vue, Svelte, Angular and Solid, but **not** in React or Preact: both reserve `key` for list reconciliation and strip it before the component receives it. `field` takes precedence when both are set.
-
labelstring'' - The human-readable header text displayed in the table's `<th>` element. This is what users see at the top of the column.
-
sortablebooleanfalse - When true (and the parent DataTable also has `sortable`), clicking this column's header toggles ascending/descending sort on the corresponding data field. A sort indicator arrow appears next to the label.
-
widthstring'' - Sets a fixed CSS width on the column (e.g., "100px", "20%"). Useful for constraining narrow columns like status badges or actions so they do not stretch unnecessarily.
See Also
- Table Data-driven table with striped and compact-density variants, powered by columns and rows props.
- Pagination Page navigation control with previous/next arrows, numbered page buttons, and smart ellipsis truncation.
- Sortable List Drag-and-drop reorderable list with grip handles, keyboard reordering support, and visual insertion indicators.