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

column-management.mddocs/

Column Management

React Table provides comprehensive column management capabilities including dynamic reordering, resizing, and visibility control. These features enable users to customize their table layout and optimize their data viewing experience.

Capabilities

Column Ordering (useColumnOrder)

Enables dynamic reordering of table columns through drag-and-drop or programmatic control.

/**
 * Adds column ordering capabilities to the table
 * @param hooks - Hook registration object
 */
function useColumnOrder(hooks: Hooks): void;

interface ColumnOrderInstance {
  /** Set the order of columns by column ID array */
  setColumnOrder: (columnOrder: string[]) => void;
}

Usage Example:

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

function ReorderableTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    setColumnOrder,
    allColumns,
  } = useTable(
    {
      columns,
      data,
    },
    useColumnOrder
  );

  // Example: Reverse column order
  const reverseColumns = () => {
    const currentOrder = allColumns.map(column => column.id);
    setColumnOrder(currentOrder.reverse());
  };

  // Example: Reset to original order
  const resetOrder = () => {
    const originalOrder = columns.map((col, index) => col.id || col.accessor || index.toString());
    setColumnOrder(originalOrder);
  };

  return (
    <div>
      <div>
        <button onClick={reverseColumns}>
          Reverse Column Order
        </button>
        <button onClick={resetOrder}>
          Reset Order
        </button>
      </div>
      
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th 
                  {...column.getHeaderProps()}
                  draggable
                  onDragStart={(e) => {
                    e.dataTransfer.setData('columnId', column.id);
                  }}
                  onDragOver={(e) => e.preventDefault()}
                  onDrop={(e) => {
                    e.preventDefault();
                    const draggedColumnId = e.dataTransfer.getData('columnId');
                    const targetColumnId = column.id;
                    
                    if (draggedColumnId !== targetColumnId) {
                      const currentOrder = allColumns.map(col => col.id);
                      const draggedIndex = currentOrder.indexOf(draggedColumnId);
                      const targetIndex = currentOrder.indexOf(targetColumnId);
                      
                      // Reorder array
                      const newOrder = [...currentOrder];
                      newOrder.splice(draggedIndex, 1);
                      newOrder.splice(targetIndex, 0, draggedColumnId);
                      
                      setColumnOrder(newOrder);
                    }
                  }}
                  style={{ cursor: 'move' }}
                >
                  {column.render('Header')}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map(row => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>
                    {cell.render('Cell')}
                  </td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

Column Resizing (useResizeColumns)

Enables interactive column width adjustment with drag handles and programmatic control.

/**
 * Adds column resizing capabilities to the table
 * @param hooks - Hook registration object
 */
function useResizeColumns(hooks: Hooks): void;

interface ResizeColumnsInstance {
  /** Total width of all columns */
  totalColumnsWidth: number;
}

interface ResizeColumnInstance {
  /** Whether this column can be resized */
  canResize: boolean;
  /** Whether this column is currently being resized */
  isResizing: boolean;
  /** Get props for the resize handle element */
  getResizerProps: PropGetter;
}

Usage Example:

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

function ResizableTable({ columns, data }) {
  const defaultColumn = React.useMemo(
    () => ({
      minWidth: 30,
      width: 150,
      maxWidth: 400,
    }),
    []
  );

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    totalColumnsWidth,
  } = useTable(
    {
      columns,
      data,
      defaultColumn,
    },
    useBlockLayout, // Required for resizing
    useResizeColumns
  );

  return (
    <div>
      <div>Total Width: {totalColumnsWidth}px</div>
      
      <div 
        {...getTableProps()}
        style={{
          display: 'inline-block',
          border: '1px solid black',
        }}
      >
        <div>
          {headerGroups.map(headerGroup => (
            <div {...headerGroup.getHeaderGroupProps()} className="tr">
              {headerGroup.headers.map(column => (
                <div {...column.getHeaderProps()} className="th">
                  {column.render('Header')}
                  {/* Resize handle */}
                  <div
                    {...column.getResizerProps()}
                    className={`resizer ${
                      column.isResizing ? 'isResizing' : ''
                    }`}
                  />
                </div>
              ))}
            </div>
          ))}
        </div>
        
        <div {...getTableBodyProps()}>
          {rows.map(row => {
            prepareRow(row);
            return (
              <div {...row.getRowProps()} className="tr">
                {row.cells.map(cell => (
                  <div {...cell.getCellProps()} className="td">
                    {cell.render('Cell')}
                  </div>
                ))}
              </div>
            );
          })}
        </div>
      </div>
      
      <style jsx>{`
        .th,
        .td {
          margin: 0;
          padding: 0.5rem;
          border-bottom: 1px solid black;
          border-right: 1px solid black;
          position: relative;
          display: inline-block;
          box-sizing: border-box;
          overflow: hidden;
        }
        
        .th {
          font-weight: bold;
        }
        
        .resizer {
          display: inline-block;
          background: blue;
          width: 5px;
          height: 100%;
          position: absolute;
          right: 0;
          top: 0;
          transform: translateX(50%);
          z-index: 1;
          cursor: col-resize;
        }
        
        .resizer.isResizing {
          background: red;
        }
      `}</style>
    </div>
  );
}

Column Visibility (useColumnVisibility)

Built-in column visibility management (automatically included with useTable).

interface ColumnVisibilityInstance {
  /** All columns including hidden ones */
  allColumns: Column[];
  /** Currently visible columns */
  visibleColumns: Column[];
  /** Toggle visibility for all columns */
  toggleAllColumnsVisible: (visible?: boolean) => void;
  /** Get props for toggle all columns visibility */
  getToggleAllColumnsVisibleProps: PropGetter;
}

interface ColumnVisibilityColumnInstance {
  /** Whether this column is visible */
  isVisible: boolean;
  /** Toggle visibility for this column */
  toggleColumnVisible: (visible?: boolean) => void;
  /** Get props for column visibility toggle */
  getToggleColumnVisibleProps: PropGetter;
}

Usage Example:

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

function TableWithColumnToggle({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    allColumns,
    getToggleAllColumnsVisibleProps,
  } = useTable({
    columns,
    data,
  });

  return (
    <div>
      {/* Column Visibility Controls */}
      <div>
        <div>
          <label>
            <input
              type="checkbox"
              {...getToggleAllColumnsVisibleProps()}
            />{' '}
            Toggle All
          </label>
        </div>
        {allColumns.map(column => (
          <div key={column.id}>
            <label>
              <input
                type="checkbox"
                {...column.getToggleColumnVisibleProps()}
              />{' '}
              {column.Header}
            </label>
          </div>
        ))}
      </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()}>
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>
                    {cell.render('Cell')}
                  </td>
                ))}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

