Skip to content
Paste
UX Platform
Change the site theme
GitHub

Table

Tables are used to display information that is meant to be compared across columns and rows.

Status
production
Version
2.0.3
Sources
Abstract
Import from
@twilio-paste/core/table — or — @twilio-paste/table

Guidelines#

About Table#

A Table is a grid of static textual and numeric data of the same content structure presented in rows and columns of cells. For example, a Table would be a good way to represent a list of multiple support agents and their respective skills and online/offline status.

Accessibility#

Tables are used to organize data with a logical relationship in grids. Accessible tables need HTML markup that indicates header cells and data cells and defines their relationship. Assistive technologies use this information to provide context to users.

Accessibility requirements:

  • Tables must have a THead, containing a Th for each column.
  • Tables must have a TBody wrapping the table body of rows.

Accessibility recommendations:

  • It is a best practice to include row headers, which can be added by including a header (Th) as the first cell in each row (Tr), with scope="row". This is not relevant for all tables, but you should follow this practice when the first cell in a row is the key value for that row, such as a username. You can find an example of this in the section on row headers.
  • Any component can be placed in a Table, but tables should only contain static textual and numeric data, rather than actionable components like buttons, whenever possible. This is because, if the table is reasonably long—say 50 rows—with multiple actions per row—say 4 actions—a keyboard-only user would have to press the tab key 200 times to get past that table.

🦮 Accessibility insight: navigating tables with a screen reader

Learn more about why semantic table markup is important in this demo video by Inclusive Componentslink takes you to an external page that shows what it's like to explore a data table with a screen reader.

So, why migrate to Table if you need to include actionable elements?

Our strong recommendation is to use Table over sticking with the legacy table, even if you need to include actionable elements, like buttons or anchors. While Table should only contain static information for the accessibility reasons we've outlined, Table can support the inclusion of actionable components when needed, and it is the best option available to you today.

Once we have a Data Grid component, our recommendation will be to use that whenever you need to include actions within a table (such as linking to object details, selecting rows, or deleting rows). Data Grid will be built on top of Table and will layer in some aria controls that make it easier to navigate with a keyboard (much like navigating through an Excel spreadsheet). However, until the Data Grid component is available, our recommendation is to use the Table component; we will just ask that you plan to switch to the Data Grid when it's ready. Here's why we recommend this over sticking with the legacy table:

  1. Using the Table component from Paste, even if it includes actionable elements, is much more accessible than the legacy table.
  2. The visual design of the Paste Table component will be very similar to the Data Grid, so they will look cohesive when used together in one product or feature, and there will be minimal customer impact when upgrading from Table to Data Grid in the future.
  3. If you use the Table component from Paste, you will benefit from design and technical upgrades, whereas the legacy table will not receive any updates.
  4. Migration from the Paste Table to Data Grid will be much easier than migrating from the legacy table to Data Grid, as the underlying architecture of the Paste Table and Data Grid will be very similar. In fact, Data Grid will be built using the Table component.

Examples#

Layouts#

Default#

The Default Table uses an automatic table layout algorithm dictated by the browser. The width of the table cells are adjusted to fit the content.

DateSIDFrom

16:24:28 PDT

2020-09-17

SM0yc4mxi6cn4z13bte7qmflc2drc85mlp(602) 609-6747

16:24:28 PDT

2020-09-17

SMl29llgoihx286uhxfb0yc5n0sg391x5n(602) 609-6747

16:24:28 PDT

2020-09-17

SMxarke3v30fv17hauqn86a7nhgm3b5d87(602) 609-6747

Fixed column width#

The Fixed Table variant sets equal column widths for the table.

AgentsSkillsTasks
Adam BrownEnglish, French, Sales, Spanish35
Adriana LovelockEnglish, French, Sales, Spanish28
Amanda CutlackEnglish, French, Sales, Spanish7
70

Specified column widths#

THead cells (Th) can be given a width in order to fill a section of the Table row (Tr). Widths can be set with Paste Size Tokens or a number value, e.g. 120px.

