Mantine React Table Accessibility
Permalink to "Mantine React Table Accessibility"Mantine React Table (MRT) combines TanStack Table’s data logic with Mantine’s components into a feature-rich table: sorting, filtering, pagination, row selection, editing, column hiding and more, with a toolbar of icon buttons. It renders a semantic HTML table by default, which is a strong starting point for screen reader users. The accessibility work is mostly in the surrounding chrome — icon-only toolbar buttons, column action menus, filter inputs — and in the announcements that tell users what their actions did.
This guide belongs to React data grid libraries.
Spec reference
Permalink to "Spec reference"- Semantic table —
table,thead,th,tbody,td; headers announced by screen readers in browse mode. aria-sorton sortable header cells (verify in your version).- Toolbar buttons — icon buttons need accessible names (SC 4.1.2); MRT uses Mantine
ActionIconwith tooltips — check that names are present, not only tooltips. - SC 4.1.3 (AA) — result counts after filtering, sorting and pagination.
- SC 2.4.7, 1.4.11 (AA) — focus visibility in the Mantine theme.
When to use — and when not to
Permalink to "When to use — and when not to"Use MRT when you are already on Mantine and need a full-featured table quickly. Keep the semantic table rendering for data that users mainly read and filter. If you enable cell-level keyboard navigation and editing, verify that roles and focus behave consistently as a grid.
Do not leave toolbar icon buttons with tooltip-only names. The misapplication: enabling every toolbar feature (density toggle, full-screen, column hiding, global filter) without checking names and keyboard paths — a dozen unlabelled icons before the table even starts.
Annotated code example
Permalink to "Annotated code example"import { MantineReactTable, useMantineReactTable } from 'mantine-react-table';
function Invoices({ data }) {
const [status, setStatus] = useState('');
const table = useMantineReactTable({
columns, data,
enableRowSelection: true,
mantineTableProps: { 'aria-labelledby': 'inv-h' }, // name the table (SC 4.1.2)
mantineSearchTextInputProps: { 'aria-label': 'Search invoices', placeholder: 'Search invoices' },
mantineFilterTextInputProps: ({ column }) => ({ 'aria-label': `Filter ${column.columnDef.header}` }),
mantineSelectCheckboxProps: ({ row }) => ({ 'aria-label': `Select invoice ${row.original.id}` }),
mantineSelectAllCheckboxProps: { 'aria-label': 'Select all invoices' },
onSortingChange: (updater) => { setSorting(updater); /* derive message after state update */ },
});
useEffect(() => {
const rows = table.getFilteredRowModel().rows.length;
const s = table.getState().sorting[0];
setStatus(`${rows} invoices${s ? `, sorted by ${s.id} ${s.desc ? 'descending' : 'ascending'}` : ''}`);
}, [table.getState().sorting, table.getState().columnFilters, table.getState().globalFilter]);
return (<>
<h2 id="inv-h">Invoices</h2>
<MantineReactTable table={table} />
<p role="status" className="visually-hidden">{status}</p> {/* SC 4.1.3 */}
</>);
}
Prop names follow MRT’s mantine*Props convention; check them against your installed version.
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"| Interaction | Expected behaviour | Expected announcement |
|---|---|---|
| Tab through toolbar | Each control named | “Search invoices, edit”, “Show/Hide columns, button” |
| Enter on sortable header | Sort | Header with sort state; status message |
| Space on row checkbox | Toggle selection | “Select invoice INV-1042, checkbox, checked” |
| Column actions menu | Opens menu; arrows navigate | Menu items |
| Table navigation commands | Read cells with headers | Native table behaviour |
Integration context
Permalink to "Integration context"MRT’s data logic is TanStack Table, so the guidance in accessible sorting with TanStack Table and row selection in TanStack Table React applies. Toolbar naming follows naming icon-only row action buttons. Column hiding follows column visibility menus and column choosers.
Gotchas
Permalink to "Gotchas"Full-screen mode. Toggling full-screen re-renders the table; check that focus stays on the toggle or moves predictably.
Tooltips as names. Mantine tooltips may not provide accessible names on their own; verify with the accessibility tree.
Editing modes. MRT offers several editing modes (modal, row, cell, table); each has different focus behaviour — test the one you use.
Common mistakes
Permalink to "Common mistakes"- Unlabelled column filter inputs.
- Toolbar icon buttons with tooltip-only names.
- Generic “Toggle select row” checkbox labels.
- No result announcements.
Version and upgrade notes
Permalink to "Version and upgrade notes"MRT follows Mantine major versions; upgrades can change component internals and prop names. After upgrading, re-check accessible names on toolbar controls and filter inputs with the accessibility tree, since those come from component props and defaults that may move.
Worked example
Permalink to "Worked example"An internal admin tool used MRT with every toolbar feature enabled. An audit found 14 unnamed or generically named controls before the table, unlabelled column filters and silent filtering. Passing aria-labels through MRT’s props, renaming selection checkboxes per record and adding a status region took half a day. The team also disabled the density and full-screen toggles, which nobody used, reducing the toolbar to four clearly named controls.
A minimal accessible MRT configuration
Permalink to "A minimal accessible MRT configuration"For most internal tools, an accessible MRT configuration needs only a handful of decisions: keep semantic table rendering; enable the features users actually need (often search, column filters, sorting, selection and pagination) and disable the rest; supply names for every enabled control through the mantine*Props options; label selection checkboxes with the record identifier; add one status region driven by table state; and verify focus styles in your Mantine theme. Document this preset once and reuse it, because MRT’s flexibility otherwise produces a slightly different — and differently broken — table in every screen.
Testing checklist
Permalink to "Testing checklist"Design system notes
Permalink to "Design system notes"Create a project-level MRT preset that supplies names for every control, an announcer and your theme’s focus styles, and disables rarely used toolbar features by default.
FAQ
Permalink to "FAQ"Does Mantine React Table render a real table?
Yes, by default it renders semantic table markup, which works well with screen reader table commands.
How do I name the toolbar buttons?
Through MRT’s component props for each control, or by overriding the toolbar rendering; verify names in the accessibility tree.
Does MRT announce sorting?
Headers can expose sort state; add a status message for the result.
Is cell keyboard navigation available?
Recent versions offer keyboard navigation options; test them and keep roles consistent if you enable them.
How do I handle large data?
Use MRT’s virtualization features and test screen reader position announcements.
Should I use MRT or plain TanStack Table?
MRT is faster to start; plain TanStack gives full control of markup. Both can be made accessible.
How do I check that names come through?
Inspect each control in the browser’s accessibility pane after rendering; tooltips and title attributes do not count as reliable names.
Does MRT support right-to-left layouts?
Mantine supports RTL; verify that arrow-key behaviour and column order match the reading direction in your configuration.
Related
Permalink to "Related"- Accessible sorting with TanStack Table — the underlying logic
- MUI X Data Grid audit — a grid-role alternative
- Naming icon-only buttons — toolbar names