Semantic structure
A semantic table preserves relationships between column headers and cells.
Compose existing xsh- classes on the appropriate HTML element. Keep content order meaningful when CSS is disabled.
Client-side sorting and filtering for ordinary HTML tables.
The same semantic table with the striped modifier. Horizontal scrolling is handled by the wrapper on narrow viewports.
| Name | Status | Updated |
|---|---|---|
| Northstar | Active | Today |
| Orion | Review | Yesterday |
| Atlas | Draft | Oct 20 |
<div class="xsh-table-wrap"><table class="xsh-table xsh-table-striped"><thead><tr><th scope="col">Name</th><th scope="col">Status</th><th scope="col">Updated</th></tr></thead><tbody><tr><td>Northstar</td><td><span class="xsh-badge xsh-badge-success">Active</span></td><td>Today</td></tr><tr><td>Orion</td><td><span class="xsh-badge xsh-badge-warning">Review</span></td><td>Yesterday</td></tr><tr><td>Atlas</td><td><span class="xsh-badge">Draft</span></td><td>Oct 20</td></tr></tbody></table></div>The same semantic table with the hover modifier. Horizontal scrolling is handled by the wrapper on narrow viewports.
| Name | Status | Updated |
|---|---|---|
| Northstar | Active | Today |
| Orion | Review | Yesterday |
| Atlas | Draft | Oct 20 |
<div class="xsh-table-wrap"><table class="xsh-table xsh-table-hover"><thead><tr><th scope="col">Name</th><th scope="col">Status</th><th scope="col">Updated</th></tr></thead><tbody><tr><td>Northstar</td><td><span class="xsh-badge xsh-badge-success">Active</span></td><td>Today</td></tr><tr><td>Orion</td><td><span class="xsh-badge xsh-badge-warning">Review</span></td><td>Yesterday</td></tr><tr><td>Atlas</td><td><span class="xsh-badge">Draft</span></td><td>Oct 20</td></tr></tbody></table></div>The same semantic table with the compact modifier. Horizontal scrolling is handled by the wrapper on narrow viewports.
| Name | Status | Updated |
|---|---|---|
| Northstar | Active | Today |
| Orion | Review | Yesterday |
| Atlas | Draft | Oct 20 |
<div class="xsh-table-wrap"><table class="xsh-table xsh-table-compact"><thead><tr><th scope="col">Name</th><th scope="col">Status</th><th scope="col">Updated</th></tr></thead><tbody><tr><td>Northstar</td><td><span class="xsh-badge xsh-badge-success">Active</span></td><td>Today</td></tr><tr><td>Orion</td><td><span class="xsh-badge xsh-badge-warning">Review</span></td><td>Yesterday</td></tr><tr><td>Atlas</td><td><span class="xsh-badge">Draft</span></td><td>Oct 20</td></tr></tbody></table></div>The same semantic table with the sticky modifier. Horizontal scrolling is handled by the wrapper on narrow viewports.
| Name | Status | Updated |
|---|---|---|
| Northstar | Active | Today |
| Orion | Review | Yesterday |
| Atlas | Draft | Oct 20 |
<div class="xsh-table-wrap"><table class="xsh-table xsh-table-sticky"><thead><tr><th scope="col">Name</th><th scope="col">Status</th><th scope="col">Updated</th></tr></thead><tbody><tr><td>Northstar</td><td><span class="xsh-badge xsh-badge-success">Active</span></td><td>Today</td></tr><tr><td>Orion</td><td><span class="xsh-badge xsh-badge-warning">Review</span></td><td>Yesterday</td></tr><tr><td>Atlas</td><td><span class="xsh-badge">Draft</span></td><td>Oct 20</td></tr></tbody></table></div>Add data-xsh-sort=text|number|date to buttons in th and use aria-sort on the heading. Set data-xsh-filter="#xsh-table-id" on an input to filter visible rows.
| Amara | 82 |
| Ben | 94 |
| Charu | 88 |
<div class="xsh-stack">
<label class="xsh-label" for="xsh-table-search">Filter team</label><input class="xsh-input" id="xsh-table-search" placeholder="Search by name..." data-xsh-filter="#xsh-sortable-table" data-xsh-filter-count="#xsh-results-count"><small class="xsh-muted">Matching rows: <span id="xsh-results-count">3</span></small>
<div class="xsh-table-responsive"><table class="xsh-table" id="xsh-sortable-table"><thead><tr><th scope="col"><button data-xsh-sort="text">Name ↕</button></th><th scope="col"><button data-xsh-sort="number">Score ↕</button></th></tr></thead><tbody><tr><td>Amara</td><td>82</td></tr><tr><td>Ben</td><td>94</td></tr><tr><td>Charu</td><td>88</td></tr></tbody></table></div>
</div>Customize this component through --xsh-* CSS tokens, data-xsh-* configuration attributes and documented xsh-* utilities. Use the optional JavaScript distribution only when an interactive behavior is needed.
These selectors exist in the current distribution. An entry in this table does not imply that arbitrary modifier combinations are meaningful; use the examples above for the intended composition.
| Class | Purpose | Delivery |
|---|---|---|
.xsh-table | Core component | CSS-only |
.xsh-table-compact | Composable modifier / structure class | CSS-only |
.xsh-table-hover | Composable modifier / structure class | CSS-only |
.xsh-table-responsive | Composable modifier / structure class | CSS-only |
.xsh-table-sticky | Composable modifier / structure class | CSS-only |
.xsh-table-striped | Composable modifier / structure class | CSS-only |
.xsh-table-wrap | Composable modifier / structure class | CSS-only |
A semantic table preserves relationships between column headers and cells.
Compose existing xsh- classes on the appropriate HTML element. Keep content order meaningful when CSS is disabled.
For wide tables provide scrolling instead of clipping data.
Load xshna.min.js only if the documented interaction needs it. Your application remains responsible for data, persistence and business rules.
Sortable columns need descriptive button labels and current sort direction.
Test 320px-wide viewports, container-constrained instances, keyboard zoom, longer translations and right-to-left text where relevant.
Use --xsh-* CSS variables for theme values and data-xsh-design / data-xsh-density on the xsh-app root.
Prefer design tokens over hard-coded overrides so components remain coherent across personalities.