Skip to main content

rc-data-table

Sortable-header enhancer for a native <table>, following the WAI-ARIA sortable table example.

Package
@rcarls/rc-data-table
Element
<rc-data-table>
Native dependency
Requires a native table child; each sortable th holds a native button or link
State model
Controlled or uncontrolled sort key and direction
Main events
rc-data-table-sort

Installation​

npm install @rcarls/rc-webcomponents@next
import '@rcarls/rc-webcomponents/rc-data-table/define';

Usage​

Author the table, and put each sortable column's header text in a native <button> inside a <th data-rc-sort-key="...">:

<rc-data-table sort-key="name" sort-direction="ascending">
<table>
<caption>
Plants. Column headers with buttons are sortable.
</caption>
<thead>
<tr>
<th scope="col" data-rc-sort-key="name"><button type="button">Name</button></th>
<th scope="col" data-rc-sort-key="price" data-rc-sort-first="descending">
<button type="button">Price</button>
</th>
<th scope="col">Notes</th>
</tr>
</thead>
<tbody>
<!-- rows, in the current sort order -->
</tbody>
</table>
</rc-data-table>

The button is part of the markup, not added at upgrade, so a framework that renders the table keeps owning every node. A header can be a link to a server-sorted URL instead, such as <a href="?sort=name&dir=descending">, which sorts the table with no JavaScript at all.

data-rc-sort-first="descending" makes a column, such as a price or date, sort descending the first time it is chosen.

Live demo​

The element never sorts rows​

rc-data-table reflects the sort state and reports requests; the consumer sorts the data and re-renders <tbody>. Activating a header fires rc-data-table-sort with { key, direction, previousKey, previousDirection }. Activating the sorted column again flips its direction.

  • Uncontrolled: the element moves aria-sort itself; set the initial state with default-sort-key and default-sort-direction.
  • Controlled: set sort-key and sort-direction, and write them from the event when the new order is rendered.

The event is cancelable. Canceling it also cancels the click, so a header link does not navigate.

Accessibility​

  • aria-sort is set only on the sorted column's header and removed from the others, rather than set to none.
  • Each sortable column shows a CSS indicator with a distinct shape for unsorted, ascending, and descending. The indicators are generated content with empty alternative text, so they are not part of the button's name.
  • Say in the <caption> that column headers with buttons sort the table. The element warns in development when a sortable table has no caption.
  • Screen readers announce sort changes inconsistently. Set announce to have the element announce "Sorted by Name, ascending" through a polite live region.
  • While the table is wider than its container, the element becomes a focusable group named by the caption, so keyboard users can scroll it.

Theming​

The default demo mode shows the component without a package theme. The Material theme keeps the Material 2 data table metrics in Material 3 color and type roles. Use the shared preview controls to compare themes.

API​

Properties​

PropertyMarkupTypeDefaultDescription
announceannouncebooleanfalseAnnounces each user sort through a polite live region.
messagesJS property onlyPartial<RCDataTableMessages> | undefinedNot specifiedBuilt-in text overrides; unset keys fall back to registered text, then English.
sortKeysort-keystring | undefinedNot specifiedCurrent sort column. Host writes are silent; assign `undefined` to release control.
sortDirectionsort-directionRCDataTableSortDirectionNot specifiedCurrent sort direction. Host writes are silent.
defaultSortKeydefault-sort-keystring | undefinedNot specifiedInitial sort column for uncontrolled use.
defaultSortDirectiondefault-sort-directionRCDataTableSortDirectionNot specifiedInitial sort direction for uncontrolled use.

Events​

EventDetail typeDescription
rc-data-table-sortNo detail type documentedFired when the user activates a sortable column header. Cancelable; canceling it also cancels the click, so a header link does not navigate.

CSS Custom Properties​

PropertyDefaultDescription
--rc-data-table-cell-padding-blockNot specifiedCell block padding. Defers to the user agent when unset.
--rc-data-table-cell-padding-inlineNot specifiedCell inline padding. Defers to the user agent when unset.
--rc-data-table-sort-indicator-gap0.25emSpace between a header label and its sort indicator.
--rc-data-table-sort-none'\25C7'Indicator for a sortable column that is not sorted.
--rc-data-table-sort-ascending'\25B2'Indicator for an ascending column.
--rc-data-table-sort-descending'\25BC'Indicator for a descending column.