GC Design SystemComponents
GC Design System Start to use Page templates overviewBasic page Components overviewAlertBreadcrumbsButtonCardCheckboxesContainerDate inputDate modifiedDetailsError messageError summaryFieldsetFile uploaderFooterGridHeaderHeadingIconInputLanguage toggleLinkNoticePaginationRadiosScreenreader-onlySearchSelectSide navigationSignatureStepperTableTextTextareaTheme and topic menuTop navigation CSS Shortcuts overview Reset styles Responsive layoutState Box sizingContainer sizingDisplayOverflowPositionVisibility FontFont familyFont sizeFont styleFont weightLine heightLink colourLink sizeLink text decorationList styleText alignText colourText overflowText transformWord break MarginPadding Align contentAlign itemsAlign selfFlexFlex directionFlex growFlex shrinkFlex wrapGapGrid columnsGrid rowsJustify contentJustify itemsJustify selfOrderPlace contentPlace itemsPlace self Background colourBorder colourBorder radiusBorder styleBorder width Icon namesIcon sizeImage CursorPointer eventsTransition Styles overviewDesign tokensColourSpacingTypography Contact usGet InvolvedFind a demo

Table
<gcds-table>

Also called: data table, data grid. A table is a structured layout of related data in rows and columns.

Table component preview

On this page

Coding and accessibility for tables

Use the correct component name

  • Use gcds-table in HTML, Vue, or React.
  • Use gcds-table-ng in Angular.

Define your columns and data

To build a table, you need at minimum to define the columns and the data.
  • Use the columns attribute to define the table’s columns and their behaviour.
  • Use the data attribute to populate the table with content.

Provide an accessible caption

Use the caption slot to give an accessible name to the table, so that assistive technologies can identify it and announce it.

Add filtering for narrowing results

Set filter to true to allow filtering, so people can narrow down results by keyword.

Add sorting for reordering data

  • Set sort to true to allow people to sort the table by column, so they can reorganize data by priority, recency, or magnitude, for example.
  • If the table has a default sort order that reflects how people are most likely to first read the data, set it using the sortDirection property in the relevant column object.

Add pagination for managing large datasets

  • Set pagination to true to split data into pages.
  • Adjust pagination-size-options to control how many rows are shown per page.

Examples

Explore the different ways you can configure the component. Each example shows a working implementation and ready-to-copy code.

In this section

Optional attributes

These attributes allow you to customize or extend the component’s behaviour and presentation.

columns

Use the columns attribute to define the columns of the table. Pass an array of objects, where each object defines a column and controls how it looks and behaves. Each column object takes the following properties:
  • alignment: Use alignment to control how the content inside the column cells is positioned horizontally. Set to start to align content to the left, center to align it to the middle, or end to align it to the right.
  • field: Use field to define the unique id that connects the column to the correct data. The value must match the key used for that data in your data object.
  • header: Use header to set the column heading that appears at the top of the column.
  • rowHeader: Set rowHeader to true if you want to mark each cell in the column as a row header. Row headers label what each row is about.
  • slotted: Set slotted to true to flag that the cell will render custom content. To see how each framework handles this, go to Framework-specific slots for custom content.
  • sort: Set sort to true to allow people to sort the table by that column.
  • sortDirection: Use sortDirection to set a default sort order for the column when the page loads. Set to asc for ascending order or desc for descending order.

data

Use data to pass the content of the table. Pass an array of objects where each object represents one row, and each key matches a column field.
<gcds-table
  columns='[{"field":"submission_id","header":"ID","rowHeader":true},{"field":"submitter_name","header":"Name"},{"field":"date_submitted","header":"Date Submitted"},{"field":"assigned_reviewer","header":"Reviewer"}]'
  data='[{"submission_id":"EXP-2026-011","submitter_name":"Carlos Rivera","date_submitted":"2026-01-17 4:12","status":"Pending Review","assigned_reviewer":"Lisa Wong"},{"submission_id":"EXP-2026-012","submitter_name":"Jennifer Kim","date_submitted":"2026-01-17 6:47","status":"Under Review","assigned_reviewer":"Michael Tran"},{"submission_id":"EXP-2026-013","submitter_name":"Marcus Brown","date_submitted":"2026-01-17 8:25","status":"Approved","assigned_reviewer":"Sarah Chen"},{"submission_id":"EXP-2026-014","submitter_name":"Olga Novak","date_submitted":"2026-01-17 10:40","status":"Pending Review","assigned_reviewer":"David Patel"},{"submission_id":"EXP-2026-015","submitter_name":"Raj Patel","date_submitted":"2026-01-18 3:20","status":"Rejected","assigned_reviewer":"Lisa Wong"}]'
></gcds-table>

filter

Set filter to true to display a filter input, so people can narrow down results by keyword.
<gcds-table filter></gcds-table>

filter-value

Use filter-value to set a default keyword in the filter input, so some rows are already filtered when the table loads. By default, there’s no set value.
<gcds-table filter filter-value="Dav"></gcds-table>

pagination

Set pagination to true to split the table into pages when there are many rows. By default, pagination is set to false.
<gcds-table pagination></gcds-table>

pagination-current-page

Use pagination-current-page to set which page is displayed when the table first loads. By default, it’s set to 1, which shows the first page.
<gcds-table pagination pagination-current-page="2"
></gcds-table>

pagination-size

Use pagination-size to set how many rows are displayed per page. The default is 10.
<gcds-table pagination pagination-size="10"
></gcds-table>

pagination-size-options

