Skip to content

Table

.bp-table is a standard <table> wrapped in .bp-table-wrap for horizontal scroll. Sortable columns use aria-sort — the <bp-table> Web Component reads it and re-orders rows client-side. CSS renders the sort indicators. No JavaScript required for display; JS adds sorting.

Sortable table

Name Role Score
Alice Designer 92
Bob Engineer 78
Carol Manager 85
David Designer 67
<bp-table>
<div class="bp-table-wrap">
<table class="bp-table">
<thead>
<tr>
<th aria-sort="none">Name</th>
<th aria-sort="none">Role</th>
<th aria-sort="ascending" class="bp-table__num">Score</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Designer</td>
<td class="bp-table__num">92</td>
</tr>
<tr>
<td>Bob</td>
<td>Engineer</td>
<td class="bp-table__num">78</td>
</tr>
<tr>
<td>Carol</td>
<td>Manager</td>
<td class="bp-table__num">85</td>
</tr>
<tr>
<td>David</td>
<td>Designer</td>
<td class="bp-table__num">67</td>
</tr>
</tbody>
</table>
</div>
</bp-table>

Striped

Product Category Price Stock
Widget AHardware $12.99 142
Widget BSoftware $49.00 23
Gadget XHardware $8.50 310
Service YSoftware $99.00
<bp-table>
<div class="bp-table-wrap">
<table class="bp-table bp-table--striped">
<thead>
<tr>
<th aria-sort="none">Product</th>
<th aria-sort="none">Category</th>
<th aria-sort="none" class="bp-table__num">Price</th>
<th aria-sort="none" class="bp-table__num">Stock</th>
</tr>
</thead>
<tbody>
<tr>
<td>Widget A</td><td>Hardware</td>
<td class="bp-table__num">$12.99</td>
<td class="bp-table__num">142</td>
</tr>
<tr>
<td>Widget B</td><td>Software</td>
<td class="bp-table__num">$49.00</td>
<td class="bp-table__num">23</td>
</tr>
<tr>
<td>Gadget X</td><td>Hardware</td>
<td class="bp-table__num">$8.50</td>
<td class="bp-table__num">310</td>
</tr>
<tr>
<td>Service Y</td><td>Software</td>
<td class="bp-table__num">$99.00</td>
<td class="bp-table__num"></td>
</tr>
</tbody>
</table>
</div>
</bp-table>

Load <bp-table> once to enable sorting:

<script type="module" src="https://unpkg.com/@be-partner-labs/ds/js/bp-table.esm.min.js"></script>

Or via npm:

import '@be-partner-labs/ds/js/bp-table'

Without JS, the table displays correctly — sort indicators are hidden and columns are not interactive.

VariableDefaultDescription
--table-border1px solid --bp-color-borderCell and wrapper border
--table-radius--bp-radius-lgWrapper border radius
--table-bg--bp-color-bgRow background
--table-bg-alt--bp-color-bg-subtleStriped alternate row
--table-bg-hover--bp-color-bg-subtleRow hover background
--table-bg-head--bp-color-bg-subtleHeader background
--table-sort-color--bp-primaryActive sort indicator color
--table-padding--bp-space-3 --bp-space-4Cell padding

Add aria-sort="none" to any <th> to make it sortable. The <bp-table> Web Component:

  1. Reads aria-sort to determine current state
  2. On click or Enter/Space, toggles ascendingdescending
  3. Resets other headers to none
  4. Re-orders <tbody> rows in-place

Numeric detection: If all values in a column parse as numbers (strips $, ,, %), numeric sort is used automatically. Add .bp-table__num to the <th> to also right-align it.

No axe violations tested 2026-05-11
  • aria-sort on <th> announces sort state to screen readers (“column header, ascending”).
  • Sortable headers get tabindex="0" automatically — keyboard users can Tab to them and press Enter or Space to sort.
  • Sort icons are rendered via CSS ::after with content: "↑" / "" — the / "" hides them from the accessibility tree.
  • The <bp-table> wrapper is a custom element with no ARIA role — it’s transparent to assistive technology.
APIAvailabilityUsed forWithout it
Custom Elements Widely available Baseline 2020 Sorting logicTable renders, no sort
aria-sort Widely available Baseline 2017 Sort state announcementUse a class
CSS content with alt text Widely available Baseline 2023 Hidden sort iconsDecorative icons visible to AT

Sorting is purely DOM manipulation — rows are detached and re-appended to <tbody> in sorted order. No virtual DOM, no state library. The sort is stable in modern browsers (Array.sort is stable since ES2019). For server-side sorting or pagination, don’t use <bp-table> — render sorted HTML directly and set aria-sort on the active column.