Data Tables

Organizes structured content so that it is easy to scan, make comparisons, and analyze the data


CdrDataTable has been deprecated and replaced with the more flexible CdrTable component. CdrDataTable will still be available in FEDCOMP as @rei/data-table

# Overview

# Default (Medium)

Basic layout with a column of row headers. Rows alternate background colors.

# Column Headers

Layout for making comparisons such as between size and sleeve length. Column headers and row headers are displayed. When columns scroll, row header column is locked in place.

# Compact and Borderless

Layout with reduced spacing within each cell. All cells are borderless. Defines a column of row headers.

# Accessibility

To ensure that usage of this component complies with accessibility guidelines and screen readers can correctly read data:

  • Table caption should be included
  • Row headers and column headers should be defined
  • Table headers should never be empty, including the top-left cell of the data table
    • If needed, use cdr-sr-only to hide descriptive text that explains the content for the first column
  • Set the scope attribute to row or col to indicate that a header applies to the entire row or column

This component has compliance with WCAG guidelines by:

  • Providing <caption> element for data tables
  • Providing <th> element for row or column headers

# Guidelines

# Use When

  • Presenting multiple metrics and categories together
  • Displaying tabular data for users to compare

# Don't Use When

  • Positioning contents on page. Instead, use Grid
  • Laying out a page design. Instead, use Grid

# Content

All tables need a table caption or brief description that indicates the table's content.

Table headers:

  • Row headers are required
  • Column headers are optional
  • Use title case for header titles

Data cells:

  • Copy should be short and concise
  • Use sentence case for cell data
  • Text, numerical data, links, buttons, or icons are acceptable

# Anatomy

Default styles for tables:

  • All cells have a 1px border
  • Column headers have a 2px bottom border
  • Row headers have a 2px right border
    • When columns can scroll, the border is 4px
  • Rows alternate background colors to improve readability
  • Scrollbars will be native and dictated by the browser
  • Options available:
    • Compact only
    • Borderless only. If using borderless, ensure readability by using the alternating background colors for rows
    • Compact and borderless

# Text Alignment

Alignment impacts the table's readability. Make the data easy to read and simple to follow by:

  • Left-align is the default
  • Use the same number of decimal places

# Table Widths

  • Minimum cell width is 127px
  • Maximum cell width is 150px
  • Text will wrap to another line, if needed

# Do/Don't

Image showing size chart
Do use Data Tables to render size charts.
Image showing layout
Don't use Data Tables as a layout tool, including inserting images into tables.
Image showing size chart
Do use Data Tables to render size charts.
Image showing links in table cells
Don't use Data Tables - version 1 for interactive experiences, including links in cells.
Image showing technical specs table
Do use Data Tables to render technical specs.
Image showing large table cells full of data
Don't use Data Tables - version 1 for large amounts of data.
Image showing size chart with column and row headers
Do label information with row header or column header titles, when appropriate.
Image showing table data without column or row headers
Don't provide unlabeled data to the user.
Image showing table with default alternating row background colors
Do use standard table styles with alternate row background colors.
Image showing table with default styles removed
Don't override table styles with all-white row background colors.

# Responsiveness

Data Tables are responsive by default. Whenever the number of columns overflows the container, the entire table will scroll.

# Locked Column Scrolling

Data Table must have row headers and more than two columns of content. The responsive behavior should be:

  • Column of row headers will lock into place
  • Remaining columns will scroll

# Only Two Columns

  • Content will not scroll
  • Text within table cells will wrap to fit in the smaller container (or viewport)

# API

# Props

id

name

string

type

N/A

default

Sets unique id on <table> element.

colHeaders

name

array/boolean

type

false

default

