Marigold
Getting StartedFoundationsComponentsPatternsRecipesReleases
Discover new Tutorials!

Components

Overview

Application

MarigoldProvider
updated
RouterProvider
updated

Layout

Aside
Aspect
Breakout
Center
Columns
Container
Grid
Inline
Inset
Scrollable
Split
Stack
updated
Tiles

Form

Autocomplete
Button
updated
Calendar
Checkbox
ComboBox
DateField
DatePicker
Form
Multiselect
new
NumberField
Radio
SearchField
Select
Slider
Switch
TextArea
TextField
TimeField
new

Collection

SelectList
updated
Table
updated
Tag

Navigation

Accordion
Breadcrumbs
beta
Pagination
Tabs

Overlay

ContextualHelp
new
Dialog
Menu
Toast
beta
Tooltip
updated

Content

Badge
Body
Card
Divider
updated
Footer
Header
Headline
updated
Icon
updated
Image
Link
updated
List
updated
SectionMessage
SVG
updated
Text
updated
VisuallyHidden
updated
XLoader

Formatters

DateFormat
NumericFormat

Hooks and Utils

cn
cva
extendTheme
useAsyncListData
useListData
useResponsiveValue
useTheme

Table

Organize and display large amout of data in table format.

The <Table> is a structured component used to organize and display tabular data in rows and columns. It enhances the functionality of regular <table> elements with the possibility to interact and select the data, and helps with accessibility by enabling keyboard navigation.

What is tabular data?

Tabular data is a structured form of data that is organized in rows and columns and resembles a table format.

Our table allows user to selecting one or multiple rows, it includes an action cell, and supports sorting columns. Additionally, it features a sticky header, can stretch to full size, and allows columns to be aligned to the left, center, or right. The table also supports nesting columns and having fixed column widths.

These features will be explained in more detail in the usage section further down the page.

Anatomy

A table is composed of a container element that organizes data into rows and columns. Each cell within the table can hold either plain text or focusable elements. If the table allows multiple row selection, the first column of each row include a checkbox for selecting that row and the first column header will contain a "select all" checkbox.

Anatomy of table

Appearance

The appearance of a component can be customized using the variant and size props. These props adjust the visual style and dimensions of the component, available values are based on the active theme.

Variant
Size
The selected theme does not has any options for "size".
IdEventDate
1234ConcertMittwoch, 10. Januar 2024
82374Open Air FestivalDienstag, 9. Juli 2024
724423Live on StageMontag, 25. November 2024
23497Open Air SummertimeSamstag, 1. Juni 2024
PropertyTypeDescription
variantdefault | grid | muted | admin | masterThe available variants of this component.
size-The available sizes of this component.

Usage

Use a <Table> if you need to organize and display large amout of data. Grouping informations provide a structured and organized way to display data, making it easier to understand and analyze. Tables allow you to group related information in a clear and concise manner, which enhances data readability and comprehension.

They are ideal for comparing data points. Unlike cards, tables enable users to compare multiple rows and columns without having to move their eyes too much or rely on memory. Also with the support of single or multiple row actions, they make it convenient to perform data-specific actions such as deleting, sharing, or editing records directly within the table.

Do
Use tables with clear understandable content

Provide descriptive column headers for each column that accurately represent the data.

Don't
Dont use tables with empty column headers.

Avoid using vague or misleading column headers that do not clearly represent the data.

Do
Stretch tables to available width.
Stretch tables to available width.

Don't
Dont use tables for layouts
Don't use a table for layouting content.

Variants

  • Default: You should use the default variant of the Table component when you want a clean, standard table appearance. It’s ideal for most use cases where you want to display tabular data clearly and simply. The default variant is a good starting point for most tables.

  • Muted: Use the muted variant for table to reduce visual noise and improve clarity, especially in tables with extensive content. This helps users focus on the data while maintaining a clean and organized appearance.

  • Grid: The grid variant is useful if you want clearer separation between columns, especially for tables with many columns or dense data. The grid variant adds vertical borders between columns, making it easier to scan and compare values across rows.

  • Admin- and Master: Use this variant to identify rows that are only relevant for internal users. Learn more about its usage.

Display secondary information

Secondary data in a cell is needed when additional context or details are necessary to fully understand the primary data. The primary data of a table cell should always be displayed clearly. It provides better readability and can improve the user experience. Too much secondary data can overwelm users and make the table complexer and harder to read.

Preview
Code
IdNameUser
Do
Use tables with clear understandable content

