Skip to content
ShineUI
Install

TreeTable

A table with depth.

<sui-tree-table>DataStable

About

A chart of accounts or any outline with columns. Branches open and close, siblings sort at every level, a filter keeps the ancestors of its matches, a tick carries down a subtree, and a branch can load its children on open. aria-label or aria-labelledby on the host names it. Use sui-tree for rows that are labels, not records.

Usage

<sui-tree-table aria-label="Chart of accounts"></sui-tree-table> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); const el = document.querySelector("sui-tree-table"); el.columns = [ { key: "name", header: "Account", sortable: true, filter: true, flex: 2, minWidth: 220 }, { key: "type", header: "Type", muted: true, sortable: true, filter: true, width: 150 }, { key: "bal", header: "Balance", money: true, type: "number", sortable: true, filter: true, width: 160, format: (v) => { /* ... */ } }, ]; /* SuiDataTableColumn[] */ el.expanded = ["a", "a-cur"]; /* SuiKey[] */ el.addEventListener("suiSelectionChange", (e) => console.log(e.detail)); </script>
import { SuiTreeTable } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { const columns = [ { key: "name", header: "Account", sortable: true, filter: true, flex: 2, minWidth: 220 }, { key: "type", header: "Type", muted: true, sortable: true, filter: true, width: 150 }, { key: "bal", header: "Balance", money: true, type: "number", sortable: true, filter: true, width: 160, format: (v) => { /* ... */ } }, ]; /* SuiDataTableColumn[] */ const expanded = ["a", "a-cur"]; /* SuiKey[] */ return <SuiTreeTable aria-label="Chart of accounts" columns={columns} expanded={expanded} onSuiSelectionChange={(e) => console.log(e.detail)} />; }
<script setup> import { SuiTreeTable } from "@shineui/vue"; import "@shineui/core/shineui.css"; const columns = [ { key: "name", header: "Account", sortable: true, filter: true, flex: 2, minWidth: 220 }, { key: "type", header: "Type", muted: true, sortable: true, filter: true, width: 150 }, { key: "bal", header: "Balance", money: true, type: "number", sortable: true, filter: true, width: 160, format: (v) => { /* ... */ } }, ]; // SuiDataTableColumn[] const expanded = ["a", "a-cur"]; // SuiKey[] const onChange = (e) => console.log(e.detail); </script> <template> <SuiTreeTable aria-label="Chart of accounts" :columns="columns" :expanded="expanded" @sui-selection-change="onChange" /> </template>
import { Component } from "@angular/core"; import { SuiTreeTable } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiTreeTable], template: `<sui-tree-table aria-label="Chart of accounts" [(selection)]="selection" [columns]="columns" [expanded]="expanded"></sui-tree-table>`, }) export class Example { selection: SuiKey[] = []; columns = [ { key: "name", header: "Account", sortable: true, filter: true, flex: 2, minWidth: 220 }, { key: "type", header: "Type", muted: true, sortable: true, filter: true, width: 150 }, { key: "bal", header: "Balance", money: true, type: "number", sortable: true, filter: true, width: 160, format: (v) => { /* ... */ } }, ]; // SuiDataTableColumn[] expanded = ["a", "a-cur"]; // SuiKey[] }

Chart of accounts

columns and nodes are properties; a node carries its record in data, which the columns read by key. The first column indents by level and carries the twisty, and a branch row is drawn heavier than the rows under it. aria-label or aria-labelledby on the host names the treegrid.

<sui-tree-table aria-label="Chart of accounts"></sui-tree-table>
// setup(root): properties and events setup(root) { const t = root.querySelector('sui-tree-table'); t.columns = accountColumns(); t.nodes = accountNodes(); t.expanded = ['a', 'a-cur']; }

Checkbox selection

Ticking a branch ticks everything under it, and a branch whose children are only partly ticked draws a mixed box. selection holds only the keys the user ticked, because every ancestor is derived from the tree on each render, and suiSelectionChange carries it.

Nothing ticked.
<div style="display:grid;gap:10px"> <code id="tt-sel-log" style="font:460 12px/1.6 var(--font-sans);color:var(--ink-muted)">Nothing ticked.</code> <sui-tree-table id="tt-sel" selection-mode="checkbox"></sui-tree-table> </div>
// setup(root): properties and events setup(root) { const t = root.querySelector('#tt-sel'); const log = root.querySelector('#tt-sel-log'); t.columns = accountColumns(); t.nodes = accountNodes(); t.expanded = ['a', 'a-cur', 'l']; t.selection = ['a1']; t.addEventListener('suiSelectionChange', (e) => { log.textContent = e.detail.length === 0 ? 'Nothing ticked.' : `Stored keys: ${e.detail.join(', ')}.`; }); }

Sorting and filtering

A sortable header orders siblings at every level and leaves the tree's shape alone; sort-indicator all draws every glyph at rest. filter-display row puts a box under each header; a filter keeps and opens the ancestors of its matches, and one that matches nothing shows empty-filter-message.

<sui-tree-table id="tt-sort" filter-display="row" sort-mode="multiple" sort-indicator="all" empty-filter-message="No accounts match." gridlines></sui-tree-table>
// setup(root): properties and events setup(root) { const t = root.querySelector('#tt-sort'); t.columns = accountColumns(); t.nodes = accountNodes(); t.expanded = ['a', 'a-cur', 'a-fix', 'l', 'e']; t.sorts = [{ key: 'bal', dir: 'desc' }]; }

Loading a branch on demand

A node marked leaf false draws the twisty with nothing under it and emits suiLoad the first time it opens. The host answers by setting that node loading, which turns the twisty into a spinner, and then its children.

<sui-tree-table id="tt-lazy"></sui-tree-table>
// setup(root): properties and events setup(root) { const t = root.querySelector('#tt-lazy'); const children = { v: [ { key: 'v1', data: { name: 'Ridgeway Supply', type: 'Vendor', bal: 12480 } }, { key: 'v2', data: { name: 'Halstead Print', type: 'Vendor', bal: 3115.4 } }, { key: 'v3', data: { name: 'Northline Utilities', type: 'Vendor', bal: 806.22 } }, ], c: [ { key: 'c1', data: { name: 'Silver Hills Church', type: 'Customer', bal: 6420 } }, { key: 'c2', data: { name: 'Riverbend Dental Group', type: 'Customer', bal: 12480 } }, ], }; t.columns = accountColumns(); t.nodes = [ { key: 'v', data: { name: 'Vendors', type: '', bal: 16401.62 }, leaf: false }, { key: 'c', data: { name: 'Customers', type: '', bal: 18900 }, leaf: false }, ]; t.addEventListener('suiLoad', (e) => { const key = e.detail.key; t.nodes = patch(t.nodes, key, { loading: true }); setTimeout(() => { t.nodes = patch(t.nodes, key, { loading: false, children: children[key] }); }, 900); }); }

Events

expandAll and collapseAll are methods, and expanded is written before suiExpandedChange fires. It does not bubble, so listen on the tree table itself. Writing it from outside opens a branch without asking the host for anything, since the caller already knows which.

Nothing yet.
<div style="display:grid;gap:10px"> <code id="tt-log" style="font:460 12px/1.6 var(--font-sans);color:var(--ink-muted)">Nothing yet.</code> <div style="display:flex;gap:8px"> <sui-button id="tt-open" variant="outline" size="sm" label="Expand all"></sui-button> <sui-button id="tt-close" variant="outline" size="sm" label="Collapse all"></sui-button> </div> <sui-tree-table id="tt-events" density="compact" striped></sui-tree-table> </div>
// setup(root): properties and events setup(root) { const t = root.querySelector('#tt-events'); const log = root.querySelector('#tt-log'); t.columns = accountColumns(); t.nodes = accountNodes(); t.expanded = ['a']; t.addEventListener('suiExpandedChange', (e) => { log.textContent = `Open: ${e.detail.join(', ') || 'nothing'}.`; }); root.querySelector('#tt-open').addEventListener('click', () => t.expandAll()); root.querySelector('#tt-close').addEventListener('click', () => t.collapseAll()); }

Loading and empty

loading draws four shimmer rows in place of the tree, which is the whole tree waiting rather than one branch. With no nodes the table shows empty-message; a filter that matches none shows empty-filter-message instead, since an empty tree and a search that found nothing are two states.

<div style="display:grid;gap:16px"> <sui-tree-table id="tt-load" loading></sui-tree-table> <sui-tree-table id="tt-empty" empty-message="No accounts in this range."></sui-tree-table> </div>
// setup(root): properties and events setup(root) { root.querySelector('#tt-load').columns = accountColumns(); const e = root.querySelector('#tt-empty'); e.columns = accountColumns(); e.nodes = []; }

Keyboard

KeyAction
TabEnters the table at the focused row, else the first. The rows are one tab stop.
ArrowDown ArrowUpMoves the focused row to the next or previous visible row.
ArrowRightOpens a closed branch. On a branch that is already open, moves to its first child. Under dir="rtl" the pair swaps, so the arrow that points along the reading direction is always the forward one.
ArrowLeftCloses an open branch. Otherwise moves to the parent row.
Home EndFocuses the first or the last visible row.
PageUp PageDownMoves the focused row by one viewport.
SpaceTicks or clears the focused row, unless the selection mode is none.
Shift+clickOn a header, adds a sort term when sort-mode is multiple.
EscapeCloses the filter menu and returns focus to its funnel button.

API

<sui-tree-table>

Properties

PropertyAttributeTypeDefaultDescription
columnsproperty onlySuiDataTableColumn[][]Column definitions, exactly as sui-data-table takes them: key is the field read from a node's data, and the first column carries the indent and the twisty. Property, not attribute.
densitydensitySuiGridDensity"comfortable" | "compact" | "standard"'standard'Row height and cell padding.
emptyFilterMessageempty-filter-messagestringstring | undefinedText for a tree whose nodes the filter row, the filter menu or globalFilter narrowed to none. An empty list and a search that found nothing are two states, so this is a second prop; an empty string silences it the same way.
emptyMessageempty-messagestringstring | undefinedText for an empty tree. An empty string draws the empty row without words, for a host that says it once above the table.
expandedproperty onlySuiKey[][]Keys of the open branches. Mutable; updated before suiExpandedChange fires. While a filter is on, the ancestors of its matches open as well without being written here. Property, not attribute.
filterDisplayfilter-display"menu" | "none" | "row"'none'Where the filter controls live: nowhere, in a row under the headers, or behind a funnel button on each header.
filterModefilter-modeSuiGridTreeFilterMode"lenient" | "strict"'lenient'What a filter does below a match. lenient keeps a matching branch's whole subtree, so opening it shows the branch as it really is; strict keeps only the descendants that match in their own right. An ancestor of a match is kept either way, or the match is unreachable.
filterModelproperty onlySuiGridFilterModelSuiGridFilterModel | undefinedThe filter model: one rule per column plus an optional global term, as sui-data-table takes it. Mutable; the filter row and the filter menu rewrite it before suiFilter fires. Property, not attribute.
globalFilterglobal-filterstringstring | undefinedOne term searched across several columns at once. Set it from a search box of your own; it is merged into filterModel as the global term.
globalFilterFieldsproperty onlystring[]string[] | undefinedColumns the global term searches. Defaults to every column. Property, not attribute.
gridlinesgridlinesbooleanfalseDraws a rule between columns as well as between rows.
loadingloadingbooleanfalseRenders four shimmer rows in place of the tree. A single branch waiting on its children uses that node's own loading instead. Reflected, so a page can style the wait.
nodesproperty onlySuiGridTreeNode[][]The node tree (key, data, children). data is the record the columns read, so a column written for a flat table works here unchanged; leaf: false marks a branch whose children have not arrived. Property, not attribute.
nullOrdernull-orderSuiGridNullOrder"first" | "last"'last'Where blanks land among their siblings, in both directions.
selectionproperty onlySuiKey[][]The keys the user has ticked. Under checkbox a branch is stored only when it was ticked whole: the mixed and fully ticked states of every ancestor are derived from the tree on each render, so there is no second copy to go stale when the tree changes shape. Mutable; updated before suiSelectionChange fires. Property, not attribute.
selectionModeselection-mode"checkbox" | "none" | "single"'none'none, single (one highlighted row) or checkbox (a box per row, a select-all box in the header, and a tick that carries down a whole subtree).
sortIndicatorsort-indicator"all" | "sorted"'sorted'Which sortable headers draw a glyph at rest, exactly as sui-data-table takes it: sorted draws the arrow on the sorted column only and the rest appear on hover and focus; all draws a glyph on every sortable header.
sortModesort-mode"multiple" | "single"'single'Whether a header click replaces the sort or adds to it. Under multiple a Shift+click adds a term; under either, a third click on a column drops it.
sortsproperty onlySuiGridSort[][]Sort terms, applied in order. Siblings are ordered at every level and the shape of the tree is left alone, so a sorted branch keeps its children. Mutable; a header click rewrites it before suiSort fires. Property, not attribute.
stripedstripedbooleanfalseTints every second row.

Events

EventDetailReactVueDescription
suiExpandedChangeSuiKey[]onSuiExpandedChange@sui-expanded-changeFires when a branch opens or closes; detail is the array of open keys. Does not bubble.
suiFilterSuiGridFilterModelonSuiFilter@sui-filterFires when the filter row or the filter menu changes the filter; detail is the whole model. Does not bubble.
suiLoadSuiGridTreeNodeonSuiLoad@sui-loadAsks the host for a branch's children: fires when a node marked leaf: false that has none yet and is not already loading opens. Detail is the node. Answer by setting its loading, then its children, and assigning a new nodes array. Writing expanded from outside opens a branch without asking, since the caller already knows which.
suiSelectionChangeSuiKey[]onSuiSelectionChange@sui-selection-changeFires when the selection changes; detail is the new selection, the ticked keys. Does not bubble.
suiSortSuiGridSort[]onSuiSort@sui-sortFires when a header click changes the sort; detail is the new ordered term list. Does not bubble.

Methods

MethodSignatureDescription
collapseAll()collapseAll() => Promise<void>Closes every branch.
expandAll()expandAll() => Promise<void>Opens every branch, including branches nothing has looked inside yet.
setFilter()setFilter(model: SuiGridFilterModel) => Promise<void>Applies a whole filter model, as the table inside does, and emits suiFilter. What sui-filter-builder calls.
setFocus()setFocus() => Promise<void>Focuses the row that holds the tree's one tab stop: the row focused last, or the first row in view. el.focus() on the host does the same.

Types

SuiDataTableColumn interfaceA column, plus the three things a table does that a grid does not: filter it from the header, edit it in place, and total it in the footer. Everything else comes from SuiGridColumn.
keystringUnique identity, and the row field read unless field or value says otherwise.
headerstringColumn heading.
headerSr?stringHeading read by assistive technology when header is empty: an actions column shows no words and still names itself. Ignored when header has text.
field?stringRow field to read, when it is not key.
value?(row: SuiGridRow) => unknownComputed value for sorting, filtering and export. Takes precedence over field; a column with only a render and no value sorts and exports by its raw field, which is usually wrong.
render?(row: SuiGridRow, key: SuiKey) => SuiGridCellValueCell content. A string renders as text; an element is mounted into the cell. Called only for cells inside the rendered window. Property, not attribute.
type?SuiGridValueTypeDrives the default comparator, the default filter match modes and the default alignment.
align?SuiGridAlignA side of the screen to align to, in either reading direction. Leave it unset for reading order: text at the inline start, numbers and money at the inline end.
money?booleanAligned to the inline end, tabular numerals, weight 640. Implies type: 'number' for comparison unless the column says otherwise, because a money column holds an amount.
nowrap?booleanOne line, clipped with an ellipsis, and the full value on the cell's title.
width?numberStarting width in px. Omit to let flex share the space.
minWidth?number
maxWidth?number
flex?numberShare of the space left after fixed widths. flex: 1 on two columns splits it evenly.
sortable?boolean
resizable?booleanDraggable edge on the header. Off by default; a resized column drops its flex.
hidden?booleanExcluded from the render, from export and from the keyboard, but kept in the model so a column toggle can bring it back without the caller rebuilding the array.
pin?SuiGridPinPins the column to an edge. Pinned columns are never windowed away.
compare?(a: unknown, b: unknown) => numberCustom comparator; overrides type. Return negative, zero or positive.
format?(value: unknown, row: SuiGridRow) => stringFormats the value for text: the cell when there is no render, the export, and the clipboard. Keep it cheap; it runs once per visible cell per render. Without it a number or money column shows a plain figure grouped and marked in the page's locale (1,234.5, 1.234,5), while the export, the clipboard and an edit keep the plain figure (1234.5).
muted?booleanDrawn in --ink-muted: a memo, an account type, anything secondary.
headerTitle?stringHeader tooltip, for a column whose heading had to be short.
editable?booleanOpts a column out of in-cell editing on a grid that has it on. A column that draws its own cell is never editable: there is no text for an editor to stand in for.
cellClass?(value: unknown, row: SuiGridRow, index: number) => string | undefinedExtra classes for this column's cells, per row. Called once per visible cell per render, so keep it cheap: return a stable string rather than building one. The grid's own classes are always applied; this adds to them.
filter?booleanOffers this column a filter control, in the filter row or the filter menu. Ignored while the element's filterDisplay is none.
matchMode?SuiGridMatchModeMatch mode the column's filter opens with. Defaults by type: contains for text, equals for numbers and booleans, dateIs for dates.
filterOptions?readonly (string | { value: string; label: string; })[]The values a status-like column holds. With them, the column's filter menu is a checklist of these values, writing an in rule, instead of a list of conditions. A bare string is its own value and label. The filter row ignores them and keeps its text box.
editor?SuiGridEditorThe control this column opens for editing. A plain text input when it is absent. Named by value rather than by a string, so an application that edits only text never carries the date picker: see the note at the top of editing.ts.
validator?SuiGridValidatorChecked when an edit commits. Returning a message refuses the commit and keeps the editor open with the message beside it.
SuiGridAlign typeCell text alignment. A side named here is a side of the screen in either reading direction. Left unset, a money or number column sits at the inline end and everything else at the inline start, so the default mirrors under dir="rtl".
No members.
SuiGridCellValue typeWhat a cell renderer may return. A string is text; an element is appended to the cell. Shared with utils/render-content.ts, which does the mounting.
No members.
SuiGridColumn interfaceOne column. key is both the field read from the row and the column's identity, so it must be unique across the set; field overrides the field when the two need to differ (two columns over the same field, or a computed column with no field at all).
keystringUnique identity, and the row field read unless field or value says otherwise.
headerstringColumn heading.
headerSr?stringHeading read by assistive technology when header is empty: an actions column shows no words and still names itself. Ignored when header has text.
field?stringRow field to read, when it is not key.
value?(row: SuiGridRow) => unknownComputed value for sorting, filtering and export. Takes precedence over field; a column with only a render and no value sorts and exports by its raw field, which is usually wrong.
render?(row: SuiGridRow, key: SuiKey) => SuiGridCellValueCell content. A string renders as text; an element is mounted into the cell. Called only for cells inside the rendered window. Property, not attribute.
type?SuiGridValueTypeDrives the default comparator, the default filter match modes and the default alignment.
align?SuiGridAlignA side of the screen to align to, in either reading direction. Leave it unset for reading order: text at the inline start, numbers and money at the inline end.
money?booleanAligned to the inline end, tabular numerals, weight 640. Implies type: 'number' for comparison unless the column says otherwise, because a money column holds an amount.
nowrap?booleanOne line, clipped with an ellipsis, and the full value on the cell's title.
width?numberStarting width in px. Omit to let flex share the space.
minWidth?number
maxWidth?number
flex?numberShare of the space left after fixed widths. flex: 1 on two columns splits it evenly.
sortable?boolean
resizable?booleanDraggable edge on the header. Off by default; a resized column drops its flex.
hidden?booleanExcluded from the render, from export and from the keyboard, but kept in the model so a column toggle can bring it back without the caller rebuilding the array.
pin?SuiGridPinPins the column to an edge. Pinned columns are never windowed away.
compare?(a: unknown, b: unknown) => numberCustom comparator; overrides type. Return negative, zero or positive.
format?(value: unknown, row: SuiGridRow) => stringFormats the value for text: the cell when there is no render, the export, and the clipboard. Keep it cheap; it runs once per visible cell per render. Without it a number or money column shows a plain figure grouped and marked in the page's locale (1,234.5, 1.234,5), while the export, the clipboard and an edit keep the plain figure (1234.5).
muted?booleanDrawn in --ink-muted: a memo, an account type, anything secondary.
headerTitle?stringHeader tooltip, for a column whose heading had to be short.
editable?booleanOpts a column out of in-cell editing on a grid that has it on. A column that draws its own cell is never editable: there is no text for an editor to stand in for.
cellClass?(value: unknown, row: SuiGridRow, index: number) => string | undefinedExtra classes for this column's cells, per row. Called once per visible cell per render, so keep it cheap: return a stable string rather than building one. The grid's own classes are always applied; this adds to them.
filter?booleanOffers this column a filter control, in the filter row or the filter menu. Ignored while the element's filterDisplay is none.
matchMode?SuiGridMatchModeMatch mode the column's filter opens with. Defaults by type: contains for text, equals for numbers and booleans, dateIs for dates.
filterOptions?readonly (string | { value: string; label: string; })[]The values a status-like column holds. With them, the column's filter menu is a checklist of these values, writing an in rule, instead of a list of conditions. A bare string is its own value and label. The filter row ignores them and keeps its text box.
editor?SuiGridEditorThe control this column opens for editing. A plain text input when it is absent. Named by value rather than by a string, so an application that edits only text never carries the date picker: see the note at the top of editing.ts.
validator?SuiGridValidatorChecked when an edit commits. Returning a message refuses the commit and keeps the editor open with the message beside it.
SuiGridDensity typeRow height and cell padding. The three stops are the library's control heights, so a grid row lines up with the inputs beside it.
No members.
SuiGridEditor interfaceA control the grid mounts into a cell, focuses, and reads back when the edit commits. In sui-data-grid focus leaving the control commits, and focus in the list or calendar the control opened has not left it, so a ShineUI picker works as an editor.
mount(ctx: SuiGridEditorContext) => HTMLElementBuilds the control, populated and ready. The grid mounts it in the cell and focuses it.
read(el: HTMLElement) => stringThe text to commit, read from the element mount returned.
handlesKey?(e: KeyboardEvent, el: HTMLElement) => booleanOptional: keys this editor consumes itself, so the grid does not also act on them.
SuiGridEditorContext interfaceWhat an editor is given when it opens.
valueunknownThe raw value from the row.
textstringWhat the cell was showing, which is what a text editor seeds with.
columnSuiGridColumn
rowSuiGridRow
seed?stringSeed text when the editor was opened by a printable keystroke, else undefined.
SuiGridFilterCondition interfaceOne condition of an advanced filter: a column, a mode and a value, the same test a constraint makes, with the column it reads named beside it.
keystring
matchModeSuiGridMatchMode
value?unknown
SuiGridFilterConstraint interfaceOne test. value carries whatever the mode needs: a scalar, an array for in and notIn, a two-element [from, to] for between, and nothing at all for empty and notEmpty.
value?unknown
matchModeSuiGridMatchMode
SuiGridFilterGroup interfaceConditions and groups joined by one operator, to any depth: "Owner is Davon, and any of (health is Critical, no next meeting, no interaction)". What sui-filter-builder edits, and the one shape in the model that can join two columns with or.
operator'and' | 'or'
items(SuiGridFilterCondition | SuiGridFilterGroup)[]
SuiGridFilterModel interfaceThe whole filter state. Rules are keyed by column so a header can ask "is this column filtered" in one lookup; the global term is a sibling rather than a magic key inside the map, because it is a different shape and a map that holds two shapes cannot be typed. tree holds what only a tree can say, conditions across columns joined by or or nested; the three are joined by and.
rules?Readonly<Record<string, SuiGridFilterRule>>
global?SuiGridGlobalFilter
tree?SuiGridFilterGroup
SuiGridFilterRule interfaceEvery constraint on one column, and how they combine. and is the default a filter menu opens with; or is what a user reaches for when one column can hold two acceptable answers.
keystringThe column this rule filters. It is repeated inside the rule, rather than being left to the map key in SuiGridFilterModel, because a rule also travels alone in an event detail and in saved state, where there is no map key to read. The evaluator reads this field, so the two can never quietly disagree about which column a rule applies to.
operator'and' | 'or'
constraintsSuiGridFilterConstraint[]
SuiGridGlobalFilter interfaceOne term searched across several columns at once. keys is required rather than defaulting to every column, for the same reason PrimeVue makes globalFilterFields explicit: a computed column's value function would otherwise be called once per row per keystroke without anyone having asked for it.
valuestring
keysreadonly string[]
matchMode?SuiGridMatchModeDefaults to contains.
SuiGridMatchMode typeHow one constraint tests a value. Declared here rather than in filter.ts because a column names one and every element reads it, which is what this file is for; the evaluator that implements them is in filter.ts, which re-exports this so both can be imported together. The first sixteen are PrimeVue's FilterMatchMode verbatim. Three are additions, and they are additions rather than oversights: notIn because in without its negation is an odd half of a pair, and empty / notEmpty because "rows with no memo" is the filter a ledger reaches for most and PrimeVue cannot express it at all (an empty filter value means "no filter" there, so emptiness is exactly the one thing a value-carrying constraint can never ask about).
No members.
SuiGridNullOrder typeWhere nulls and blanks land, independent of direction: last keeps empties out of the way in both directions, which is what a ledger wants.
No members.
SuiGridPin typeWhich edge a column is pinned to, if any. The grid renders a pane per edge; the table uses position: sticky cells, because a native table cannot be split into panes.
No members.
SuiGridRow typeA row is the host's own record. The elements read fields by column key, print them and compare them; they never assume a shape beyond that.
No members.
SuiGridSort interfaceOne sort term. The elements sort by an ordered list of these, so single-column sort is a list of one and no second code path exists for it.
keystring
dirSuiGridSortDir
SuiGridSortDir type
No members.
SuiGridTreeFilterMode typeHow a filter treats a branch whose own row does not match but whose descendants do.
No members.
SuiGridTreeNode interfaceOne node. data is the record the columns read, exactly as a flat row is, so a column definition written for a table works unchanged over a tree.
keySuiKey
dataSuiGridRow
children?SuiGridTreeNode[]
leaf?booleanfalse marks a branch whose children have not arrived: it draws the twisty and asks for them the first time it opens. Leave it unset for a node that is settled either way.
loading?booleanShows the branch is fetching its children.
SuiGridValidator typeReturns null when the value is acceptable, or the message to show when it is not.
No members.
SuiGridValueType typeHow a column's values are compared, formatted and filtered when the column does not say otherwise. text is the fallback for anything unrecognised.
No members.
SuiKey typeA record's or an item's key wherever the library identifies one: a row, a tree node, a list item, a selected value. Numbers stay numbers, so a numeric id round-trips through selection, the events and a framework binding without turning into a string.
No members.

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

Color1

--ink

Typography1

Ag--font-sans

Every name above is listed with its value and its role in Foundations.

See also