The ‘colHeaders’ prop accepts an array of column header strings or a boolean value. Renders in the `thead’ slot. If the value is false, column heads are not displayed. For example, possible values are: [ ‘Column Header 1’, ‘Column Header 2’, ... ]

rowHeaders

name

array/boolean

type

false

default

The ‘rowHeaders’ prop accepts an array of row header strings or a boolean value. Renders in the ‘tbody’ slot. If the value is false, row heads are not displayed. For example, possible values are: [ ‘Row Header 1’, ‘Row Header 2’, ... ]

rowData

name

array

type

[ ]

default

Sets an array of objects representing each row in the table.

keyOrder

name

array

type

[ ]

default

Determines the order of cell content in a row.

caption

name

string

type

N/A

default

Sets the caption text for the table.

constrainWidth

name

boolean

type

true

default

Applies default width constraints to table cells.

# Slots

Find more information about using Slots in the article Getting Started as a Developer.

thead

name

Sets the innerHTML for the <thead> element. Includes default slot content.

tbody

name

Sets the innerHTML for the <tbody> element. Includes default slot content.

# Usage

# Using Props

The simplest way to use CdrDataTable is using the props API. The below example shows how:

  • The data props (colHeaders, rowHeaders, rowData) are used
  • keyOrder determines values displayed in each cell. The array order must match the colHeaders or column order

The locked-column behavior described in the design guidelines is available only when using the props API.

<template>
  <cdr-data-table
    :col-headers="colHeaders"
    :row-headers="rowHeaders"
    :row-data="rowData"
    :key-order="keyOrder"
    caption="CdrTable props usage"
  />
</template>

<script>
  ...
  data() {
    colHeaders: ['XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'],
    rowHeaders: ['Chest', 'Sleeve Length', 'Waist', 'Hip', 'Inseam'],
    keyOrder: ['xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl'],
    rowData: [
      {
        xs: '31.5 - 33',
        s: '35 - 38',
        m: '38 - 41',
        l: '42 - 45',
        xl: '46 - 49',
        xxl: '50 - 53',
        xxxl: '54-57',
      },
      {
        s: '33',
        m: '34',
        l: '35',
        xl: '35.5',
        xxl: '36',
        xxxl: '36.6',
        xs: 'N/A',
      },
      ...
    ],
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# Using Slots

The same information can be rendered using CdrDataTable's named slots, however the locked column behavior is not available.

The below example shows:

  • How to use the thead and tbody slots to define table markup
  • colHeaders prop set to true because the thead slot is being used
  • scope attribute on th elements inside a slot


 


 



 










 

























<template>
  <cdr-data-table
    :col-headers="true"
    caption="CdrTable slots usage"
  >
    <template slot="thead">
       <tr>
         <th
           class="empty"
           scope="col"
         />
         <th
           v-for="(header, index) in tableData.colHeaders"
           :key="index"
           scope="col"
         >
           {{ header }}
         </th>
       </tr>
     </template>
     <template slot="tbody">
       <tr
         v-for="(row, index) in tableData.rowData"
         :key="'tr_' + index"
       >
         <th
           scope="row"
         >{{ tableData.rowHeaders[index] }}</th>
         <td
           v-for="(key, index) in ['xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl']"
           :key="index"
         >{{ row[key] }}
         </td>
       </tr>
     </template>
  </cdr-data-table>
</template>

<script>
  ...
  data() {
    ...
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

The below example uses:

  • compact and borderless modifiers
  • CdrDataTable's named slots
  • Markup is manual, not data-driven
<cdr-data-table
  modifier="compact borderless"
  caption="Full Manual - Compact & Borderless"
  id="full-manual"
>
  <template slot="tbody">
    <tr>
      <th scope=”row”>Best Use</th>
      <td>Casual</td>
    </tr>
    <tr>
      <th scope=”row”>Fabric</th>
      <td>Cotton canvas</td>
    </tr>
    <tr>
      <th scope=”row”>Lining Fabric</th>
      <td>Polyester microfleece/nylon</td>
    </tr>
    ...
  </template>
</cdr-data-table>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Responsive Setup

CdrDataTable relies on the mounted lifecycle hook to set up some responsive functionality. Use v-if to ensure that CdrDataTable doesn't render before the data is available.

<template>
  <cdr-data-table
    :col-headers="colHeaders"
    :row-headers="rowHeaders"
    :row-data="rowData"
    :key-order="keyOrder"
    v-if="hasData"
  />
</template>

<script>
  ...
  data() {
    hasData: false,
    ...
  },
  mounted() {
    fetch('https://swapi.co/api/people')
     .then(response => response.json())
     .then((json) => {
       this.hasData = true;
       ...
     })
     .catch(err => console.log(err));
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Modifiers

Following variants are available to the cdr-data-table modifier attribute:

Value Description
'compact' Reduces cell padding
'borderless' Removes cell borders