Workday Canvas

Table

Tables are an efficient way of displaying sets of repeating data with the same structure.

v14.2.34
Install
yarn add @workday/canvas-kit-react

Anatomy - Tables

Example of the anatomy of a Table.

  1. Table Header (Optional): May consist of a header, result count, optional subheading, or any custom configuration of text.
  2. Table Outline (Optional): A border is used by default, but may be omitted for a full page table or in cases where a table is the sole element on a page.
  3. Column Header: Include just column labels by default, but icon actions for actions such as sort and filter may be added. Note that this functionality will be a custom add for developers.
  4. Cell: May consist of text, icons, status indicators, buttons, data types, or other custom content. Text overflows by default, but teams may elect to apply truncation with a tooltip.

Usage Guidance

Data Tables are intended to display data that can be easily scanned and compared.

  • Conceptually, each row in a Table represents an item, and each cell of that row is an attribute of that item.
  • This means that all the cells in a particular column will be the same data type such as dates, numerals, text, etc.
  • Ideally, there should be one value per cell. Field sets are discouraged.
  • Nested Tables are highly discouraged.

When to Use

Use tables to allow users to:

  • Easily scan and compare data
  • View and edit data
  • Manipulate and navigate through a large amount of data
  • Preview data

When to Use Something Else

Consider another component when:

  • You only have a small data set.
  • A more detailed amount of information needs to be displayed by default.
  • There is more than one piece of information within a cell.

Canvas Table vs. Tables 2.0

The Canvas Table provides a simple, semantic table with some basic styling while Tables 2.0 provides a more fully featured table experience.

The Canvas Table is intended for use cases with view only data, simpler data sets, or custom styling. It doesn’t provide functionality such as search, filter, sort, etc out of the box; teams will need to customize it to fit their use cases. The Canvas Table is intended for Bespoke development and cannot be used with XO.

Tables 2.0 provides much more functionality out of the box, including column sorting & filtering, column resizing, pagination, etc. In addition, Tables 2.0 is configured to be used both in Bespoke and XO development. For uptake and usage details, please refer to the Tables 2.0 documentation site.

Dos and Don’ts

Image displaying a table of expense items and a last column of left aligned numbers.

Do

Right align numeric data in tables.

Image displaying a table of exceptions and a last column of left aligned action buttons.

Do

Right align actions in tables.

Image displaying a table of native tree types and a comments column with text that wraps.

Do

Allow cell text to wrap where possible, giving users access to the full contents of the cell by default.

Image displaying a table of planetary stats, with a cell that is truncated and shows a tooltip with the full text.

Do

We recommend wrapping text where possible, but if needed, cell text may be truncated, showing full text in a tooltip on hover.

Examples

Basic Example

Users may not want to use a caption so they can import Heading or Text instead. This will give the user more flexibility around the customization of the title/heading of their table.

Pizza Toppings

ToppingsAmount
Pepperoni2.5 oz
Mozzarella5 oz
Basil10 Leaves
import React from 'react';

import {Table} from '@workday/canvas-kit-react/table';
import {Heading} from '@workday/canvas-kit-react/text';
import {useUniqueId} from '@workday/canvas-kit-react/common';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const styleOverrides = {
  parentContainerStyles: createStyles({
    marginBottom: system.space.x4,
  }),
  tableHeaderStyles: createStyles({
    backgroundColor: system.color.bg.alt.softer,
  }),
};

export default () => {
  const headingID = useUniqueId();

  return (
    <>
      <Heading as="h3" id={headingID} size="small" cs={styleOverrides.parentContainerStyles}>
        Pizza Toppings
      </Heading>
      <Table aria-labelledby={headingID}>
        <Table.Head>
          <Table.Row>
            <Table.Header scope="col" cs={styleOverrides.tableHeaderStyles}>
              Toppings
            </Table.Header>
            <Table.Header scope="col" cs={styleOverrides.tableHeaderStyles}>
              Amount
            </Table.Header>
          </Table.Row>
        </Table.Head>
        <Table.Body>
          <Table.Row>
            <Table.Cell>Pepperoni</Table.Cell>
            <Table.Cell>2.5 oz</Table.Cell>
          </Table.Row>
          <Table.Row>
            <Table.Cell>Mozzarella</Table.Cell>
            <Table.Cell>5 oz</Table.Cell>
          </Table.Row>
          <Table.Row>
            <Table.Cell>Basil</Table.Cell>
            <Table.Cell>10 Leaves</Table.Cell>
          </Table.Row>
        </Table.Body>
      </Table>
    </>
  );
};

Right to Left

Table supports right-to-left languages when specified in the CanvasProvider theme.

משקאות קפה וגדלים
מַשׁקֶהגודל
אספרסו1 גר
מקיאטו2 גרם אספרסו
גזירה2 גרם אספרסו, 1 גרם חלב מוקצף
import React from 'react';

import {Table} from '@workday/canvas-kit-react/table';
import {CanvasProvider} from '@workday/canvas-kit-react/common';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const tableHeaderStyles = createStyles({
  backgroundColor: system.color.bg.alt.softer,
});

export default () => {
  return (
    <CanvasProvider dir="rtl">
      <Table>
        <Table.Caption>משקאות קפה וגדלים</Table.Caption>
        <Table.Head>
          <Table.Row>
            <Table.Header scope="col" cs={tableHeaderStyles}>
              מַשׁקֶה
            </Table.Header>
            <Table.Header scope="col" cs={tableHeaderStyles}>
              גודל
            </Table.Header>
          </Table.Row>
        </Table.Head>
        <Table.Body>
          <Table.Row>
            <Table.Cell>אספרסו</Table.Cell>
            <Table.Cell>1 גר</Table.Cell>
          </Table.Row>
          <Table.Row>
            <Table.Cell>מקיאטו</Table.Cell>
            <Table.Cell>2 גרם אספרסו</Table.Cell>
          </Table.Row>
          <Table.Row>
            <Table.Cell>גזירה</Table.Cell>
            <Table.Cell>2 גרם אספרסו, 1 גרם חלב מוקצף</Table.Cell>
          </Table.Row>
        </Table.Body>
      </Table>
    </CanvasProvider>
  );
};

Example with Caption

Users are free to use a caption instead of a heading. A caption is not required but it is good for accessibility purposes.

Coffee Drinks and Sizes
DrinkSize
Espresso1 oz
Macchiato2 oz Espresso
Cortado2 oz Espresso, 1 oz Foamed Milk
Cappuccino2 oz Espresso, 2 oz Foamed Milk, 2 oz Steamed Milk
import React from 'react';

import {Table} from '@workday/canvas-kit-react/table';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const tableHeaderStyles = createStyles({
  backgroundColor: system.color.bg.alt.softer,
});

export default () => {
  return (
    <Table>
      <Table.Caption>Coffee Drinks and Sizes</Table.Caption>
      <Table.Head>
        <Table.Row>
          <Table.Header scope="col" cs={tableHeaderStyles}>
            Drink
          </Table.Header>
          <Table.Header scope="col" cs={tableHeaderStyles}>
            Size
          </Table.Header>
        </Table.Row>
      </Table.Head>
      <Table.Body>
        <Table.Row>
          <Table.Cell>Espresso</Table.Cell>
          <Table.Cell>1 oz</Table.Cell>
        </Table.Row>
        <Table.Row>
          <Table.Cell>Macchiato</Table.Cell>
          <Table.Cell>2 oz Espresso</Table.Cell>
        </Table.Row>
        <Table.Row>
          <Table.Cell>Cortado</Table.Cell>
          <Table.Cell>2 oz Espresso, 1 oz Foamed Milk</Table.Cell>
        </Table.Row>
        <Table.Row></Table.Row>
        <Table.Row>
          <Table.Cell>Cappuccino</Table.Cell>
          <Table.Cell>2 oz Espresso, 2 oz Foamed Milk, 2 oz Steamed Milk</Table.Cell>
        </Table.Row>
      </Table.Body>
    </Table>
  );
};

