tables

star 4

Patterns for implementing tables using '@backstage/core-components' Table, including column definitions, sorting, filtering, and visibility persistence.

giantswarm By giantswarm schedule Updated 2/9/2026

name: tables description: Patterns for implementing tables using '@backstage/core-components' Table, including column definitions, sorting, filtering, and visibility persistence.

Table Structure

File Organization

  • Table components are organized in dedicated directories (e.g., DeploymentsTable/, ClustersTable/)
  • Separate column definitions into a columns.tsx file
  • Export a getInitialColumns function that accepts visibleColumns and returns TableColumn<T>[]
  • Define column field names as a const object (e.g., DeploymentColumns, ClusterColumns)

Table Component Pattern

import { Table, TableColumn } from '@backstage/core-components';
import { useTableColumns } from '@giantswarm/backstage-plugin-ui-react';

// Use generic Table component with typed data
<Table<YourDataType>
  isLoading={loading}
  options={{
    pageSize: 50,
    pageSizeOptions: [10, 25, 50, 100],
    emptyRowsWhenPaging: false,
    columnsButton: true, // Enable column visibility toggle
  }}
  data={data}
  columns={columns}
  style={{ width: '100%' }}
  title={<Typography variant="h6">Title ({data.length})</Typography>}
/>;

Column Definitions

Required Imports

import {
  isTableColumnHidden,
  semverCompareSort,
  sortAndFilterOptions,
} from '@giantswarm/backstage-plugin-ui-react';

Column Visibility Persistence

  • Use useTableColumns(TABLE_ID) hook to persist column visibility in localStorage
  • Apply visibility with isTableColumnHidden() when generating columns:
return columns.map(column => ({
  ...column,
  hidden: isTableColumnHidden(column.field, {
    defaultValue: Boolean(column.hidden),
    visibleColumns,
    queryParameters, // Optional: show columns if they have query params
  }),
}));

Sorting & Filtering

Semver Data

  • Use customSort: semverCompareSort(row => row.version) for version columns

Custom String Sorting/Filtering

  • Use sortAndFilterOptions(row => row.fieldValue) to add both customSort and customFilterAndSearch
  • Useful when the display value differs from the data value:
{
  title: 'Source',
  field: 'source',
  render: row => formatSource(row.sourceKind, row.sourceName),
  ...sortAndFilterOptions(row => `${row.sourceKind} ${row.sourceName}`),
}

DateTime Columns

  • Set type: 'datetime' for automatic date sorting
  • Use <DateComponent value={row.date} relative /> for rendering

Common Patterns

Link Columns with Route Refs

render: row => {
  const LinkWrapper = () => {
    const routeLink = useRouteRef(detailsRouteRef);
    return (
      <Link component={RouterLink} to={routeLink({ id: row.id })}>
        <Typography variant="inherit" noWrap>{row.name}</Typography>
      </Link>
    );
  };
  return <LinkWrapper />;
},

Columns with Subvalues

import { SubvalueCell } from '@backstage/core-components';

render: row => (
  <SubvalueCell value={<MainContent />} subvalue={row.description} />
),

Hidden by Default Columns

  • Set hidden: true on columns that should be hidden by default
  • Users can toggle visibility via the columns button

Refresh Action

actions={[
  {
    icon: () => <SyncIcon />,
    tooltip: 'Reload data',
    isFreeAction: true,
    onClick: () => retry(),
  },
]}

Not Available State

  • Use <NotAvailable /> component when data is missing
Install via CLI
npx skills add https://github.com/giantswarm/backstage --skill tables
Repository Details
star Stars 4
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator