Sortable Table Web Component Demo

A web component to enable users to sort table data by clicking on column headers. Built with accessibility in mind, supporting keyboard navigation and screen reader announcements. See the README for installation and API documentation.

Progressive Enhancement

The component automatically enhances plain table headers by injecting buttons. You don't need to add buttons or links to your markup!

Auto-Enhanced Table

<table-sortable>
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Age</th>
        <th>City</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Charlie Brown</td>
        <td>35</td>
        <td>New York</td>
      </tr>
      <!-- more rows -->
    </tbody>
  </table>
</table-sortable>
Name Age City Occupation
Charlie Brown 35 New York Designer
Alice Cooper 28 Boston Developer
Bob Dylan 42 Chicago Manager
Diana Prince 31 Seattle Engineer
Eve Anderson 26 Portland Designer
Progressive Enhancement: The component automatically creates sortable buttons inside each <th> element. No need to add buttons or links manually!

Custom Sort Keys

Use the data-sort-value attribute to define custom sort values that differ from the displayed content.

Product Pricing with Custom Keys

<tr>
  <td data-sort-value="WIDGET-B">Widget B (Premium)</td>
  <td>WDG-002</td>
  <td data-sort-value="50">$50.00</td>
  <td data-sort-value="15">Low (15)</td>
</tr>
Product SKU Price Stock
Widget B (Premium) WDG-002 $50.00 Low (15)
Widget A (Basic) WDG-001 $30.00 High (100)
Widget C (Deluxe) WDG-003 $100.00 Very Low (5)
Gadget A (Standard) GDG-001 $75.00 Medium (50)
Note: The "Price" and "Stock" columns use data-sort-value to sort numerically rather than alphabetically by the formatted text.

Hidden Sort Keys

Use a [data-sort-as] element to provide sort values that aren't displayed to users.

Sorting by Last Name

<td>
  John <span data-sort-as>Smith</span>
</td>
Full Name Email Department
John Smith john.smith@example.com Engineering
Emily Anderson emily.anderson@example.com Marketing
Wei Zhang wei.zhang@example.com Design
Sarah Brown sarah.brown@example.com Sales
Note: The name column sorts by last name (indicated using [data-sort-as]) while displaying "First Last" format.

Grouped Tables

Use multiple <tbody> elements with data-table-sort-group attributes to maintain groupings while sorting.

Department-Grouped Employee List

<tbody>
  <tr data-table-sort-group="engineering">
    <td>Charlie Brown</td>
    <td>85</td>
    <td>Active</td>
  </tr>
</tbody>
Name Score Status
Charlie Brown (Engineering) 85 Active
Frank Miller (Engineering) 88 On Leave
Eve Adams (Engineering) 76 Inactive
Alice Cooper (Design) 92 Active
Grace Hopper (Design) 98 Active
Bob Dylan (Sales) 78 Active
Henry Ford (Sales) 84 Active
Diana Prince (Marketing) 95 Active
Note: Multiple rows can exist within each <tbody> group. Each group has a data-table-sort-group attribute. Rows within the same tbody are kept together when sorting.

Custom Labels (Localization)

Customize screen reader announcements using the label-sortable, label-ascending, and label-descending attributes. Perfect for localization. Note that label-ascending and label-descending will be prefixed by the column name.

French Localization

<table-sortable
  label-sortable="Cliquer pour trier"
  label-ascending="trié croissant. Cliquer pour trier décroissant"
  label-descending="trié décroissant. Cliquer pour trier croissant">
  <table>
    <thead>
      <tr>
        <th>Nom</th>
        <th>Âge</th>
      </tr>
    </thead>
    <!-- ... -->
  </table>
</table-sortable>
Nom Âge Ville
Marie 28 Paris
Pierre 35 Lyon
Sophie 42 Marseille
Note: The custom labels are announced to screen readers. Click a column header and check your screen reader to hear the French announcements.

Progressive Enhancement

The component uses pure progressive enhancement. Simply write plain <th> elements in your table headers, and the component automatically injects accessible <button> elements to make them sortable. You don't need to add any buttons or links manually.

All examples on this page demonstrate this approach - just plain <th> elements that get enhanced with sorting functionality.

Event Handling

Listen to the table-sortable:sort event to react to sorting changes.

Sort Event Listener

element.addEventListener('table-sortable:sort', (event) => {
  const { column, direction, header } = event.detail;
  console.log(`Sorted by ${header.textContent}`);
});
Name Value
Item C 30
Item A 10
Item B 20
Event Log:
Click a column header to see events...

API Reference

For complete documentation of attributes, events, and browser support, see the README.