Combined Column Management

Combine multiple column management features for maximum flexibility.

import React from 'react';
import { 
  useTable, 
  useColumnOrder, 
  useBlockLayout, 
  useResizeColumns 
} from 'react-table';

function AdvancedColumnTable({ columns, data }) {
  const [columnVisibility, setColumnVisibility] = React.useState({});
  
  const defaultColumn = React.useMemo(
    () => ({
      minWidth: 50,
      width: 200,
      maxWidth: 500,
    }),
    []
  );

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    allColumns,
    setColumnOrder,
    totalColumnsWidth,
  } = useTable(
    {
      columns,
      data,
      defaultColumn,
      initialState: {
        hiddenColumns: Object.keys(columnVisibility).filter(
          key => !columnVisibility[key]
        ),
      },
    },
    useColumnOrder,
    useBlockLayout,
    useResizeColumns
  );

  return (
    <div>
      {/* Column Management Controls */}
      <div style={{ marginBottom: '20px' }}>
        <h3>Column Management</h3>
        
        {/* Visibility Controls */}
        <div>
          <h4>Visibility</h4>
          {allColumns.map(column => (
            <label key={column.id} style={{ marginRight: '10px' }}>
              <input
                type="checkbox"
                {...column.getToggleColumnVisibleProps()}
              />
              {column.Header}
            </label>
          ))}
        </div>
        
        {/* Order Controls */}
        <div>
          <h4>Order</h4>
          <button
            onClick={() => {
              const currentOrder = allColumns.map(col => col.id);
              setColumnOrder(currentOrder.reverse());
            }}
          >
            Reverse Order
          </button>
        </div>
      </div>
      
      {/* Resizable Table */}
      <div style={{ overflow: 'auto' }}>
        <div {...getTableProps()} className="table">
          <div>
            {headerGroups.map(headerGroup => (
              <div {...headerGroup.getHeaderGroupProps()} className="tr">
                {headerGroup.headers.map(column => (
                  <div {...column.getHeaderProps()} className="th">
                    <div className="header-content">
                      {column.render('Header')}
                      {column.canResize && (
                        <div
                          {...column.getResizerProps()}
                          className={`resizer ${
                            column.isResizing ? 'isResizing' : ''
                          }`}
                        />
                      )}
                    </div>
                  </div>
                ))}
              </div>
            ))}
          </div>
          
          <div {...getTableBodyProps()}>
            {rows.map(row => {
              prepareRow(row);
              return (
                <div {...row.getRowProps()} className="tr">
                  {row.cells.map(cell => (
                    <div {...cell.getCellProps()} className="td">
                      {cell.render('Cell')}
                    </div>
                  ))}
                </div>
              );
            })}
          </div>
        </div>
      </div>
      
      <div>
        Total table width: {totalColumnsWidth}px
      </div>
    </div>
  );
}

Types

interface TableState {
  /** Column order by column IDs */
  columnOrder: string[];
  /** Hidden column IDs */
  hiddenColumns: string[];
  /** Column resizing state */
  columnResizing: {
    columnSizes: Record<string, number>;
    headerIdWidths: Record<string, number>;
    columnWidth: number;
    isResizingColumn?: string;
  };
}

interface ColumnManagementMeta {
  instance: TableInstance;
  column: Column;
}

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