Fixed Column

Users may add styles to the Table.Header to render a fixed column. The example below assigns a width to the Table to guarantee the fixed column is triggered, but you are free to omit the width if you would only like the fixed column to be triggered if necessary.

Performance Car Specs

MakeModelYearPriceEngineTransmissionHorsepowerTorqueCurb Weight
Porsche992 911 GT32022Starts at $160,0004.0L Flat 6PDK or 7-Speed Manual502hp346 lb-ft3,164 lbs
BMWM5 Competition2018Starts at $105,000Twin-Turbo 4.4L V8Automatic627hp553 lb-ft4,345 lbs
Alfa Romeo1750 GTV1970$30,000 - $55,0001.75L Inline 4Manual122hp137 lb-ft2,140 lbs
LotusEmira2023Starts at $78,000Supercharged 3.5L V6Automatic or 6-Speed Manual400hp317 lb-ft3520 lbs
ToyotaSupra1998$40,000 - $80,0003.0L Inline 6Automatic or 6-Speed Manual320hp315 lb-ft3,599 lbs
NissanSkyline GT-R1994$45,000 - $90,0002.6L Twin-Turbo Inline 65-Speed Manual276hp260 lb-ft3,153 lbs
import React from 'react';

import {Table} from '@workday/canvas-kit-react/table';
import {Heading} from '@workday/canvas-kit-react/text';
import {useUniqueId} from '@workday/canvas-kit-react/common';
import {createStyles, px2rem} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const styleOverrides = {
  parentContainerStyles: createStyles({
    marginBottom: system.space.x4,
  }),
  tableStyles: createStyles({
    width: px2rem(690),
  }),
  tableHeaderStyles: createStyles({
    position: 'sticky',
    left: system.space.zero,
    backgroundColor: system.color.bg.alt.softer,
    borderRight: `2px solid ${system.color.border.divider}`,
  }),
};

export default () => {
  const headingID = useUniqueId();
  const exampleData = [
    {
      make: 'Porsche',
      model: '992 911 GT3',
      year: '2022',
      price: 'Starts at $160,000',
      engine: '4.0L Flat 6',
      transmission: 'PDK or 7-Speed Manual',
      horsepower: '502hp',
      torque: '346 lb-ft',
      curbWeight: '3,164 lbs',
    },
    {
      make: 'BMW',
      model: 'M5 Competition',
      year: '2018',
      price: 'Starts at $105,000',
      engine: 'Twin-Turbo 4.4L V8',
      transmission: 'Automatic',
      horsepower: '627hp',
      torque: '553 lb-ft',
      curbWeight: '4,345 lbs',
    },
    {
      make: 'Alfa Romeo',
      model: '1750 GTV',
      year: '1970',
      price: '$30,000 - $55,000',
      engine: '1.75L Inline 4',
      transmission: 'Manual',
      horsepower: '122hp',
      torque: '137 lb-ft',
      curbWeight: '2,140 lbs',
    },
    {
      make: 'Lotus',
      model: 'Emira',
      year: '2023',
      price: 'Starts at $78,000',
      engine: 'Supercharged 3.5L V6',
      transmission: 'Automatic or 6-Speed Manual',
      horsepower: '400hp',
      torque: '317 lb-ft',
      curbWeight: '3520 lbs',
    },
    {
      make: 'Toyota',
      model: 'Supra',
      year: '1998',
      price: '$40,000 - $80,000',
      engine: '3.0L Inline 6',
      transmission: 'Automatic or 6-Speed Manual',
      horsepower: '320hp',
      torque: '315 lb-ft',
      curbWeight: '3,599 lbs',
    },
    {
      make: 'Nissan',
      model: 'Skyline GT-R',
      year: '1994',
      price: '$45,000 - $90,000',
      engine: '2.6L Twin-Turbo Inline 6',
      transmission: '5-Speed Manual',
      horsepower: '276hp',
      torque: '260 lb-ft',
      curbWeight: '3,153 lbs',
    },
  ];
  return (
    <>
      <Heading as="h3" id={headingID} size="small" cs={styleOverrides.parentContainerStyles}>
        Performance Car Specs
      </Heading>
      <Table cs={styleOverrides.tableStyles} aria-labelledby={headingID} tabIndex={0}>
        <Table.Head>
          <Table.Row>
            <Table.Header scope="col" cs={styleOverrides.tableHeaderStyles}>
              Make
            </Table.Header>
            <Table.Header scope="col">Model</Table.Header>
            <Table.Header scope="col">Year</Table.Header>
            <Table.Header scope="col">Price</Table.Header>
            <Table.Header scope="col">Engine</Table.Header>
            <Table.Header scope="col">Transmission</Table.Header>
            <Table.Header scope="col">Horsepower</Table.Header>
            <Table.Header scope="col">Torque</Table.Header>
            <Table.Header scope="col">Curb Weight</Table.Header>
          </Table.Row>
        </Table.Head>
        <Table.Body>
          {exampleData.map(item => (
            <>
              <Table.Row>
                <Table.Header scope="row" cs={styleOverrides.tableHeaderStyles}>
                  {item.make}
                </Table.Header>
                <Table.Cell>{item.model}</Table.Cell>
                <Table.Cell>{item.year}</Table.Cell>
                <Table.Cell>{item.price}</Table.Cell>
                <Table.Cell>{item.engine}</Table.Cell>
                <Table.Cell>{item.transmission}</Table.Cell>
                <Table.Cell>{item.horsepower}</Table.Cell>
                <Table.Cell>{item.torque}</Table.Cell>
                <Table.Cell>{item.curbWeight}</Table.Cell>
              </Table.Row>
            </>
          ))}
        </Table.Body>
      </Table>
    </>
  );
};

