Base data table, sortable column headers, and filter toolbar patterns used across the admin console and arXiv Check.
The .ds-table class provides warm-tinted header row, subtle row dividers, and hover highlighting. Condensed uppercase headers use IBM Plex Sans Condensed.
The Type column uses rectangular tags at the default level, documented on Tags.
| Date | Title | Submitter | Type |
|---|---|---|---|
| 2026-03-24 | Asymptotic Expansions of Schrödinger Operators | Esther McGill-Henry | New |
| 2025-07-09 | Symmetry Breaking in Non-Abelian Gauge Theories | Esther McGill-Henry | Rep |
| 2024-07-08 | Spectral Properties of Discrete Schrödinger Operators | Esther McGill-Henry | Wdr |
<div class="table-scroll" role="region" aria-label="Submissions" tabindex="0">
<table class="ds-table">
<thead>
<tr>
<th scope="col">Date</th>
<th scope="col">Title</th>
<th scope="col">Submitter</th>
<th scope="col">Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>2026-03-24</td>
<td>Asymptotic Expansions of Schrödinger Operators</td>
<td>Esther McGill-Henry</td>
<td><span class="ds-tag ds-tag--rectangle">New</span></td>
</tr>
<tr>
<td>2025-07-09</td>
<td>Symmetry Breaking in Non-Abelian Gauge Theories</td>
<td>Esther McGill-Henry</td>
<td><span class="ds-tag ds-tag--rectangle">Rep</span></td>
</tr>
<!-- … one row per record -->
</tbody>
</table>
</div>
<table> element: it gives the
header row its tint, the rows their dividers, and each row its hover highlight.<table> when fixed column widths are needed.
The table defaults to auto layout.<div> below the table for row counts or pagination.<th> in the header row, so a screen reader
reads the column name with each cell.role="region", an aria-label that
names the table, and tabindex="0" so a keyboard user can reach it to
scroll.The public site's table, .ds-table-framed in tier 1: the page's own
type, a hairline frame and rounded corners, header and cells taking the element defaults. It is the
table on every specification section of this documentation. Shown here beside the internal data
table above so the two can be compared: they differ in type size, in the header row, and in
row hover.
| Date | Title | Category |
|---|---|---|
| 2026-03-24 | Spectral gaps in random regular hypergraphs | math.CO |
| 2026-03-23 | Anomalous diffusion in confined active matter | cond-mat.soft |
| 2026-03-22 | A note on the endpoint Strichartz estimate | math.AP |
<table class="ds-table-framed">
<thead>
<tr><th scope="col">Date</th><th scope="col">Title</th><th scope="col">Category</th></tr>
</thead>
<tbody>
<tr><td>2026-03-24</td><td>Spectral gaps in random regular hypergraphs</td><td>math.CO</td></tr>
</tbody>
</table>
.ds-page has.A sortable column has a <button class="sortable"> inside its <th>, holding the label and a <span class="sort-arrow"> for the direction. It looks like the plain header and it can be reached and pressed from the keyboard, which a <th> on its own cannot. .sort-asc or .sort-desc and aria-sort go on the <th> of the sorted column.
Sortable headers, click to sort
Sort logic is application-specific; the CSS only handles visual states.
| Title | |||
|---|---|---|---|
| 2026-03-24 | Asymptotic Expansions | New | On Hold |
| 2025-07-09 | Symmetry Breaking | Rep | Removed |
| 2024-07-08 | Spectral Properties | New | Removed |
| 2023-04-18 | Geometric Phases | Wdr | Removed |
<table class="ds-table">
<thead>
<tr>
<th scope="col" class="sort-desc" aria-sort="descending">
<button type="button" class="sortable">Date <span class="sort-arrow">↓</span></button>
</th>
<th scope="col">Title</th>
<th scope="col"><button type="button" class="sortable">Type <span class="sort-arrow">⇅</span></button></th>
<th scope="col"><button type="button" class="sortable">Status <span class="sort-arrow">⇅</span></button></th>
</tr>
</thead>
<tbody>
<tr>
<td>2026-03-24</td>
<td>Asymptotic Expansions</td>
<td><span class="ds-tag ds-tag--rectangle">New</span></td>
<td>On Hold</td>
</tr>
<tr>
<td>2025-07-09</td>
<td>Symmetry Breaking</td>
<td><span class="ds-tag ds-tag--rectangle">Rep</span></td>
<td>Removed</td>
</tr>
<!-- … one row per record -->
</tbody>
</table>
<div class="ds-table-footer">1–4 of 4</div>
<button type="button"> inside the <th>. The
button is styled to look like the plain header text, so nothing changes visually; what it
adds is a keyboard stop, so a reader who cannot use a mouse can sort. Pointer cursor, and
the label darkens on hover.<span> inside the header. Unsorted it
shows ⇅ in --ds-border-strong (3.12:1 on the header background).<th> of the sorted column. The arrow shows ↑ in
--ds-text.<th> of the sorted column. The arrow shows ↓ in
--ds-text.<th>, matching the class. Remove it from the column that is no
longer sorted. The arrow is a glyph, so this is what tells a screen reader which
column orders the table.The .ds-filter component provides a minimal underline-only <select> for filtering data. Typically placed in a toolbar row above or alongside a table. The custom chevron replaces the native dropdown arrow for visual consistency.
Filter select, standalone
<div class="ds-filter">
<label for="filter-status">Show:</label>
<select id="filter-status">
<option>All</option>
<option selected>Removed</option>
<option>On Hold</option>
</select>
</div>
<label> and one
<select>. The select gets an underline-only border, the custom
chevron, and a focus ring in --ds-focus-ring. Always include an
“All” option as the inclusive default.for attribute
points at the select’s id.Filter above a table
| Name | Category | Status |
|---|---|---|
| Alice Chen | cs.AI | Active |
| Bob Singh | math.AP | Archived |
<div class="ds-btn-group ds-btn-group--end" style="margin-bottom: var(--ds-space-3)">
<div class="ds-filter">
<label for="filter-users">Show:</label>
<select id="filter-users">
<option selected>All</option>
<option>Active</option>
<option>Archived</option>
</select>
</div>
</div>
<div class="table-scroll" role="region" aria-label="Users" tabindex="0">
<table class="ds-table">
…
</table>
</div>
Rules for tables whose rows can be selected and acted on together — moderation queues, ownership lists.
Selection active — actions left, filter right, selected rows tinted
| Select | Date | Title | Type |
|---|---|---|---|
| 2026-03-24 | Asymptotic Expansions of Schrödinger Operators | New | |
| 2025-07-09 | Symmetry Breaking in Non-Abelian Gauge Theories | Rep | |
| 2024-07-08 | Spectral Properties of Discrete Schrödinger Operators | Wdr |
<div class="ds-btn-group ds-btn-group--split" style="margin-bottom: var(--ds-space-3)">
<div class="ds-btn-group">
<button class="ds-btn ds-btn-primary" type="button">Approve</button>
<button class="ds-btn" type="button">Hold</button>
<button class="ds-btn ds-btn-destructive" type="button" style="margin-inline-start: var(--ds-space-tight)">Remove…</button>
<span class="ds-bulk-count" role="status">2 selected · <a href="#">Clear selection</a></span>
</div>
<div class="ds-filter">
<label for="filter-owned">Show</label>
<select id="filter-owned">…</select>
</div>
</div>
<div class="table-scroll" role="region" aria-label="Owned papers" tabindex="0">
<table class="ds-table">
<thead>
<tr>
<th scope="col"><span class="is-sr-only">Select</span></th>
<th scope="col">Date</th>
<th scope="col">Title</th>
<th scope="col">Type</th>
</tr>
</thead>
<tbody>
<tr class="is-selected">
<td>
<input type="checkbox" id="sel-1" checked>
<label for="sel-1" class="is-sr-only">Select Asymptotic Expansions of Schrödinger Operators</label>
</td>
<td>2026-03-24</td>
<td>Asymptotic Expansions of Schrödinger Operators</td>
<td><span class="ds-tag ds-tag--rectangle">New</span></td>
</tr>
<tr>
<td>
<input type="checkbox" id="sel-2">
<label for="sel-2" class="is-sr-only">Select Symmetry Breaking in Non-Abelian Gauge Theories</label>
</td>
<td>2025-07-09</td>
<td>Symmetry Breaking in Non-Abelian Gauge Theories</td>
<td><span class="ds-tag ds-tag--rectangle">Rep</span></td>
</tr>
<!-- … one row per record -->
</tbody>
</table>
</div>
role="status" so a change in the count is announced.<tr>. Tints the row with --ds-accent-wash;
the tint aids scanability of the selection set. Selection state must not rely on the
tint alone: the row’s checkbox carries the state (WCAG 1.4.1).<td>, which
gives it a 24px target and this surface’s accent. Each one has a
<label class="is-sr-only"> that names its row.Nothing selected — actions disable, they never disappear
<div class="ds-btn-group ds-btn-group--split">
<div class="ds-btn-group">
<button class="ds-btn ds-btn-primary" type="button" disabled>Approve</button>
<button class="ds-btn" type="button" disabled>Hold</button>
<button class="ds-btn ds-btn-destructive" type="button" disabled style="margin-inline-start: var(--ds-space-tight)">Remove…</button>
<span class="ds-bulk-count" role="status">0 selected</span>
</div>
<div class="ds-filter">
<label for="filter-owned">Show</label>
<select id="filter-owned">…</select>
</div>
</div>
disabled attribute on every action button while nothing is selected. The buttons stay in place; the
filter stays live, because it does not depend on a selection.scope="col" on every
<th> in the header row, so a screen reader reads the column name with
each cell instead of a bare value.<caption>, or an
aria-label on the scrolling region around the table, as the examples on this
page do. Without one, a screen reader user lands in “table, 4 columns” with no idea
which table it is.aria-sort="ascending" or
aria-sort="descending" on the sorted <th> and remove it from
the others when the sort changes. The arrow is a glyph, and the class is invisible to a
screen reader.<label class="is-sr-only"> that names its row, such as “Select
Asymptotic Expansions”. Without it the choice reads as “checkbox, not checked” and
nothing more. Prefer the label to aria-label, because page translation tools
skip attributes.role="status", so a screen reader user hears “2 selected” when it changes
without leaving the checkbox they just ticked.Pressing a sortable header, by mouse or keyboard, toggles through: descending → ascending → descending. Clicking a different column resets the previous column to unsorted. Sort logic is application-specific; the CSS only handles visual states.
Action buttons and their descriptive text (selection count, “Clear selection”) sit on the left; filter dropdowns sit on the right. No background tint behind the action buttons — the bar itself stays neutral. Destructive actions (Remove, Delete) are visually separated from constructive ones and always require a confirmation step.