Keep cell content concise. Only add additional data when necessary to help understand the data.

Don't
Dont use tables with too much informations inside

Avoid overloading cells with too much information or complex data, and multiple data values in one cell.

Sticky header

If you have large data tables, setting the header to sticky can provide context when scrolling. To do this, set the stickyHeader property on the <Table> and wrap it in the Scrollable component with a specified height, as shown in the example below.

Preview
Code
IdNameUser

Highlight data

This is an example of how you can use the <Badge> within the <Table>. Badges can be used in a table to highlight or categorize certain data, making it easier for users to quickly identify key information. This is a common use case if you need to add status indicators, categorizations, labels or tags within the table.

Preview
Code
IdEventDateStatus
16382462873ConcertMittwoch, 10. Januar 2024
updated
383262736Open Air FestivalDienstag, 9. Juli 2024
new
62836432Live on StageMontag, 25. November 2024-
82742834Open Air SummertimeSamstag, 1. Juni 2024
updated
78263482OperaDonnerstag, 12. Dezember 2024
new
9823742MusicalMontag, 19. August 2024
updated
Do

Place badges consistently within the table, preferably in a dedicated column.

Don't

Don't place badges randomly within the table or overload the table with too many badges.

Sorting

Enable the sorting function to help users organize and find data efficiently. This is especially useful since different user tasks may require different sorting orders.

The <Table> is sortable through allowsSorting prop on it. Sorting controls, indicated by an arrow icon, are located in the column headers and allow for ascending or descending order. For this purpose the properties onSortChange which handles the direction when changing and sortDescriptor, containing the current column and direction must be specified.

To make async sorting more convenient, you can use the useAsyncList hook. The hook manages the async list data and provides convenience methods for updating the data.

Preview
Code
NameHeightMassBirth Year

Handling numeric values

With our formatting helper components for dates and numeric values you can easily ensure consistent and accurate display. See NumericFormat, DateFormat for more informations.

Also you see how to use the align property on the columns. With that you can set the content of a column to left, center or right.

Preview
Code
EventDatePriceTicket Number
Music FestivalFreitag, 25. August 2023$50.00123456789
Red Carpet TheaterSonntag, 10. September 2023$150.00987654321
ConferenceDonnerstag, 5. Oktober 2023$220.50246813579
Sports TournamentMontag, 20. November 2023$75.00135792468
OperaMontag, 15. Mai 2023$500.00128216789
Do
  • Align numeric values and their header cells to the right.
  • Format numbers to provide tabular numeric font style.

Nested columns

Nested columns can be useful in tables when you need to organize complex or hierarchical data in a more structured format. These columns can be nested, which will result in more than one header row to be created.

Note the usage of isRowHeader in the example below. It controls which columns are included in the accessibility name for each row. By default, only the first column is included, meaning the aria label will be on the first column only.

Preview
Code
NameInformation
First NameLast NameBirthdayAge
SamSmithMay 336
JuliaJonesFebruary 1024
PeterParkerSeptember 728
BruceWayneDecember 1832
Do

Keep nested columns simple to avoid overwhelming users with too much information at once. Only use one level of nesting.

Don't

Don't use multiple levels of nested columns, this can make the table complex and difficult to navigate.

Multiple line cells

If your table contains cells with multiple lines of text, use the alignY="top" property on the <Table> component to align cell content to the top. This ensures text consistently starts at the top of each cell, making it easier to scan down columns. It also keeps buttons, text, and icons visually aligned, avoiding uneven spacing caused by varying content heights.

Preview
Code
EventDescriptionLocation
Conference
ID: EVT-001
Annual Tech Conference
Join industry leaders for a day of talks and networking.
Registration required
Berlin
Venue: City Expo Center
Workshop
ID: EVT-002
React Advanced
Hands-on coding session for intermediate React developers.
Limited seats available
Munich
Venue: TechHub
Meetup
ID: EVT-003
Frontend Community
Monthly meetup for frontend enthusiasts.
Free entry
Hamburg
Venue: Innovation Loft
Webinar
ID: EVT-004
Design Systems 101
Online session covering the basics of design systems.
Live Q&A included
Online
Platform: Zoom
Hackathon
ID: EVT-005
Open Source Sprint
Collaborate and build open source projects in teams.
Prizes for top teams
Cologne
Venue: Startup Garage

Row Actions

