CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-table

Hooks for building lightweight, fast and extendable datagrids for React

Pending
Overview
Eval results
Files

row-features.mddocs/

Row Features

React Table provides comprehensive row-level functionality including expansion, selection, and individual row state management. These features enable building interactive tables with hierarchical data, multi-select capabilities, and per-row customization.

Capabilities

Row Expansion (useExpanded)

Enables hierarchical data display with expandable/collapsible rows for nested content.

/**
 * Adds row expansion capabilities to the table
 * @param hooks - Hook registration object
 */
function useExpanded(hooks: Hooks): void;

interface ExpandedInstance {
  /** Toggle expansion state for all rows */
  toggleAllRowsExpanded: (expanded?: boolean) => void;
  /** Array of currently expanded rows */
  expandedRows: Row[];
}

interface ExpandedRowInstance {
  /** Whether this row is expanded */
  isExpanded: boolean;
  /** Whether this row can be expanded */
  canExpand: boolean;
  /** Sub-rows for this row */
  subRows: Row[];
  /** Toggle expansion for this row */
  toggleRowExpanded: (expanded?: boolean) => void;
  /** Get props for expansion toggle element */
  getToggleRowExpandedProps: PropGetter;
}

Usage Example:

import React from 'react';
import { useTable, useExpanded } from 'react-table';

function ExpandableTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    toggleAllRowsExpanded,
    state: { expanded },
  } = useTable(
    {
      columns,
      data,
      getSubRows: (row) => row.subRows || [],
    },
    useExpanded
  );

  return (
    <div>
      <div>
        <button onClick={() => toggleAllRowsExpanded()}>
          {Object.keys(expanded).length ? 'Collapse All' : 'Expand All'}
        </button>
      </div>
      
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              <th>Expand</th>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>
                  {column.render('Header')}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map(row => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                <td>
                  {row.canExpand && (
                    <span
                      {...row.getToggleRowExpandedProps()}
                      style={{
                        cursor: 'pointer',
                        paddingLeft: `${row.depth * 2}rem`,
                      }}
                    >
                      {row.isExpanded ? '👇' : '👉'}
                    </span>
                  )}
                </td>
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>
                    {cell.render('Cell')}
                  </td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

Row Selection (useRowSelect)

Enables single or multi-row selection with customizable selection controls.

/**
 * Adds row selection capabilities to the table
 * @param hooks - Hook registration object
 */
function useRowSelect(hooks: Hooks): void;

interface RowSelectInstance {
  /** Toggle selection for all rows */
  toggleAllRowsSelected: (selected?: boolean) => void;
  /** Toggle selection for all rows on current page */
  toggleAllPageRowsSelected: (selected?: boolean) => void;
  /** Get props for select all checkbox */
  getToggleAllRowsSelectedProps: PropGetter;
  /** Get props for select all page rows checkbox */
  getToggleAllPageRowsSelectedProps: PropGetter;
  /** Whether all rows are selected */
  isAllRowsSelected: boolean;
  /** Array of selected row objects */
  selectedFlatRows: Row[];
}

interface RowSelectRowInstance {
  /** Whether this row is selected */
  isSelected: boolean;
  /** Whether some child rows are selected (for hierarchical data) */
  isSomeSelected: boolean;
  /** Toggle selection for this row */
  toggleRowSelected: (selected?: boolean) => void;
  /** Get props for row selection checkbox */
  getToggleRowSelectedProps: PropGetter;
}

Usage Example:

import React from 'react';
import { useTable, useRowSelect } from 'react-table';

// Custom checkbox component
const IndeterminateCheckbox = React.forwardRef(
  ({ indeterminate, ...rest }, ref) => {
    const defaultRef = React.useRef();
    const resolvedRef = ref || defaultRef;

    React.useEffect(() => {
      resolvedRef.current.indeterminate = indeterminate;
    }, [resolvedRef, indeterminate]);

    return <input type="checkbox" ref={resolvedRef} {...rest} />;
  }
);

function SelectableTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    selectedFlatRows,
    toggleAllRowsSelected,
    getToggleAllRowsSelectedProps,
  } = useTable(
    {
      columns,
      data,
    },
    useRowSelect,
    (hooks) => {
      hooks.visibleColumns.push((columns) => [
        // Add selection column
        {
          id: 'selection',
          Header: ({ getToggleAllRowsSelectedProps }) => (
            <div>
              <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
            </div>
          ),
          Cell: ({ row }) => (
            <div>
              <IndeterminateCheckbox
                {...row.getToggleRowSelectedProps()}
              />
            </div>
          ),
        },
        ...columns,
      ]);
    }
  );

  return (
    <div>
      <div>
        <button onClick={() => toggleAllRowsSelected(false)}>
          Clear Selection
        </button>
        <span>Selected: {selectedFlatRows.length} rows</span>
      </div>
      
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>
                  {column.render('Header')}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map(row => {
            prepareRow(row);
            return (
              <tr 
                {...row.getRowProps()}
                className={row.isSelected ? 'selected' : ''}
              >
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>
                    {cell.render('Cell')}
                  </td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
      
      <div>
        <h3>Selected Rows:</h3>
        <pre>
          {JSON.stringify(
            selectedFlatRows.map(row => row.original),
            null,
            2
          )}
        </pre>
      </div>
    </div>
  );
}

Row State Management (useRowState)

Provides individual state management for each row, useful for per-row configurations or temporary data.

/**
 * Adds individual row state management to the table
 * @param hooks - Hook registration object
 */
function useRowState(hooks: Hooks): void;

interface RowStateInstance {
  /** Individual row state by row ID */
  rowState: Record<string, any>;
}

interface RowStateRowInstance {
  /** Update state for this specific row */
  setState: (updater: any) => void;
  /** Current state object for this row */
  state: any;
}

Usage Example:

import React from 'react';
import { useTable, useRowState } from 'react-table';

function StatefulRowsTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
  } = useTable(
    {
      columns,
      data,
    },
    useRowState
  );

  return (
    <table {...getTableProps()}>
      <thead>
        {headerGroups.map(headerGroup => (
          <tr {...headerGroup.getHeaderGroupProps()}>
            <th>Actions</th>
            {headerGroup.headers.map(column => (
              <th {...column.getHeaderProps()}>
                {column.render('Header')}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps()}>
        {rows.map(row => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps()}>
              <td>
                <button
                  onClick={() => row.setState({ editing: !row.state.editing })}
                >
                  {row.state.editing ? 'Save' : 'Edit'}
                </button>
                <button
                  onClick={() => row.setState({ favorite: !row.state.favorite })}
                  style={{
                    color: row.state.favorite ? 'gold' : 'gray'
                  }}
                >
                  ⭐
                </button>
              </td>
              {row.cells.map(cell => (
                <td 
                  {...cell.getCellProps()}
                  style={{
                    backgroundColor: row.state.editing ? '#f0f0f0' : 'white'
                  }}
                >
                  {cell.render('Cell')}
                </td>
              ))}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

Combined Row Features

Combine multiple row features for advanced table functionality.

import React from 'react';
import { 
  useTable, 
  useExpanded, 
  useRowSelect, 
  useRowState 
} from 'react-table';

function AdvancedRowTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    toggleAllRowsExpanded,
    selectedFlatRows,
    state: { expanded, selectedRowIds },
  } = useTable(
    {
      columns,
      data,
      getSubRows: (row) => row.children || [],
    },
    useExpanded,
    useRowSelect,
    useRowState
  );

  return (
    <div>
      <div className="table-controls">
        <button onClick={() => toggleAllRowsExpanded()}>
          {Object.keys(expanded).length ? 'Collapse All' : 'Expand All'}
        </button>
        <span>Selected: {selectedFlatRows.length}</span>
      </div>
      
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              <th>Select</th>
              <th>Expand</th>
              <th>Actions</th>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>
                  {column.render('Header')}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map(row => {
            prepareRow(row);
            return (
              <tr 
                {...row.getRowProps()}
                className={[
                  row.isSelected && 'selected',
                  row.state.editing && 'editing',
                ].filter(Boolean).join(' ')}
              >
                <td>
                  <input
                    type="checkbox"
                    {...row.getToggleRowSelectedProps()}
                  />
                </td>
                <td>
                  {row.canExpand && (
                    <button
                      {...row.getToggleRowExpandedProps()}
                      style={{ marginLeft: `${row.depth}rem` }}
                    >
                      {row.isExpanded ? '▼' : '▶'}
                    </button>
                  )}
                </td>
                <td>
                  <button
                    onClick={() => 
                      row.setState({ editing: !row.state.editing })
                    }
                  >
                    {row.state.editing ? 'Save' : 'Edit'}
                  </button>
                </td>
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>
                    {cell.render('Cell')}
                  </td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

Types

interface TableState {
  /** Expanded row IDs */
  expanded: Record<string, boolean>;
  /** Selected row IDs */
  selectedRowIds: Record<string, boolean>;
  /** Individual row states */
  rowState: Record<string, any>;
}

interface RowFeatureMeta {
  instance: TableInstance;
  row: Row;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-table

docs

built-in-types.md

column-management.md

core-table.md

filtering.md

grouping.md

index.md

layout.md

pagination.md

row-features.md

sorting.md

utilities.md

tile.json