Data Management Table
A data-management table composed from tables, checkboxes, pagination, filters, selected and zero-selection bulk actions, and filtered empty states.
Manage customer records
Keep filters separate from bulk changes, give every row checkbox an accessible record name and submit selected identifiers with the chosen action. A Menu keeps related export formats compact without hiding the primary archive action. Keep the action area visible when nothing is selected so its availability does not depend on layout changes.
Customer records
Review account ownership, plans and lifecycle status.
<h3 id="records-title">Customer records</h3>
<form class="card shadow-sm border-primary bg-primary bg-opacity-10" role="search" method="get" action="/records" aria-label="Filter customer records">
<label class="form-label" for="record-search">Search records</label>
<input class="form-control" id="record-search" name="query" type="search" />
<label class="form-label" for="record-status">Status</label>
<select class="form-select" id="record-status" name="status">
<option value="all">All statuses</option>
<option value="active">Active</option>
</select>
<button class="btn btn-solid btn-primary" type="submit">Apply filters</button>
</form>
<form action="/records/bulk" method="post" aria-label="Customer record bulk actions">
<div class="card shadow-sm border-primary bg-primary bg-opacity-10 p-3" role="group" aria-label="Actions for selected records">
<p><strong>2 records selected</strong></p>
<div class="menu" data-menu>
<button class="btn btn-outline btn-secondary menu-trigger" type="button" data-menu-trigger>
Export selected
</button>
<div class="menu-popup" role="menu" popover="manual" hidden data-menu-popup>
<button class="menu-item" type="submit" role="menuitem" name="action" value="export-csv">
Export as CSV
</button>
<button class="menu-item" type="submit" role="menuitem" name="action" value="export-pdf">
Export as PDF
</button>
</div>
</div>
<button class="btn btn-solid btn-primary" type="submit" name="action" value="archive">
Archive selected
</button>
</div>
<div class="table-responsive card shadow-sm" role="region" tabindex="0" aria-labelledby="records-title">
<table class="table table-striped table-hover">
<caption class="text-start text-muted text-xs p-2">Customer record management</caption>
<thead>
<tr>
<th scope="col">Select</th>
<th scope="col">Customer</th>
<th scope="col">Plan</th>
<th scope="col">Owner</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="form-check">
<input
class="form-check-input"
name="recordIds"
type="checkbox"
value="acme-labs"
aria-labelledby="record-name"
checked />
</div>
</td>
<th scope="row" id="record-name">Acme Labs</th>
<td><span class="badge bg-primary">Pro</span></td>
<td>Alex Morgan</td>
<td><span class="badge bg-success">Active</span></td>
</tr>
</tbody>
</table>
</div>
<nav class="pagination" aria-label="Customer record pages">
<span class="pagination-item disabled">Previous</span>
<a class="pagination-item is-active" href="?page=1" aria-current="page">1</a>
<a class="pagination-item" href="?page=2">2</a>
<a class="pagination-item" href="?page=2">Next</a>
</nav>
</form>No records selected
Keep bulk actions in a stable location before rows are selected, but disable them with their native disabled state. Pair the unavailable actions with concise guidance that explains how to enable them.
Customer records
Choose records before applying a bulk action.
<section aria-labelledby="data-management-zero-title">
<header class="d-flex flex-wrap align-items-center gap-2 py-3 mb-3">
<div>
<h3 class="h4 mb-0" id="data-management-zero-title">Customer records</h3>
<p class="text-muted mb-0" id="data-management-zero-description">
<span>Choose records before applying a bulk action.</span>
</p>
</div>
<span class="badge bg-primary ms-auto">2 records</span>
</header>
<form action="/records/bulk" method="post" aria-label="Customer record bulk actions with no selection">
<div
class="card shadow-sm d-flex flex-column flex-sm-row align-items-sm-center gap-3 p-3 mb-3"
role="group"
aria-label="Unavailable bulk actions">
<div class="flex-fill">
<p class="h6 mb-0">No records selected</p>
<p class="text-muted text-sm mb-0">Select one or more rows to enable bulk actions.</p>
</div>
<div class="d-flex flex-column flex-sm-row gap-2">
<div class="menu" data-menu>
<button class="btn btn-outline btn-secondary btn-sm menu-trigger" type="button" disabled data-menu-trigger>
<span>Export selected</span>
</button>
<div class="menu-popup" role="menu" popover="manual" hidden data-menu-popup>
<button class="menu-item" type="submit" role="menuitem" name="action" value="export-csv">
<span class="menu-item-label">Export as CSV</span>
</button>
<button class="menu-item" type="submit" role="menuitem" name="action" value="export-pdf">
<span class="menu-item-label">Export as PDF</span>
</button>
</div>
</div>
<button class="btn btn-solid btn-primary btn-sm" type="submit" name="action" value="archive" disabled>
<span>Archive selected</span>
</button>
</div>
</div>
<div
class="table-responsive card shadow-sm"
role="region"
tabindex="0"
aria-labelledby="data-management-zero-title"
aria-describedby="data-management-zero-description">
<table class="table table-striped table-hover mb-0">
<caption class="text-start text-muted text-xs p-2">Customer records with no current selection</caption>
<thead>
<tr>
<th scope="col">
<div class="form-check">
<input class="form-check-input" id="zeroSelectAllRecords" type="checkbox" aria-label="Select all records on this page" />
</div>
</th>
<th scope="col">Customer</th>
<th scope="col">Plan</th>
<th scope="col">Owner</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="form-check">
<input class="form-check-input" id="zeroRecordAcme" name="recordIds" type="checkbox" value="acme-labs" aria-labelledby="zero-record-acme-name" />
</div>
</td>
<th scope="row" id="zero-record-acme-name">Acme Labs</th>
<td><span class="badge bg-primary">Pro</span></td>
<td>Alex Morgan</td>
<td><span class="badge bg-success">Active</span></td>
</tr>
<tr>
<td>
<div class="form-check">
<input class="form-check-input" id="zeroRecordNorthstar" name="recordIds" type="checkbox" value="northstar-studio" aria-labelledby="zero-record-northstar-name" />
</div>
</td>
<th scope="row" id="zero-record-northstar-name">Northstar Studio</th>
<td><span class="badge bg-inverse">Business</span></td>
<td>Morgan Lee</td>
<td><span class="badge bg-warning">Review needed</span></td>
</tr>
</tbody>
</table>
</div>
</form>
</section>No matching records
Keep the applied filters visible when they produce no results, then replace the table and pagination with the Empty State. Give users one direct way to broaden or clear the query.
<section aria-labelledby="empty-records-title">
<div class="d-flex align-items-center flex-wrap gap-2" role="group" aria-label="Active customer filters">
<span class="text-muted">Active filters:</span>
<span class="chip chip-primary chip-outline">
<span class="chip-label">Plan: Business</span>
<button class="chip-action" type="button" aria-label="Remove Business plan filter">
<!-- Decorative close icon -->
</button>
</span>
<span class="chip chip-primary chip-outline">
<span class="chip-label">Status: Paused</span>
<button class="chip-action" type="button" aria-label="Remove Paused status filter">
<!-- Decorative close icon -->
</button>
</span>
</div>
<div class="card shadow-sm">
<div
class="empty-state"
aria-labelledby="empty-records-title"
aria-describedby="empty-records-description">
<span class="empty-state-icon" aria-hidden="true">
<!-- Decorative search icon -->
</span>
<h3 class="empty-state-title" id="empty-records-title">No matching customer records</h3>
<p class="empty-state-description" id="empty-records-description">
No Business accounts currently have the Paused status.
</p>
<div class="empty-state-actions">
<a class="btn btn-solid btn-primary" href="/records">Clear all filters</a>
</div>
</div>
</div>
</section>