Row actions let users interact with individual records directly from a table, such as editing, viewing details, or triggering specific operations. These interactions are essential for working with tabular data, and thoughtful design helps users stay oriented and confident. To support clarity, predictability, and efficiency, it’s important to align how and where these actions appear.

Use the <Button> component with the secondary (default) variant for row actions. If the action is destructive, use the destructive variant instead. In both cases, apply the small button size to maintain visual consistency and minimize visual noise in dense table layouts.

When it comes to placement, always position row actions at the end of the row. This improves scannability and clearly signals which parts of the row are interactive, helping users quickly locate available actions.

Preview
Code
VenueAddressRatingAction
Giggle Grounds123 Main Street, Laughville4.7
Wobbling Stage456 Comedy Boulevard, Shakytown3.6
Chuckle Barn789 Oak Road, Hee-Haw City2.3

Show only the most important 1–3 actions per row. These should be the actions users are most likely to need or expect to find without having to open a menu, such as “Edit” or “View.” If you need to support more than three actions, prioritize them by frequency and importance: display the most critical ones directly, and group the rest into a contextual menu using an <ActionMenu> (see ActionMenu section). This keeps the row clean and scannable while still offering access to all necessary actions.

Using too many visible actions at once can overwhelm users, make it hard to identify what to do, and increase visual clutter. If space is limited or the layout feels crowded, consider using icon buttons to keep actions compact. Pair them with tooltips to clearly communicate each action’s purpose without adding visual noise.

Use icons with care

Only use icons when their meaning is clear without explanation. If the icon might be ambiguous, prefer a labeled button or add context with a tooltip.

Preview
Code
VenueAddressRatingAction
Giggle Grounds123 Main Street, Laughville4.7
Wobbling Stage456 Comedy Boulevard, Shakytown3.6
Chuckle Barn789 Oak Road, Hee-Haw City2.3

If you cannot place all row actions at the end of the row, be mindful of clarity and consistency. Actions should remain visually distinct from content and navigation, and be grouped where possible to support scannability. Apply consistent styling to each action and avoid placing them in unexpected locations, as this can increase cognitive load and make it harder for users to understand what they can do in each row.

Links

Inline links for actions can sometimes be mistaken for regular content and may add visual noise, so it’s best to use them with care. A common and appropriate use of links in tables is placing one on the identifying attribute of a record, such as a name or title, when it leads to the related item or detail view.

When using links in tables, default to the standard <Link> component. If the table contains many links, consider simplifying the layout to reduce visual clutter. If links cannot be reduced, use the secondary variant of <Link> to maintain clarity and minimize distraction.

Preview
Code
VenueAddressRating
Giggle Grounds123 Main Street, Laughville4.7
Wobbling Stage456 Comedy Boulevard, Shakytown3.6
Chuckle Barn789 Oak Road, Hee-Haw City2.3
Quirky Quay101 Riverside Drive, Port Funsies4.2

Props

Hint: Dynamic Collections

You don't have to hard code the table items, you could also create a dynamic collection and iterate through it. You can read more about these collections here.

Did you know? You can explore, test, and customize props live in Marigold's storybook. Watch the effects they have in real-time!
View Table stories

Table

alignY?
"top" | "middle";
Control the vertical alignment of table content.
Defaults to:
"middle"
children?
[
  ReactElement<TableHeaderProps<object>, string | JSXElementConstructor<any>>,
  ReactElement<TableBodyProps<object>, string | JSXElementConstructor<...>>,
];
The elements that make up the table. Includes the TableHeader, TableBody, Columns, and Rows.
collection?
TableCollection<object>;
A pre-constructed collection to use instead of building one from items and children.
defaultSelectedKeys?
Iterable<Key> | "all";
The initial selected keys in the collection (uncontrolled).
disableKeyboardNavigation?
boolean;
Disable keyboard navigation. Use if you have input fields in your table. Be aware that this is bad for accessibility.
Defaults to:
"false"
disabledBehavior?
DisabledBehavior;
Whether disabledKeys applies to all interactions, or only selection.
disabledKeys?
Iterable<Key>;
A list of row keys to disable.
disallowEmptySelection?
boolean;
Whether the collection allows empty selection.
emptyState?
() => ReactNode;
Content to display when there are no rows in the table.
focusMode?
"row" | "cell";
Whether initial grid focus should be placed on the grid row or grid cell.
Defaults to:
'row'
onCellAction?
(key: Key) => void;
Handler that is called when a user performs an action on the cell.
onRowAction?
(key: Key) => void;
Handler that is called when a user performs an action on the row.
onSelectionChange?
(keys: Selection) => void;
Handler that is called when the selection changes.
onSortChange?
(descriptor: SortDescriptor) => any;
Handler that is called when the sorted column or direction changes.
selectedKeys?
Iterable<Key> | "all";
The currently selected keys in the collection (controlled).
selectionBehavior?
SelectionBehavior;
How multiple selection should behave in the collection.
selectionMode?
SelectionMode;
The type of selection that is allowed in the collection.
Defaults to:
"none"
sortDescriptor?
SortDescriptor;
The current sorted column and direction.
stickyHeader?
boolean;
Make the column sticky to the top of the table.
Defaults to:
"true"
stretch?
boolean;
Stretch table to fill the container.
Defaults to:
"false"