Base Html Table Example

If a user needs a standard HTML table with no CSS Grid features, then they can use the BaseTable component.

Coffee Drinks and Sizes
DrinkSize
Espresso1 oz
Macchiato2 oz Espresso
Cortado2 oz Espresso, 1 oz Foamed Milk
Cappuccino2 oz Espresso, 2 oz Foamed Milk, 2 oz Steamed Milk
import React from 'react';

import {BaseTable} from '@workday/canvas-kit-react/table';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const tableHeaderStyles = createStyles({
  backgroundColor: system.color.bg.alt.softer,
});

export default () => {
  return (
    <BaseTable>
      <BaseTable.Caption>Coffee Drinks and Sizes</BaseTable.Caption>
      <BaseTable.Head>
        <BaseTable.Row>
          <BaseTable.Header scope="col" cs={tableHeaderStyles}>
            Drink
          </BaseTable.Header>
          <BaseTable.Header scope="col" cs={tableHeaderStyles}>
            Size
          </BaseTable.Header>
        </BaseTable.Row>
      </BaseTable.Head>
      <BaseTable.Body>
        <BaseTable.Row>
          <BaseTable.Cell>Espresso</BaseTable.Cell>
          <BaseTable.Cell>1 oz</BaseTable.Cell>
        </BaseTable.Row>
        <BaseTable.Row>
          <BaseTable.Cell>Macchiato</BaseTable.Cell>
          <BaseTable.Cell>2 oz Espresso</BaseTable.Cell>
        </BaseTable.Row>
        <BaseTable.Row>
          <BaseTable.Cell>Cortado</BaseTable.Cell>
          <BaseTable.Cell>2 oz Espresso, 1 oz Foamed Milk</BaseTable.Cell>
        </BaseTable.Row>
        <BaseTable.Row></BaseTable.Row>
        <BaseTable.Row>
          <BaseTable.Cell>Cappuccino</BaseTable.Cell>
          <BaseTable.Cell>2 oz Espresso, 2 oz Foamed Milk, 2 oz Steamed Milk</BaseTable.Cell>
        </BaseTable.Row>
      </BaseTable.Body>
    </BaseTable>
  );
};