Use pagination-size-options to define the page size choices available to people in the row control. The default options are [10, 25, 50, 0]. Note: Including 0 in the options adds an “All” choice that displays all rows at once. Use with caution on large datasets, as it may affect performance.
<gcds-table pagination pagination-size-options="[10, 15, 20, 25, 0]"></gcds-table>

sort

Set sort to true to allow users to sort the table by clicking on column headers. Set to false to disable sorting across all columns. By default, sort is set to false. Note: The sort property in each column object has the final say. If a column sets sort to false, that column will not be sortable even if the table-level sort is set to true.
<gcds-table sort></gcds-table>

Slots

The default slot allows you to inject custom content into the component’s primary content area, and named slots, into specific areas.

caption

Use the caption slot to give an accessible name to the table, so that assistive technologies can identify it and announce it.
<gcds-table>
  <div slot="caption">
    <h5>Table caption</h5>
    <p>Detailed caption for the table</p>
  </div>
</gcds-table>

Framework-specific slots for custom content

Use custom cell content when you need something more than plain text in a cell, like a link, image, or button. To enable custom content for a column, set slotted to true in your column object. Each framework handles custom cell content differently. HTML, Vue, and Angular use slots or directives, while React uses the renderCell property. Use the cell:<field> slot to define custom content for a specific column. Replace <field> with the field name you set in the column object. Use data-bind-* to pass a row value directly into an attribute. Use data-bind-template-* when you need to insert a row value inside a string before assigning it to an attribute. For example, use it to build an image’s alt and src attributes. If interactive elements need to use the row data in their functions, you can use the properties of row, rowIndex, column and value through this.
<gcds-table
  columns='[
    ...,
    {
      field: "submission_id",
      header: "ID",
      slotted: true,
    },
    {
      field: "actions",
      header: "Actions",
      slotted: true,
    },
    ...,
  ];'
>
  <template slot="cell:submission_id">
    <a
      data-bind-template-href="/view_submission/{submission_id}"
      data-bind="submission_id"
    ></a>
  </template>
  <template slot="cell:actions">
    <gcds-button
      button-role="secondary"
      size="small"
      onclick="console.log(this.row, this.rowIndex, this.column, this.value)"
    >
      Console log row data
    </gcds-button>
  </template>
</gcds-table>
Use the #<field> slot to define custom content for a specific column. Replace <field> with the field name you set in the column object. Use { row } to access row data inside the slot.
<GcdsTable
  :columns="[
    ...,
    {
      field: 'submission_id',
      header: 'ID',
      slotted: true,
    },
    {
      field: 'actions',
      header: 'Actions',
      slotted: true,
    },
  ]"
>
  <template #submission_id="{ row }">
    <a
      :href="`/view_submission/${row.submission_id}`"
    >
      {{ '{{ row.submission_id }}' }}
    </a>
  </template>
  <template #actions="{ row, rowIndex, column, value }">
    <gcds-button
      button-role="secondary"
      size="small"
      @click="() => {
        console.log(row, rowIndex, column, value);
      }"
    >
      Console log row data
    </gcds-button>
  </template>
</GcdsTable>
Use the gcdsCell=”<field>” directive to assign custom cell content to the correct column. If interactive elements need to use the row data in their functions, you can use the properties of row, rowIndex, column and value through let-*.
<gcds-table-ng
  [columns]="[
    ...,
    {
      field: 'submission_id',
      header: 'ID',
      slotted: true,
    },
    {
      field: 'actions',
      header: 'Actions',
      slotted: true,
    },
  ]"
>
  <ng-template gcdsCell="submission_id" let-row>
    <a
      [href]="'/view_submission/' + row.submission_id"
    >
      {{ '{{ row.submission_id }}' }}
    </a>
  </ng-template>
  <ng-template
    gcdsCell="actions"
    let-row
    let-rowIndex="rowIndex"
    let-column="column"
    let-value="value"
  >
    <gcds-button
      button-role="secondary"
      (click)="logRow(row, rowIndex, column, value)"
    >
      Console log row data
    </gcds-button>
  </ng-template>
</gcds-table-ng>
Use the renderCell property to define the content to render in the cell. Unlike the other frameworks, React uses a renderCell property instead of slots. This property extends the column object with a function that returns what to display.
<GcdsTable
  columns={[
    ...,
    {
      field: 'submission_id',
      header: 'ID',
      slotted: true,
      renderCell: ({ row }) => {
        return (
          <a
            href={`/view_submission/${row.submission_id}`}
          >
            {{ '{{ row.submission_id }}' }}
          </a>
        );
      },
    },
    {
      field: 'actions',
      header: 'Actions',
      slotted: true,
      renderCell: ({ row, rowIndex, column, value }) => {
        return (
          <GcdsButton
            buttonRole="secondary"
            size="small"
            onClick={() => console.log(row, rowIndex, column, value)}
          >
            Console log row data
          </GcdsButton>
        )
      }
    },
  ]}
>
</GcdsTable>
Code builder Generate an instance of the component you need by selecting its code properties.
  • Explore by choosing different code values to generate the instance you want.
  • Get the code and pull it into your environment.
  • Add any copy you need to the component (like text for a label).
Note: The code builder uses English for all code elements, which follows standard practice.
Help us improve Have questions or a request? Give feedback on our contact form. Something's wrong? Raise it through GitHub with an account. You'll have access to the team's direct responses, progress made on your issue, and issues raised by others. Give feedback Report an issue on GitHub
2026-06-01