enes

Table

Table displays sets of two dimensional data. Every part is a primitive that can be composed freely, so the table itself stays unopinionated about where the data comes from.

File Author Last updated
Meeting notes
Max Mustermann 7h ago
Thursday presentation
Erika Mustermann Yesterday at 1:45 PM
Training recording
John Doe Yesterday at 1:45 PM
Purchase order
Jane Doe Tue at 9:30 AM

The components are deliberately low level: sorting, selection and filtering are not built in. The table renders what you hand it and reports the state you give it, so any data layer drives it without fighting an internal engine.

To create a table, you will need to use the following components:

  • Table: The root component that creates the context every other part reads: the size, whether the parts render as native table elements, and whether the columns are sortable.
  • TableHeader: The header section of the table.
  • TableHeaderCell: A column header. It turns into a sort button when the column is sortable.
  • TableBody: The body section of the table, where the rows of data live.
  • TableRow: A row of the table. It can be filled to mark it as selected.
  • TableCell: A single cell of a row.

Other components that can be used within the table include:

  • TableCellLayout: Lays a cell out as media, main content and an optional description.
  • TableSelectionCell: A cell holding the checkbox or radio button that reports whether the row is selected.
  • TableCellActions: Actions pinned to the end of a cell, revealed while the row is hovered or holds the focus.

Usage

Compose the parts the same way you would write the markup by hand: a header row of header cells, then one row of cells per item.

<script>
	import { Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell } from 'fluentui-svelte';

	const columns = ['File', 'Author', 'Last updated'];
	const items = [{ file: 'Meeting notes', author: 'Max Mustermann', lastUpdated: '7h ago' }];
</script>

