Columns can be configured to have either a fixed or flexible size. In addition, you can have column min and max sizes and also default column sizes.

Note

Use columnDefaultWidth to configure the default column width. If a column is not sized otherwise, this will be applied. The default value for columnDefaultWidth is 200 (pixels).

For setting a minimum and maximum width for all columns, use columnMinWidth (defaults to 30) and columnMaxWidth (defaults to 2000) respectively.

Sizing the column is done via the controlled columnSizing prop and it’s uncontrolled variant, defaultColumnSizing. If you want to get updates to columns changing size as a result of user interaction, use onColumnSizingChange.

Fixed vs flexible sizing

The columnSizing prop is an object (or Map) of column ids to column sizing objects. Those sizing objects can have the following properties:

  • flex - use this for flexible columns. Behaves like the flex CSS property.
  • width - use this for fixed sized columns
  • minWidth - specifies the minimum width of the column. Useful for flexible columns or for restricting users resizing both fixed and flexible columns.
  • maxWidth - specifies the maximum width of the column. Useful for flexible columns or for restricting users resizing both fixed and flexible columns.

Note

If a column is not specified in the columnSizing prop (or its uncontrolled variant), or sized otherwise (eg: via the column type), it will have a fixed size, defaulting to columnDefaultWidth (which also defaults to 200 if no value is passed in).

const columnSizing: InfiniteTablePropColumnSizing = {
  country: {
    flex: 1,
    // minWidth is optional
    minWidth: 200
  },
  city: {
    width: 400,
    // and so is maxWidth
    maxWidth: 500
  },
  salary: {
    flex: 3
  }
}
// any column not specified in the columnSizing (or defaultColumnSizing) prop
// will have fixed width (defaulting to `columnDefaultWidth`, which in turn defaults to 200px)

Note

You might find specifying the column size outside the column object to be a bit verbose to start with, but it will be easier to manage in many cases and is much more flexible. For example, when the user resizes a column via d&d (COMING SOON) and you want to persist the new column sizes, you don’t have to update the whole columns map but instead update columnSizing alone. The same principle is true for columnPinning and other column-level props.

Deep Dive

Flexible sizing explained

The way flex sizing is implemented is similar to how CSS flexbox algorithm works. Explore this section to find out more details.

Take a look at the snippet below to see column sizing at work with flexible and fixed columns.

Using controlled columnSizing
Fork
import * as React from 'react';
import {
  InfiniteTable,
  DataSource,
  InfiniteTablePropColumnSizing,
  InfiniteTableColumn,
} from '@infinite-table/infinite-react';

export const columns = new Map<
  string,
  InfiniteTableColumn<Employee>
>([
  [
    'firstName',
    {
      field: 'firstName',
      header: 'First Name',
    },
  ],
  [
    'country',
    {
      field: 'country',
      header: 'Country',
    },
  ],

  [
    'city',
    {
      field: 'city',
      header: 'City',
    },
  ],
  [
    'salary',
    {
      field: 'salary',
      type: 'number',
      header: 'Salary',
    },
  ],
]);

const columnSizing: InfiniteTablePropColumnSizing = {
  country: { width: 100 },
  city: { flex: 1, minWidth: 100 },
  salary: { flex: 2, maxWidth: 500 },
};

export default function App() {
  return (
    <DataSource<Employee> data={dataSource} primaryKey="id">
      <InfiniteTable<Employee>
        columns={columns}
        columnDefaultWidth={50}
        columnSizing={columnSizing}
      />
    </DataSource>
  );
}

const dataSource = () => {
  return fetch(
    'https://infinite-table.com/.netlify/functions/json-server' + '/employees100'
  )
    .then((r) => r.json())
    .then((data: Employee[]) => data);
};

export type Employee = {
  id: number;
  companyName: string;
  companySize: string;
  firstName: string;
  lastName: string;
  country: string;
  countryCode: string;
  city: string;
  streetName: string;
  streetNo: string;
  department: string;
  team: string;
  salary: number;
  age: number;
  email: string;
};

Note

You might find viewportReservedWidth useful for advanced configuration when you have flexible columns.

Gotcha

You can also size (generated) group columns by using their column.id property.

For groupRenderStrategy=“multi-column”, if no id is specified in the group column configuration, each column will have a generated id like this: "group-by-${field}".

For groupRenderStrategy=“single-column”, if no id is specified in the groupColumn it will default to: "group-by".

Auto-sizing columns

For sizing columns to the width of their content, you can use autoSizeColumnsKey to declaratively auto-size columns:

  • when autoSizeColumnsKey is a string or number and the value of the prop is changed, all columns will be auto-sized.
  • when autoSizeColumnsKey is an object, it needs to have a key property (of type string or number), so whenever the key changes, the columns will be auto-sized. Specifying an object for autoSizeColumnsKey gives you more control over which columns are auto-sized and if the size measurements include the header or not.

When an object is used, the following properties are available:

  • key - mandatory property, which, when changed, triggers the update
  • includeHeader - optional boolean, - decides whether the header will be included in the auto-sizing calculations. If not specified, true is assumed.
  • columnsToSkip - a list of column ids to skip from auto-sizing. If this is used, all columns except those in the list will be auto-sized.
  • columnsToResize - the list of column ids to include in auto-sizing. If this is used, only columns in the list will be auto-sized.
Auto-sizing columns
Fork
import * as React from 'react';

import {
  InfiniteTable,
  DataSource,
} from '@infinite-table/infinite-react';

import type { InfiniteTablePropColumns } from '@infinite-table/infinite-react';

type Developer = {
  id: number;
  firstName: string;
  lastName: string;
  country: string;
  city: string;
  currency: string;
  preferredLanguage: string;
  stack: string;
  canDesign: 'yes' | 'no';
  hobby: string;
  salary: number;
  age: number;
};

const dataSource = () => {
  return fetch(
    'https://infinite-table.com/.netlify/functions/json-server' + '/developers1k'
  )
    .then((r) => r.json())
    .then((data: Developer[]) => data);
};

const columns: InfiniteTablePropColumns<Developer> = {
  id: { field: 'id' },
  firstName: { field: 'firstName' },
  preferredLanguage: { field: 'preferredLanguage' },
  stack: { field: 'stack' },
  country: { field: 'country' },
  age: { field: 'age', type: 'number' },
  salary: { field: 'salary', type: 'number' },
  currency: { field: 'currency', type: 'number' },
};

export default function GroupByExample() {
  const [key, setKey] = React.useState(0);
  const [includeHeader, setIncludeHeader] =
    React.useState(false);

  const autoSizeColumnsKey = React.useMemo(() => {
    return {
      includeHeader,
      key,
    };
  }, [key, includeHeader]);
  return (
    <>
      <div
        style={{
          color: 'var(--infinite-row-color)',
          background: 'var(--infinite-background)',
        }}>
        <label>
          <input
            checked={includeHeader}
            type={'checkbox'}
            onChange={(e) => {
              setIncludeHeader(e.target.checked);
            }}
          />{' '}
          Include header
        </label>

        <button
          style={{
            margin: 10,
            padding: 10,
            borderRadius: 5,
            border: '2px solid magenta',
          }}
          onClick={() => {
            setKey((key) => key + 1);
          }}>
          Click to auto-size
        </button>
      </div>

      <DataSource<Developer>
        primaryKey="id"
        data={dataSource}>
        <InfiniteTable<Developer>
          autoSizeColumnsKey={autoSizeColumnsKey}
          columns={columns}
          columnDefaultWidth={200}
        />
      </DataSource>
    </>
  );
}