# Table `{% table %}` is a **built-in** tag for data tables — the Mantine Table element. A plain Markdown table still works; reach for this tag when you want striping, borders, row hover, a caption, or a sticky header. Give the header cells in `head` (pipe-separated) and the body in `rows` (rows separated by `;` or newlines, cells by `|`, or a JSON array of arrays); each cell renders inline Markdown. Use it as `{% table %}` in Markdown, or call it from Python logic (loops, snippets) via `component('aardvark', 'table', …)`. ## Demonstrations A basic table needs only `head` and `rows`:
Source: Markdown ```aardvark {% table head='Name | Role | Status' rows='Ada | Engineer | Active ; Grace | Admiral | Active' %} ``` Source: Python ```python component('aardvark', 'table', head='Name | Role | Status', rows='Ada | Engineer | Active ; Grace | Admiral | Active') ``` ### Striping and hover `striped` shades alternate rows (pass `odd` or `even` to choose which) and `highlightOnHover` lights up the row under the cursor:
Source: Markdown ```aardvark {% table striped=true highlightOnHover=true head='Package | Version' rows='aardvark | 0.1.10 ; mantine | 9.x ; react | 19' %} ``` Source: Python ```python component('aardvark', 'table', striped=True, highlightOnHover=True, head='Package | Version', rows='aardvark | 0.1.10 ; mantine | 9.x ; react | 19') ``` ### Borders Toggle the outer border (`withTableBorder`), column dividers (`withColumnBorders`), and row dividers (`withRowBorders`, on by default — set `false` to remove them):
Source: Markdown ```aardvark {% table withTableBorder=true withColumnBorders=true head='Method | Path' rows='GET | /pets ; POST | /pets ; DELETE | /pets/{id}' %} ``` Source: Python ```python component('aardvark', 'table', withTableBorder=True, withColumnBorders=True, head='Method | Path', rows='GET | /pets ; POST | /pets ; DELETE | /pets/{id}') ``` ### Caption and inline Markdown Add a `caption` (set `captionSide` to `top` or `bottom`, the default). Cells render inline Markdown, so `` `code` `` and `**bold**` format:
Source: Markdown ```aardvark {% table caption='Build stats' captionSide='bottom' withTableBorder=true head='Stage | Time' rows='`render` | **2.4s** ; `bundle` | 0.3s' %} ``` Source: Python ```python component('aardvark', 'table', caption='Build stats', captionSide='bottom', withTableBorder=True, head='Stage | Time', rows='`render` | **2.4s** ; `bundle` | 0.3s') ``` ### Spacing, width, and JSON rows `horizontalSpacing` / `verticalSpacing` size the cell padding with Mantine tokens, and `minWidth` sets the width below which the table scrolls horizontally. Pass `rows` as a JSON array of arrays when a cell contains a literal `|` or `;`:
Source: Markdown ```aardvark {% table horizontalSpacing='xl' verticalSpacing='md' minWidth='30rem' head='Key | Default' rows='[["timeout", "`30 ; per call`"], ["retries", "3"]]' %} ``` Source: Python ```python component('aardvark', 'table', horizontalSpacing='xl', verticalSpacing='md', minWidth='30rem', head='Key | Default', rows='[["timeout", "`30 ; per call`"], ["retries", "3"]]') ``` ### Sticky header `stickyHeader` pins the header while the body scrolls; `maxHeight` caps the scroll window (px, default 320) and `stickyHeaderOffset` pushes the pinned header down past a fixed navbar:
Source: Markdown ```aardvark {% table stickyHeader=true maxHeight=140 striped=true head='Build | Result' rows='1.0.0 | pass ; 1.0.1 | pass ; 1.0.2 | fail ; 1.0.3 | pass ; 1.0.4 | pass ; 1.0.5 | pass' %} ``` Source: Python ```python component('aardvark', 'table', stickyHeader=True, maxHeight=140, striped=True, head='Build | Result', rows='1.0.0 | pass ; 1.0.1 | pass ; 1.0.2 | fail ; 1.0.3 | pass ; 1.0.4 | pass ; 1.0.5 | pass') ``` ## With other components Build a table from a loop in Python, or pass [Text](/components/typography/text/) and [Title](/components/typography/title/) inside a containing layout. Here the rows come from a Python list, joined into the `;`/`|` shorthand: Release matrix
Source: Markdown ```aardvark {% title order=4 mb='sm' %}Release matrix{% endTitle %} {% table withTableBorder=true striped=true head='Version | Channel' rows='0.1.8 | stable ; 0.1.9 | stable ; 0.1.10 | latest' %} ``` Source: Python ```python releases = [('0.1.8', 'stable'), ('0.1.9', 'stable'), ('0.1.10', 'latest')] rows = ' ; '.join(f'{v} | {c}' for v, c in releases) component('aardvark', 'title', children='Release matrix', order=4, mb='sm') component('aardvark', 'table', withTableBorder=True, striped=True, head='Version | Channel', rows=rows) ``` ## Attributes Omit any attribute to take its Mantine default. | Attribute | Valid values | Description | | --- | --- | --- | | `head` | String, pipe-separated (`A \| B \| C`) | Header cells; each renders inline Markdown. Empty omits the ``. | | `rows` | String, or JSON array of arrays | Body rows — rows split on `;` or newlines, cells on `\|`; or `[["a","b"],…]`. Each cell renders inline Markdown. | | `caption` | String | A caption rendered above or below the table. | | `captionSide` | `top`, `bottom` | Which side the caption sits on. Default `bottom`. | | `striped` | `true`, `false`, `odd`, `even` | Shade alternate rows. A bare `striped` flag or `true` stripes odd rows; `odd` / `even` choose which. Default `false`. | | `highlightOnHover` | `true`, `false` | Highlight the row under the cursor. Default `false`. | | `withTableBorder` | `true`, `false` | Outer border around the whole table. Default `false`. | | `withColumnBorders` | `true`, `false` | Vertical dividers between columns. Default `false`. | | `withRowBorders` | `true`, `false` | Horizontal dividers between rows. Default `true`; set `false` to remove them. | | `stickyHeader` | `true`, `false` | Pin the header while the table body scrolls. Default `false`. | | `stickyHeaderOffset` | Integer (px) | Offset for the sticky header, e.g. to clear a fixed navbar. | | `maxHeight` | Integer (px) | Cap the sticky-header scroll window height. Default 320. | | `horizontalSpacing` | Mantine size token (`xs`–`xl`) or CSS value | Horizontal cell padding. | | `verticalSpacing` | Mantine size token (`xs`–`xl`) or CSS value | Vertical cell padding. | | `minWidth` | CSS width (`30rem`, `600px`) | Minimum width before the table scrolls horizontally. | ## CSS Selectors Target the rendered element through its island marker, `[data-aardvark-island="Table"]`, or through the Mantine Styles API classes. (Table uses element-named parts rather than a `-root`.) The relevant classes: ```css /* Every rendered Table carries this island marker */ [data-aardvark-island="Table"] { } /* Mantine Styles API classes */ .mantine-Table-table { } .mantine-Table-thead { } .mantine-Table-tbody { } .mantine-Table-tr { } .mantine-Table-th { } .mantine-Table-td { } ``` ## Injecting Attributes `attr={…}` forwards raw HTML attributes — including event handlers — straight onto the rendered element, so you can wire DOM behavior the tag does not expose. The handler can be a full multi-line script, not just one expression — this one logs the value to the console and shows it in an alert:
Source: Markdown ```aardvark {% table head='Name | Role | Status' rows='Ada | Engineer | Active ; Grace | Admiral | Active' attr={'onclick': ''' const value = this.innerText; console.log('attr demo value:', value); alert(value); '''} %} ``` Source: Python ```python component('aardvark', 'table', head='Name | Role | Status', rows='Ada | Engineer | Active ; Grace | Admiral | Active', attr={'onclick': ''' const value = this.innerText; console.log('attr demo value:', value); alert(value); '''}) ```