<Table aria-label="Files">
	<TableHeader>
		<TableRow>
			{#each columns as column (column)}
				<TableHeaderCell>{column}</TableHeaderCell>
			{/each}
		</TableRow>
	</TableHeader>
	<TableBody>
		{#each items as item (item.file)}
			<TableRow>
				<TableCell>{item.file}</TableCell>
				<TableCell>{item.author}</TableCell>
				<TableCell>{item.lastUpdated}</TableCell>
			</TableRow>
		{/each}
	</TableBody>
</Table>

Size

Use `size` to set the row height and the type scale of every part at once.

File Author Last updated
Meeting notes
Max Mustermann 7h ago
Thursday presentation
Erika Mustermann Yesterday at 1:45 PM
File Author Last updated
Meeting notes
Max Mustermann 7h ago
Thursday presentation
Erika Mustermann Yesterday at 1:45 PM
File Author Last updated
Meeting notes
Max Mustermann 7h ago
Thursday presentation
Erika Mustermann Yesterday at 1:45 PM

Sort

`sortable` on the table turns every header cell into a button, and a single cell can opt in or out with its own `sortable`. The table never sorts the data: give each header the `sortDirection` it should announce, handle `onclick`, and hand back the rows in the order you want.

Last updated
Meeting notes
Max Mustermann 7h ago
Purchase order
Jane Doe Tue at 9:30 AM
Thursday presentation
Erika Mustermann Yesterday at 1:45 PM
Training recording
John Doe Yesterday at 1:45 PM

Multiple Selection

The selection cell displays the selection, it does not own it. A click on the indicator also reaches the row underneath, so the row is the single place to wire `onclick`. Mark it with `aria-selected`, fill it with `appearance="brand"`, and feed `checked` back from your own state.

File Author
Meeting notes
Max Mustermann
Thursday presentation
Erika Mustermann
Training recording
John Doe
Purchase order
Jane Doe

Single Selection

Set `type="radio"` on the selection cell when only one row can be selected at a time. Give every indicator the same `name` so the browser groups them, and use `invisible` on the header cell to keep the column aligned without offering a "select all".

File Author
Meeting notes
Max Mustermann
Thursday presentation
Erika Mustermann
Training recording
John Doe
Purchase order
Jane Doe

Subtle Selection

`subtle` keeps the indicator out of sight until the row is hovered, holds the focus, or is selected. It calms a dense table without losing the affordance.

File Author
Meeting notes
Max Mustermann
Thursday presentation
Erika Mustermann
Training recording
John Doe
Purchase order
Jane Doe

Cell Layout

`TableCellLayout` gives a cell the standard Fluent arrangement: media, main content, and a second line below it. `appearance="primary"` emphasizes the cell, and `truncate` clips the content with an ellipsis.

File Author
Meeting notes 7h ago
Max Mustermann
Thursday presentation Yesterday at 1:45 PM
Erika Mustermann
Training recording Yesterday at 1:45 PM
John Doe
Purchase order Tue at 9:30 AM
Jane Doe

Cell Actions

`TableCellActions` pins content to the end of a cell and reveals it while the row is hovered or holds the focus. It is usually a row of buttons, and `visible` keeps them on screen at all times.

File Author
Meeting notes
Max Mustermann
Thursday presentation
Erika Mustermann
Training recording
John Doe
Purchase order
Jane Doe

Keyboard Navigation

`enableTabspot` gives the table a single tab stop and moves the focus between cells with the arrow keys, with `Home`, `End`, `PageUp` and `PageDown` jumping further. It also switches the table over to the `role="grid"` pattern, which that navigation requires.

File Author Actions
Meeting notes
Max Mustermann
Thursday presentation
Erika Mustermann
Training recording
John Doe
Purchase order
Jane Doe

Resizable Columns

`resizableColumns` gives every header cell a handle that drags its column wider or narrower, and pins the table to a fixed layout so the width sticks. `columnSizing` sets a floor per column, `columnWidths` is bindable if you want to read the widths back or restore them later, and the handle answers the left and right arrows for anyone not using a pointer.

File Author Last updated
Meeting notes
Max Mustermann 7h ago
Thursday presentation
Erika Mustermann Yesterday at 1:45 PM
Training recording
John Doe Yesterday at 1:45 PM
Purchase order
Jane Doe Tue at 9:30 AM

No Row Borders

`noRowBorders` drops the line that separates one row from the next, for a table that sits inside a card or another surface that already frames it.

File Author
Meeting notes
Max Mustermann
Thursday presentation
Erika Mustermann
Training recording
John Doe
Purchase order
Jane Doe

Non Native Elements

`noNativeElements` renders every part as a `div` and lays the rows out with flexbox, writing out the ARIA roles a native table provides implicitly. Use it when the strict table layout gets in the way, as virtualized rows and sticky headers do.

File
Author
Last updated
Meeting notes
Max Mustermann
7h ago
Thursday presentation
Erika Mustermann
Yesterday at 1:45 PM
Training recording
John Doe
Yesterday at 1:45 PM
Purchase order
Jane Doe
Tue at 9:30 AM

Virtualization

The table renders whatever you put inside it, so any virtualization library works. Pair it with `noNativeElements`, because a semantic `table` is laid out by the browser in a single pass and fights a windowed list. Only a window of rows exists in the DOM, so nothing inside can size the columns: give the table a `min-width`, and report the real size of the data set with `aria-rowcount` and `aria-rowindex`.

File
Author
Last updated
Document 1
Max Mustermann
7h ago
Document 2
Erika Mustermann
Yesterday at 1:45 PM
Document 3
John Doe
Yesterday at 1:45 PM
Document 4
Jane Doe
Tue at 9:30 AM
Document 5
Max Mustermann
7h ago
Document 6
Erika Mustermann
Yesterday at 1:45 PM
Document 7
John Doe
Yesterday at 1:45 PM
Document 8
Jane Doe
Tue at 9:30 AM
Document 9
Max Mustermann
7h ago
Document 10
Erika Mustermann
Yesterday at 1:45 PM
Document 11
John Doe
Yesterday at 1:45 PM
Document 12
Jane Doe
Tue at 9:30 AM
Document 13
Max Mustermann
7h ago
Document 14
Erika Mustermann
Yesterday at 1:45 PM
Document 15
John Doe
Yesterday at 1:45 PM
Document 16
Jane Doe
Tue at 9:30 AM
Document 17
Max Mustermann
7h ago
Document 18
Erika Mustermann
Yesterday at 1:45 PM
Document 19
John Doe
Yesterday at 1:45 PM
Document 20
Jane Doe
Tue at 9:30 AM
Document 21
Max Mustermann
7h ago

Component Props (Table)

NameTypeDefaultDescription
as'table' | 'div''table'The HTML element to render the table as. Defaults to a `div` when `noNativeElements` is set.
ref bindableHTMLTableElement | HTMLDivElementThe DOM reference of the table element.
size'extra-small' | 'small' | 'medium''medium'Affects the sizes of all table subcomponents.
noNativeElementsbooleanfalseRenders every table part as a `div` instead of a semantic table element. The layout switches from `display: table` to `display: flex`, which virtualization and sticky headers need.
sortablebooleanfalseTurns every header cell into a sort button. Individual cells can still opt in on their own.
noRowBordersbooleanfalseDrops the line that separates one row from the next.
enableTabspotbooleanfalseMoves the focus between cells with the arrow keys, through a single tab stop. It also switches the table over to the `role="grid"` pattern, which that navigation requires.
virtualizerTableVirtualizerLets the arrow keys reach rows a windowed list has not rendered. Only read when `enableTabspot` is set, and the rows need an `aria-rowindex` for it to find them again.
resizableColumnsbooleanfalseGives every header cell a handle that drags its column wider or narrower. It also pins the table to a fixed layout, so a column keeps the width it was given.
columnWidths bindablenumber[]The width of each column in pixels, by column position. Columns left out keep their own size.
columnSizingColumnSizing[]Per column limits, by column position.
onColumnResize(e: Event, data: { index: number; width: number }) => voidCalled whenever a column is dragged or nudged to a new width.
HTML Attributes

Component Props (TableHeader)

NameTypeDefaultDescription
as'thead' | 'div''thead'The HTML element to render the header as. Inherited from the table by default.
ref bindableHTMLTableSectionElement | HTMLDivElementThe DOM reference of the header element.
HTML Attributes

Component Props (TableHeaderCell)

NameTypeDefaultDescription
as'th' | 'div''th'The HTML element to render the header cell as. Inherited from the table by default.
ref bindableHTMLTableCellElement | HTMLDivElementThe DOM reference of the header cell element.
sortablebooleanWhether the column is sortable. Inherited from the table by default.
sortDirection'ascending' | 'descending'The direction the column is currently sorted in. Also sets `aria-sort`.
sortIconSnippet | ComponentThe indicator rendered next to the label of a sortable column.
asideSnippet | ComponentContent placed after the label, outside the sort button.
focusMode'cell' | 'group' | 'none''cell'How the arrow keys treat the cell. `'group'` holds the focusable content of the cell out of the tab order until `Enter` steps in, and `Escape` steps back out. `'none'` skips the cell altogether. Only read when the table sets `enableTabspot`. A resizable header cell defaults to `'group'`, so the arrows reach its handle instead of leaving the column behind.
resizablebooleanWhether the column can be resized. Inherited from the table by default.
resizeLabelstring'Resize column'The accessible name of the resize handle. Give it a translated, and ideally per column, string — the attributes of the cell reach the cell, never the handle inside it.
HTML Attributes

Component Props (TableBody)

NameTypeDefaultDescription
as'tbody' | 'div''tbody'The HTML element to render the body as. Inherited from the table by default.
ref bindableHTMLTableSectionElement | HTMLDivElementThe DOM reference of the body element.
HTML Attributes

Component Props (TableRow)

NameTypeDefaultDescription
as'tr' | 'div''tr'The HTML element to render the row as. Inherited from the table by default.
ref bindableHTMLTableRowElement | HTMLDivElementThe DOM reference of the row element.
appearance'none' | 'brand' | 'neutral''none'How the row is filled. Intended to mark a selected row.
HTML Attributes

Component Props (TableCell)

NameTypeDefaultDescription
as'td' | 'div''td'The HTML element to render the cell as. Inherited from the table by default.
ref bindableHTMLTableCellElement | HTMLDivElementThe DOM reference of the cell element.
focusMode'cell' | 'group' | 'none''cell'How the arrow keys treat the cell. `'group'` holds the focusable content of the cell out of the tab order until `Enter` steps in, and `Escape` steps back out. `'none'` skips the cell altogether. Only read when the table sets `enableTabspot`.
HTML Attributes

Component Props (TableSelectionCell)

NameTypeDefaultDescription
as'td' | 'div''td'The HTML element to render the cell as. Inherited from the table by default.
ref bindableHTMLTableCellElement | HTMLDivElementThe DOM reference of the cell element.
type'checkbox' | 'radio''checkbox'A table can have two kinds of selection modes.
checkedboolean | 'mixed'falseWhether the row is selected. `'mixed'` renders the indeterminate state.
subtlebooleanfalseOnly shows the indicator when it is checked, or the row is hovered or focused.
invisiblebooleanfalseHides the indicator while it keeps taking up the same space.
checkboxIndicatorCheckboxPropsThe props to spread on the checkbox rendered when `type` is `'checkbox'`.
radioIndicatorRadioButtonPropsThe props to spread on the radio button rendered when `type` is `'radio'`.
HTML Attributes

Component Props (TableCellLayout)

NameTypeDefaultDescription
ref bindableHTMLDivElementThe DOM reference of the layout element.
mediaSnippet | ComponentAn icon, an avatar or any other visual element placed before the main content.
descriptionstringA second line of text that describes or complements the main content.
appearance'primary'Emphasizes the cell by enlarging the media and bolding the main content.
truncatebooleanClips the content with an ellipsis instead of letting it wrap.
HTML Attributes

Component Props (TableCellActions)

NameTypeDefaultDescription
ref bindableHTMLDivElementThe DOM reference of the actions element.
visiblebooleanKeeps the actions on screen instead of waiting for the row to be hovered or focused.
HTML Attributes