First NameLast Name
TamirRice
PhilandoCastile
TrayvonMartin
BreonnaTaylor
ShantelDavis
WalterScott

Alignment#

Column alignment#

You can adjust the text alignment within Table cells (Td or Th). By default they are left-aligned.

In general, text should be left-aligned, numbers should be right-aligned, and the header should be aligned with the data. Data should rarely ever be centered. Numbers only need to be right-aligned when they indicate size or are meant to be compared to each other. Numbers like ID numbers, phone numbers, etc. should stay left-aligned.

First NameLast Name
TamirRice
PhilandoCastile
TrayvonMartin
BreonnaTaylor
ShantelDavis
WalterScott

Row alignment#

Table rows (Tr) can be set with either top, middle, or bottom vertical alignment. By default they are middle-aligned.

AuthorQuote
Chinua AchebeThe impatient idealist says: ‘Give me a place to stand and I shall move the earth.' But such a place does not exist. We all have to stand on the earth itself and go with her at her pace.
James BaldwinAnyone who has ever struggled with poverty knows how extremely expensive it is to be poor.
Dorothy WestTo know how much there is to know is the beginning of learning to live.
W.E.B. Du BoisHerein lies the tragedy of the age: not that men are poor—all men know something of poverty; not that men are wicked—who is good? Not that men are ignorant—what is truth? Nay, but that men know so little of men.

Borderless#

Tables can support a borderless variant, which can be useful in cases where the Table is placed inside of another containing element, such as a modal or a card. Tables have borders by default, but these can optionally be turned off by setting variant="borderless" on Table.

AgentsSkillsTasks
Adam BrownEnglish, French, Sales, Spanish35
Adriana LovelockEnglish, French, Sales, Spanish28
Amanda CutlackEnglish, French, Sales, Spanish7
70

Row headers#

Tables support row headers in addition to the more commonly seen column headers. It is a best practice to provide row headers in cases where the first cell in a row is the key value for that row, such as a username or the name of an email campaign.

Row headers can be added by including a Th as the first cell in each Tr, with scope="row".

UserEmail AddressLast Login Time
tamir.ricetamir@rice.com12:24:00 PDT
philando.castilephilando@castile.com08:24:20 PDT
trayvon.martintrayvon@martin.com16:05:10 PDT
breonna.taylorbreonna@taylor.com13:10:28 PDT
shantel.davisshantel@davis.com01:04:54 PDT
walter.scottwalter@scott.com08:19:10 PDT

Tables support an optional TFoot, which comes after the TBody. The TFoot must contain at least one Tr. A good use case for a TFoot is when you want to provide a summary or total for the rows of data in your table.

The placement of the TFoot is based on classic HTML table design, so it can not be placed anywhere except at the bottom of a table. In cases where you do want to show a summary or total, and that information is of high importance to the user, you can place it above the table or at the top of the table in a regular table row, rather than using the TFoot.

AgentsSkillsTasks
Adam BrownEnglish, French, Sales, Spanish35
Adriana LovelockEnglish, French, Sales, Spanish28
Amanda CutlackEnglish, French, Sales, Spanish7
Total tasks70

Composition Notes#

Tables must be created using a combination of:

  • Table: The table wrapper
  • THead: The header of your table
  • TBody: The main body of your table
  • TFoot: The footer of your table (optional)
  • Tr: A row of cells in your table
  • Th: A header cell which can be used as a column title and row title
  • Td: A cell of table content

Tables fill 100% width of the space of their containing element. Use Layout components to control the size and placement of Tables within a page.

Ordering columns#

In many cases, each table row has some kind of identifier, such as a username, SID, or friendly name. In cases where the data in each row is associated with an overarching, named object, the name of that object should generally be the first column in the table. In these cases, the cells in that first column should be Row Headers.

For the remaining columns, you will need to conduct usability testing to hone in on what column ordering works best for your users and their particular needs. Generally, it is a good practice to put columns that are closely related to one another (such as a unit price, quantity purchased, and total price) near each other in a table.

If you do have actions in your Table (see our Accessibility Information on this), they should generally be placed in the last column.

Text alignment in cells#

In general, text should be left-aligned, numbers should be right-aligned, and the header should be aligned with the data. Data should rarely ever be centered. Numbers only need to be right-aligned when they indicate size and/or are meant to be compared to each other. Numbers like ID numbers, phone numbers, etc. should stay left-aligned.

Zebra striping#

Tables can have zebra stripes (i.e. alternating row highlighting), which can improve readability of particularly large data sets. Tables have zebra stripes turned off by default, but these can optionally be turned on by setting striped on Table.

AgentsSkillsTasks
Adam BrownEnglish, French, Sales, Spanish35
Adriana LovelockEnglish, French, Sales, Spanish28
Amanda CutlackEnglish, French, Sales, Spanish7
Total tasks70

Table with description text#

Each individual table cell can support multiple rows of text, which we'll refer to as "description text". This is useful when you want to provide related details in a table without adding additional columns, such as placing a user's email address beneath their username in a single cell under a column header titled "user".

Description text is recommended in cases where the user would benefit from having additional context about a particular cell, but that additional context is not the primary data that is being presented in the table. For example, in a table that lists a user's email campaigns with open rates, click rates, etc. for each, it may help the user identify a particular campaign by knowing both the campaign name and what time it was sent, so the first column of this table may include the campaign name with the send time included as description text. In this example, the send time is not being compared across rows like the open rates and click rates are; instead, the send time is used to add additional detail that helps the user identify and understand data in an individual row.

UserSkillsTasks

Adam Brown

adam@brown.com

English, French, Sales, Spanish35

Adriana Lovelock

adriana@lovelock.com

English, French, Sales, Spanish28

Amanda Cutlack

amanda@cutlack.com

English, French, Sales, Spanish7

Table with avatars#

Tables can be composed using Avatar, which can be used to make a table of user data more scannable. You can put an avatar next to a user's first and last name using Stack inside a single Td.

UserSkillsTasks
Adam Brown

Adam Brown

adam@brown.com

English, French, Sales, Spanish35
Adriana Lovelock

Adriana Lovelock

adriana@lovelock.com

English, French, Sales, Spanish28
Amanda Cutlack

Amanda Cutlack

amanda@cutlack.com

English, French, Sales, Spanish7

Table with status indicators#

Tables can support custom compositions using Box and Text, such as custom status indicators. When including statuses in a table, be sure to include supporting text so color isn't the only indicator of status.

Refer to our Status Indicator pattern (coming soon!) for guidance on displaying statuses in your tables.

ResultSIDEmail Address

Valid

2020-09-17, 16:24:28 PDT

SM0yc4mxi6cn4z13bte7qmflc2drc85mlphayden74@hotmail.com

Risky

2020-09-17, 16:24:28 PDT

SMl29llgoihx286uhxfb0yc5n0sg391x5nbeyrek70@hotmail.com

Invalid

2020-09-17, 16:24:28 PDT

SMxarke3v30fv17hauqn86a7nhgm3b5d87kevin@hotmail.com

Table with tooltips on headers#

A Th can be composed to include icon buttons, such as an information icon button with additional details placed in a Tooltip or Popover.

Date
SID
From

16:24:28 PDT

2020-09-17

SM0yc4mxi6cn4z13bte7qmflc2drc85mlp(602) 609-6747

16:24:28 PDT

2020-09-17

SMl29llgoihx286uhxfb0yc5n0sg391x5n(602) 609-6747

16:24:28 PDT

2020-09-17

SMxarke3v30fv17hauqn86a7nhgm3b5d87(602) 609-6747

Table with truncated cells#

In rare cases, you may want to truncate the text in a given cell. For example, when a table contains long URLs, and the user does not need to read the full URL.

AgentsSkillsProfile URL
Adam BrownEnglish, French, Sales, Spanishhttps://paste.twilio.design/getting-started/about-paste
Adriana LovelockEnglish, French, Sales, Spanishhttps://paste.twilio.design/getting-started/about-paste
Amanda CutlackEnglish, French, Sales, Spanishhttps://paste.twilio.design/getting-started/about-paste

