Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

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.

Components Data Table
data interactive
<arc-data-table>

Overview

DataTable is the go-to component when you need to render structured, tabular data sourced from an array of objects. Instead of hand-writing `<tr>` and `<td>` elements, you pass a `rows` array to the component and declare columns as `<arc-column>` children — each column maps a `key` to a field in your data. The table handles rendering, alternating row backgrounds, hover highlighting, and sticky headers automatically. Sorting is opt-in at two levels: the table must have the `sortable` attribute, and each column that should be sortable needs its own `sortable` flag. When a user clicks a sortable header, the table toggles between ascending and descending order and emits an `arc-sort` event with the active column and direction, making it easy to integrate with server-side sorting if needed. Row selection adds a checkbox column to the left of the table. A "select all" checkbox in the header toggles every row, and individual row checkboxes emit `arc-select` events. The `selectable` attribute enables this mode. Selected rows receive a subtle blue highlight so the user always knows which rows are active. This is ideal for bulk-action patterns like "delete selected" or "export selected."

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

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

rows Array<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.
sortable boolean false
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.
selectable boolean false
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-column string ''
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.
virtual boolean false
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-height number 40
Height in pixels of each row when virtual scrolling is enabled. Must match the actual rendered row height for correct scroll calculations.

Events

arc-sort detail: { 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`.
field string ''
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.
key string ''
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.
label string ''
The human-readable header text displayed in the table's `<th>` element. This is what users see at the top of the column.
sortable boolean false
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.
width string ''
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