Which Component Should I Use?

If a user wants CSS Grid features with their Table, then use the Table component.

If a user does not want CSS Grid features with their Table, then use the BaseTable component.

Advanced

You can also find several advanced Table examples in our Storybook Examples section.

Custom Styles

Table and its subcomponents support custom styling via the cs prop. For more information, check our “How To Customize Styles”.

Component API

Table

Table is a simple styled compound component that renders a table element. It is used to present information in a two-dimensional table comprised of rows and columns of cells containing data. Table is built off of BaseTable and is using CSS Grid features.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
 <Table>
   <Table.Caption>Table Caption</Table.Caption>
   <Table.Head>
     <Table.Row>
       <Table.Header>Table Header</Table.Header>
       <Table.Header>Table Header</Table.Header>
     </Table.Row>
   </Table.Head>
   <Table.Body>
     <Table.Row>
       <Table.Header>Table Header</Table.Header>
       <Table.Header>Table Header</Table.Header>
     </Table.Row>
     <Table.Row>
       <Table.Header>Table Header</Table.Header>
       <Table.Cell>Table Data Cell</Table.Cell>
     </Table.Row>
     <Table.Row>
       <Table.Header>Table Header</Table.Header>
       <Table.Cell>Table Data Cell</Table.Cell>
     </Table.Row>
   </Table.Body>
   <Table.Footer>
     <Table.Row>
       <Table.Header>Table Header</Table.Header>
       <Table.Cell>Table Data Cell</Table.Cell>
     </Table.Row>
   </Table.Footer>
 </Table>
);
}

Layout Component

Table supports all props from thelayout component.

Props

Props extend from table. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

table
refReact.Ref<R = table>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Caption

Table.Caption renders a caption element.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
 return (
   <Table>
     <Table.Caption>Table Caption</Table.Caption>
     <Table.Body>
       <Table.Row>
         <Table.Header>Table Header</Table.Header>
         <Table.Cell>Table Cell</Table.Cell>
       </Table.Row>
     </Table.Body>
   </Table>
 );
}

Layout Component

Table.Caption supports all props from thelayout component.

Props

Props extend from caption. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

caption
refReact.Ref<R = caption>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Head

Table.Head renders a thead element.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
  <Table>
    <Table.Head>
      <Table.Row>
        <Table.Header>Table Header</Table.Header>
        <Table.Cell>Table Cell</Table.Cell>
      </Table.Row>
    </Table.Head>
  </Table>
);
}

Layout Component

Table.Head supports all props from thelayout component.

Props

Props extend from thead. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

thead
refReact.Ref<R = thead>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Body

Table.Body renders a tbody element.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
 <Table>
   <Table.Body>
     <Table.Row>
       <Table.Header>Table Header</Table.Header>
       <Table.Cell>Table Cell</Table.Cell>
     </Table.Row>
   </Table.Body>
 </Table>
);
}

Layout Component

Table.Body supports all props from thelayout component.

Props

Props extend from tbody. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

tbody
refReact.Ref<R = tbody>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Row

Table.Row renders a tr element.

Note: Table.Row is built on Grid. It will look for how many children are there and if those children are valid React Elements. This will adjust the amount of columns automatically using the gridTemplateColumns style prop and the width of the columns is also set using a minmax function in the gridTemplateColumns style prop. If a user would like to adjust this, it can be overwritten on Table.Row. See the example below for how to overwrite gridTemplateColumns.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
 <Table>
   <Table.Head>
     <Table.Row gridTemplateColumns="repeat(4, minmax(100px, 1fr))">
       <Table.Header>Table Header</Table.Header>
       <Table.Cell>Table Cell</Table.Cell>
     </Table.Row>
   </Table.Head>
 </Table>
);
}

Layout Component

Table.Row supports all props from thelayout component.

Props

Props extend from tr. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

tr
refReact.Ref<R = tr>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Header

