| Agents | Skills | Tasks |
|---|---|---|
| Adam Brown | English, French, Sales, Spanish | 35 |
| Adriana Lovelock | English, French, Sales, Spanish | 28 |
| Amanda Cutlack | English, French, Sales, Spanish | 7 |
| 70 |
Table
Tables are used to display information that is meant to be compared across columns and rows.
- Status
- production
- Version
- 2.0.3
- 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
TBodywrapping 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), withscope="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 Components 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:
- Using the Table component from Paste, even if it includes actionable elements, is much more accessible than the legacy table.
- 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.
- 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.
- 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.
| 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 |
Fixed column width#
The Fixed Table variant sets equal column widths for the table.
| Agents | Skills | Tasks |
|---|---|---|
| Adam Brown | English, French, Sales, Spanish | 35 |
| Adriana Lovelock | English, French, Sales, Spanish | 28 |
| Amanda Cutlack | English, French, Sales, Spanish | 7 |
| 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 Name | Last Name |
|---|---|
| Tamir | Rice |
| Philando | Castile |
| Trayvon | Martin |
| Breonna | Taylor |
| Shantel | Davis |
| Walter | Scott |
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 Name | Last Name |
|---|---|
| Tamir | Rice |
| Philando | Castile |
| Trayvon | Martin |
| Breonna | Taylor |
| Shantel | Davis |
| Walter | Scott |
Row alignment#
Table rows (Tr) can be set with either top, middle, or bottom vertical alignment. By default they are middle-aligned.
| Author | Quote |
|---|---|
| Chinua Achebe | The 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 Baldwin | Anyone who has ever struggled with poverty knows how extremely expensive it is to be poor. |
| Dorothy West | To know how much there is to know is the beginning of learning to live. |
| W.E.B. Du Bois | Herein 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.
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".
| User | Email Address | Last Login Time |
|---|---|---|
| tamir.rice | tamir@rice.com | 12:24:00 PDT |
| philando.castile | philando@castile.com | 08:24:20 PDT |
| trayvon.martin | trayvon@martin.com | 16:05:10 PDT |
| breonna.taylor | breonna@taylor.com | 13:10:28 PDT |
| shantel.davis | shantel@davis.com | 01:04:54 PDT |
| walter.scott | walter@scott.com | 08:19:10 PDT |
Table with footer#
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.
| Agents | Skills | Tasks |
|---|---|---|
| Adam Brown | English, French, Sales, Spanish | 35 |
| Adriana Lovelock | English, French, Sales, Spanish | 28 |
| Amanda Cutlack | English, French, Sales, Spanish | 7 |
| Total tasks | 70 |
Composition Notes#
Tables must be created using a combination of:
Table: The table wrapperTHead: The header of your tableTBody: The main body of your tableTFoot: The footer of your table (optional)Tr: A row of cells in your tableTh: A header cell which can be used as a column title and row titleTd: 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.
| Agents | Skills | Tasks |
|---|---|---|
| Adam Brown | English, French, Sales, Spanish | 35 |
| Adriana Lovelock | English, French, Sales, Spanish | 28 |
| Amanda Cutlack | English, French, Sales, Spanish | 7 |
| Total tasks | 70 |
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.
| User | Skills | Tasks |
|---|---|---|
Adam Brown adam@brown.com | English, French, Sales, Spanish | 35 |
Adriana Lovelock adriana@lovelock.com | English, French, Sales, Spanish | 28 |
Amanda Cutlack amanda@cutlack.com | English, French, Sales, Spanish | 7 |
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.
| User | Skills | Tasks |
|---|---|---|
Adam Brown adam@brown.com | English, French, Sales, Spanish | 35 |
Adriana Lovelock adriana@lovelock.com | English, French, Sales, Spanish | 28 |
Amanda Cutlack amanda@cutlack.com | English, French, Sales, Spanish | 7 |
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.
| Result | SID | Email Address |
|---|---|---|
Valid 2020-09-17, 16:24:28 PDT | SM0yc4mxi6cn4z13bte7qmflc2drc85mlp | hayden74@hotmail.com |
Risky 2020-09-17, 16:24:28 PDT | SMl29llgoihx286uhxfb0yc5n0sg391x5n | beyrek70@hotmail.com |
Invalid 2020-09-17, 16:24:28 PDT | SMxarke3v30fv17hauqn86a7nhgm3b5d87 | kevin@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.
| Agents | Skills | Profile URL |
|---|---|---|
| Adam Brown | English, French, Sales, Spanish | https://paste.twilio.design/getting-started/about-paste |
| Adriana Lovelock | English, French, Sales, Spanish | https://paste.twilio.design/getting-started/about-paste |
| Amanda Cutlack | English, French, Sales, Spanish | https://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#
| Property | Default token | Modifiable? |
|---|---|---|
| border-color | color-border-lighter | No |
| border-width | Default: border-width-10, Borderless: border-width-0 | No |
| width | 100% | No |
THead#
| Property | Default token | Modifiable? |
|---|---|---|
| background-color | color-background | No |
| border-bottom-width | border-width-20 | No |
| border-bottom-color | color-border-lighter | No |
TBody#
| Property | Default token | Modifiable? |
|---|---|---|
| background-color | color-background-body | No |
TFoot#
| Property | Default token | Modifiable? |
|---|---|---|
| background-color | color-background | No |
| border-top-width | border-width-20 | No |
| border-top-color | color-border-lighter | No |
Tr#
| Property | Default token | Modifiable? |
|---|---|---|
| background-color | Striped even rows: color-background-row-striped | No |
| border-bottom-width | border-width-10 | No |
| border-bottom-color | color-border-lighter | No |
Th#
| Property | Default token | Modifiable? |
|---|---|---|
| font-size | font-size-30 | No |
| line-height | line-height-30 | No |
| font-weight | font-weight-semibold | No |
| padding |
| No |
Td#
| Property | Default token | Modifiable? |
|---|---|---|
| font-size | font-size-30 | No |
| line-height | line-height-30 | No |
| font-weight | font-weight-normal | No |
| padding |
| No |
Usage Guide#
API#
Installation#
yarn add @twilio-paste/table - or - yarn add @twilio-paste/coreUsage#
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.