Interactive Tables

Use SDK table primitives for sortable/resizable/reorderable tables instead of maintaining custom table mechanics per widget.

What The SDK Provides

  • InteractiveTable: shared table rendering with sticky headers and interaction chrome

  • useInteractiveTableState: sorting, order, width, drag bookkeeping

  • helpers: fitColumnWidths, normalizeColumnOrder, normalizeColumnWidths, resolveColumnKey

  • StateChip: consistent enum-style chip rendering with optional brush integration

Real Pattern: Components Table Widget

ska-octopus-components-table-widget/src/components/ComponentsTable.tsx shows a production pattern:

  • Initializes useInteractiveTableState with configured order/width/sort

  • Applies responsive auto-fit widths when no saved widths are present

  • Sorts rows by selected column (including synthetic columns)

  • Uses StateChip for enum values

Persist User Table State

Pair table state callbacks with useWidgetConfigPersistence(instanceId):

const { persistConfig } = useWidgetConfigPersistence(instanceId);

const handleColumnOrderChange = (nextOrder: string[]) => {
  persistConfig({ columnOrder: nextOrder });
};

const handleColumnWidthsChange = (nextWidths: Record<string, number>) => {
  persistConfig({ columnWidths: nextWidths });
};

const handleSortChange = (next: { key: string; dir: "asc" | "desc" }) => {
  persistConfig({ sortKey: next.key, sortDir: next.dir });
};

When To Use fitColumnWidths

Use fitColumnWidths or a project wrapper when:

  • Container width changes frequently

  • Visible columns are dynamic

  • You need deterministic first render widths

Recommendation

For any table heavy widget, start from the Components Table example and keep only domain specific data shaping in your widget.