Table.Header

children
ColumnElement<T> | (ColumnElement < T > []) | ColumnRenderer<T>;
A list of Column(s) or a function. If the latter, a list of columns must be provided using the columns prop.
columns?
T[]
A list of table columns.

Table.Column

allowsResizing?
boolean;
Whether the column allows resizing.
allowsSorting?
boolean;
Whether the column allows sorting.
childColumns?
T[]
A list of child columns used when dynamically rendering nested child columns.
children
ReactNode | ColumnElement<T> | (ColumnElement < T > []);
Static child columns or content to render as the column header.
defaultWidth?
ColumnSize | null;
The default width of the column.
isRowHeader?
boolean;
Whether a column is a row header and should be announced by assistive technology during row navigation.
maxWidth?
ColumnStaticSize | null;
The maximum width of the column.
minWidth?
ColumnStaticSize | null;
The minimum width of the column.
textValue?
string;
A string representation of the column's contents, used for accessibility announcements.
title?
ReactNode;
Rendered contents of the column if children contains child columns.
width?
WidthProp;
The width of the column.

Table.Body

children
RowElement<T> | (RowElement < T > []) | ((item: T) => RowElement<T>);
The contents of the table body. Supports static items or a function for dynamic rendering.
items?
Iterable<T>;
A list of row objects in the table body used when dynamically rendering rows.
loadingState?
LoadingState;
The current loading state of the table.
onLoadMore?
() => any;
Handler that is called when more items should be loaded, e.g. while scrolling near the bottom.

Table.Row

children
CellElement | CellElement[] | CellRenderer
Rendered contents of the row or row child items.
download?
string | boolean;
Causes the browser to download the linked URL. A string may be provided to suggest a file name. See MDN.
href?
string;
A URL to link to. See MDN.
hrefLang?
string;
Hints at the human language of the linked URL. SeeMDN.
ping?
string;
A space-separated list of URLs to ping when the link is followed. See MDN.
referrerPolicy?
HTMLAttributeReferrerPolicy;
How much of the referrer to send when following the link. See MDN.
rel?
string;
The relationship between the linked resource and the current page. See MDN.
routerOptions?
undefined;
Options for the configured client side router.
target?
HTMLAttributeAnchorTarget;
The target window for the link. See MDN.
textValue?
string;
A string representation of the row's contents, used for features like typeahead.

Table.Cell

children
ReactNode;
The contents of the cell.
colSpan?
number;
Indicates how many columns the data cell spans.
textValue?
string;
A string representation of the cell's contents, used for features like typeahead.

Alternative components

Choosing the right alternative to data tables is crucial for effectively displaying your data and enhancing user interaction. Depending on the type of data and the desired user experience, different components can offer different benefits. Here are some alternatives to data tables that might better suit your needs:

  • SelectionList: Displays a list of interactive items, useful to create an actionable list of related items, such as a list of users.

  • Cards: Helpful if the data needs to be displayed with more visual hierarchy. Keep in mind that you can't compare data in this way not as good as tables, because the eyes have to move much more.

  • List: When presenting a simple, linear collection of items, often with less data per item. Easy to read and navigate, especially for data that doesn’t require complex organization.

  • Grid: Layout in a table-like structure. This gives you full control over the size of the columns and rows and allows you to align them according to your needs.

  • Columns: Create columns in one row, useful if you need to align content in a table-like way with fewer rows.

Is there still not the right alternative for you please get in touch with us!

Related

Recipe for Core Table
A recipe for a typical core table.
Admin- & master mark
Used for marking internal-only features.
useAsyncListData
If you need to load async data into tables.
Last update: 9 minutes ago
Build with 🥵, 🧡 and
v14.1.1