Table.Header renders a th element.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
  <Table>
    <Table.Head>
      <Table.Row>
        <Table.Header>Table Header</Table.Header>
        <Table.Cell>Table Cell</Table.Cell>
      </Table.Row>
    </Table.Head>
  </Table>
);
}

Layout Component

Table.Header supports all props from thelayout component.

Props

Props extend from th. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

th
refReact.Ref<R = th>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Cell

Table.Cell renders a td element.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
  <Table>
    <Table.Body>
      <Table.Row>
        <Table.Header>Table Header</Table.Header>
        <Table.Cell>Table Cell</Table.Cell>
      </Table.Row>
    </Table.Body>
  </Table>
);
}

Layout Component

Table.Cell supports all props from thelayout component.

Props

Props extend from td. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

td
refReact.Ref<R = td>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Table.Footer

Table.Footer renders a tfoot element.

import {Table} from '@workday/canvas-kit-react/table';

export default function App() {
return (
  <Table>
    <Table.Footer>
      <Table.Row>
        <Table.Header>Table Header</Table.Header>
        <Table.Cell>Table Cell</Table.Cell>
      </Table.Row>
    </Table.Footer>
  </Table>
);
}

Layout Component

Table.Footer supports all props from thelayout component.

Props

Props extend from tfoot. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReactNode
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

tfoot
refReact.Ref<R = tfoot>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

Accessibility Guidelines

How Tables Impact The Accessible Experience

Whether you are comparing products or understanding a schedule, arranging information into rows and columns helps communicate relationships in the content. When users are unable to perceive the visual layout of the content, screen readers are able to derive context like the number of rows in a table from the number of <tr> elements. Similarly, the number of columns is based on the <th> and <td> elements used in a row.

Semantic, and correct, HTML markup is critical to providing access to tabular content. On the other hand, table markup used strictly for the purposes of content layout may be invisible to sighted users, but screen readers will continue to express the content in terms of rows and columns. This dated practice can make it much more difficult for non-visual users to understand simple content on a page.

Keyboard Interaction

Any interactive elements in the Table must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.

Tables must support the following keyboard interactions: Tab: Focuses interactive elements included inside the table cells (e.g. buttons, links, inputs, selects, etc.) Left Arrow or Right Arrow:Scroll the table with fixed columns

NOTE: The keyboard should only be allowed to focus on the interactive components inside of a table. Allowing the keyboard to focus on the individual rows of the table is not recommended.

Screen Reader Interaction

Tables must communicate the following to users:

  • The purpose of the table
  • The correct number of rows and columns in each table
  • Automatically describe the column headers when reading content from any row in the table
  • Automatically describe row headers when reading content from any column in the table (if applicable)

Design Annotations Needed

  • Specify the column header for every column
  • Specify the row headers, if applicable
  • Specify the caption of the table

Implementation Markup Needed

  • Do not use any table markup strictly for layout purposes.
  • Set the scope attribute to ”col” on the column header <th> elements.
  • Set the scope attribute to ”row” on the row header <th> elements, if applicable.
  • When a Table <caption> is not used, set an aria-labelledby attribute on the <table> element referencing the unique id of the table’s heading.
  • When a table can scroll horizontally with fixed columns, set tabindex=”0” on the <table> element.
  • [Included in component] The <caption> element must be used to briefly describe the purpose of a table.

Content Guidelines

  • When writing titles, column headers, and other text for Tables, refer to the Tables section of the Content Style Guide.

Mobile

PlatformAvailability
iOSYes
AndroidYes

Guidelines

  • Due to screen size limitations, the display of Tables on mobile is different from the desktop display. Rather than displaying inline on the page, there is a tile preview which the user can tap to display a full-page view-only Table. To edit the data in this Table, the user taps the row they wish to edit and an editable form of that row is shown.

    Please note: Tables 2.0 is not currently available for Mobile applications.

Can't Find What You Need?

Check out our FAQ section which may help you find the information you're looking for. For further information, contact the #ask-canvas-design or #ask-canvas-kitchannels on Slack.

On this Page: