Tables
Summary
Data tables for tabular content. Two opt-in modifiers add
interactivity (row hover) and column sorting. The sortable
modifier reads aria-sort on each <th>
and toggles the clicked column between ascending and
descending (other columns lose their
aria-sort).
When to use
| Variant | Use it for |
|---|---|
Plain.neura-table | Static tabular data: read-only summaries, configuration values, two-column key-value pairs. |
Interactive.neura-table-interactive | Modifier: adds row hover. Use when rows link to a detail view or are otherwise clickable. |
Sortable.neura-table-sortable | Modifier: clickable (and keyboard-operable) column headers toggle aria-sort. Pairs with .neura-table-interactive. |
Unsortable column.neura-table-column-unsortable | Per-th modifier: opts a single column out of sorting (e.g. an actions column). |
Zebra.neura-table-zebra | Modifier: tints even rows and drops the row borders in favour of the stripes. For dense listings where per-row borders get noisy. |
Examples
Sortable + interactive table. Click any header cell to toggle
aria-sort ascending ↔ descending, hover
rows to highlight, and verify lozenge cells render with the
expected status colors.
| Name | Role | Status | Actions | |
|---|---|---|---|---|
| Alice | alice@example.com | Admin | active | Edit |
| Bob | bob@example.com | Editor | pending | Edit |
| Carol | carol@example.com | Viewer | disabled | Edit |
HTML
Plain table: no interactivity, no sort. An optional
<caption> renders as a tinted title bar
above the table (caption-side: top).
<table class="neura-table">
<thead>
<tr><th>Name</th><th>Email</th></tr>
</thead>
<tbody>
<tr><td>Alice</td><td>alice@example.com</td></tr>
<tr><td>Bob</td><td>bob@example.com</td></tr>
</tbody>
</table>
Interactive + sortable. Set the initial sort column via aria-sort:
<table class="neura-table neura-table-interactive neura-table-sortable">
<thead>
<tr>
<th aria-sort="ascending">Name</th>
<th>Email</th>
<th class="neura-table-column-unsortable">Actions</th>
</tr>
</thead>
<tbody>
<!-- rows -->
</tbody>
</table>
Lozenges in cells (see .neura-lozenge for status pills):
<td><span class="neura-lozenge neura-lozenge-success">active</span></td>
<td><span class="neura-lozenge neura-lozenge-error">disabled</span></td>
CSS classes
| Class | Effect |
|---|---|
.neura-table | Base styling: borders, padding, header weight, caption bar. |
.neura-table-interactive | Modifier: adds row hover background. |
.neura-table-sortable | Modifier: clickable headers cycle aria-sort. Adds the sort caret; hovering an unsorted column previews a faint one. |
.neura-table-column-unsortable | On a <th>: exempts that column from the sort handler. |
.neura-table-zebra | Modifier: even-row striping instead of row borders (AUI: table.aui.aui-zebra). |
Attributes
| Attribute | Effect |
|---|---|
aria-sort="ascending" | Marks the column as currently sorted ascending. Visual caret + screen-reader cue. |
aria-sort="descending" | Currently sorted descending. |
aria-sort="none" | Sortable but not currently sorted. |
JavaScript
Sorting is a Neura-native component. Every
table.neura-table-sortable auto-inits on
DOMContentLoaded: headers become clickable and
keyboard-operable (focusable, Enter/Space), rows reorder
alphabetically / numerically, and aria-sort tracks
the active column. No JS is needed for static markup.
API
| Member | Description |
|---|---|
Neura.sortableTable(tableOrSelector) | Get the singleton instance for a table (binds its headers on first call). |
.sort(column[, direction]) | Sort imperatively: column is a zero-based index or a <th>; direction is 'ascending' / 'descending' (defaults to the same toggle a click performs). |
.refresh() | Bind headers added after init (re-rendered thead). |
.on('sort', fn) / .off('sort', fn) | The neura-table-sort CustomEvent (detail: { th, columnIndex, direction }), fired after each sort. |
.destroy() | Unbind all headers and forget the instance. |
Manual setup (e.g. for a table inserted after page load):
const st = Neura.sortableTable('#report');
// Sort the second column descending without a click:
st.sort(1, 'descending');
// React to sorting:
st.on('sort', (e) => {
console.log(e.detail.columnIndex, e.detail.direction);
});
If you need custom sort logic (e.g. dates, mixed types), do it yourself and just keep aria-sort in sync:
document.querySelector('th.date-col').addEventListener('click', (e) => {
const th = e.currentTarget;
const dir = th.getAttribute('aria-sort') === 'ascending' ? 'descending' : 'ascending';
// ... sort the rows however you want ...
th.setAttribute('aria-sort', dir);
});
AUI compatibility
table.aui, .aui-table-interactive,
.aui-table-sortable, table.aui.aui-zebra,
and .aui-table-column-unsortable all alias to the
Neura rules.
AJS.tablessortable.setup() is a compat alias over
Neura.sortableTable. It normalizes the legacy
aui-* marker classes and delegates, so legacy
markup sorts identically and auto-inits on every page load.