When to use Table#

Tables are used to represent static, tabular data. For example, a list of users' first names, last names, and email addresses.

Do

Left-align textual table data, such as an email address.

Don't

Don't right- or center-align textual table data.

Do

Right-align numeric table data that is meant to be compared along a single column, such as the open rate on an email campaign.

Don't

Don't left- or center-align numeric table data that is meant to be compared along a single column.

Do

Provide numeric data that is meant to be compared along a single column at the same level of precision, so that the decimal point aligns across all rows and the numbers can be easily compared. For example, show all numbers to two decimal places.

Don't

Don't provide numeric data that is meant to be compared along a single column at differing levels of precision. For example, don't show some numbers to one decimal place and others to two.

Do

Include supporting text when providing a status in a table row.

Don't

Don't use color as the only indicator of status in a table row.

Anatomy#

Table#
PropertyDefault tokenModifiable?
border-colorcolor-border-lighterNo
border-widthDefault: border-width-10, Borderless: border-width-0No
width100%No
THead#
PropertyDefault tokenModifiable?
background-colorcolor-backgroundNo
border-bottom-widthborder-width-20No
border-bottom-colorcolor-border-lighterNo
TBody#
PropertyDefault tokenModifiable?
background-colorcolor-background-bodyNo
TFoot#
PropertyDefault tokenModifiable?
background-colorcolor-backgroundNo
border-top-widthborder-width-20No
border-top-colorcolor-border-lighterNo
Tr#
PropertyDefault tokenModifiable?
background-colorStriped even rows: color-background-row-stripedNo
border-bottom-widthborder-width-10No
border-bottom-colorcolor-border-lighterNo
Th#
PropertyDefault tokenModifiable?
font-sizefont-size-30No
line-heightline-height-30No
font-weightfont-weight-semiboldNo
padding
  • Top: space-40
  • Bottom: space-40
  • Left: space-50
  • Right: space-50
No
Td#
PropertyDefault tokenModifiable?
font-sizefont-size-30No
line-heightline-height-30No
font-weightfont-weight-normalNo
padding
  • Top: space-40
  • Bottom: space-40
  • Left: space-50
  • Right: space-50
No

Usage Guide#

API#

Installation#

yarn add @twilio-paste/table - or - yarn add @twilio-paste/core

Usage#

import {Table} from ‘@twilio-paste/table';
const TableExample: React.FC = () => {
return (
<Table tableLayout="fixed" variant="default" striped>
<THead>
<Tr verticalAlign="middle">
<Th width="size40" textAlign="left">Column 1</Th>
<Th>Column 2</Th>
</Tr>
</THead>
<TBody>
<Tr>
<Td>Content</Td>
<Td>Content</Td>
</Tr>
</TBody>
<TFoot>
<Tr>
<Td>Content</Td>
<Td>Content</Td>
</Tr>
</TFoot>
</Table>
);
};

Props#

Table#

All the valid HTML attributes for table are supported including the following props:

striped?: boolean

Sets a background color for even rows within the table.

tableLayout?: "auto" | "fixed"

Sets the table-layout style of the Table. Defaults to auto.

variant?: "default" | "borderless"

Sets the border style of the Table. Defaults to default.

Tr Props#

All the valid HTML attributes for tr are supported including the following props:

verticalAlign?: "top" | "middle" | "bottom"

Sets the vertical alignment of the content within the Table row. Defaults to middle.

Th Props#

All the valid HTML attributes for th are supported including the following props:

textAlign?: "left" | "center" | "right"

Sets the text alignment of the content within the Table cell. Defaults to left.

width?: WidthOptions

Sets the width of a Table cell.

Td Props#

All the valid HTML attributes for td are supported including the following props:

textAlign?: "left" | "center" | "right"

Sets the text alignment of the content within the Table cell. Defaults to left.


Black lives matter.