Skip to content

Table Resource 20260313

Paulo Gomes da Cruz Junior edited this page Apr 10, 2026 · 1 revision

TableResource Refactoring Documentation

Overview

The TableResource component was refactored to separate toolbar customization concerns from the core table rendering flow. At refactor completion, the main component was reduced from ~402 lines to ~323 lines, with column preference persistence and menu rendering extracted into focused modules.

This refactor was driven by two related goals:

  • reduce the amount of inline toolbar/preference logic in the main table component
  • make the toolbar extensible so callers can inject their own actions alongside the built-in column customization UI

Refactoring Goals

✅ Reduce component complexity — move preference and toolbar concerns out of the main table
✅ Enable extensibility — support consumer-provided toolbar actions via toolbarEntries
✅ Improve testability — isolate persistence logic and toolbar menu rendering
✅ Preserve public behavior — keep pagination, sorting, expansion, empty states, and loading behavior intact
✅ Keep persistence intact — preserve saved column visibility by table id

Architecture

Before

TableResource (~402 lines)
├── Table rendering
├── Pagination and sorting
├── Expand-row state management
├── Column preference loading/saving
├── Column customization toolbar JSX
└── All concerns mixed in one file

After

TableResource (~323 lines at refactor completion) — Table orchestration
├── useTableToolbar hook (68 lines) — column visibility state + preference persistence
├── ColumnCustomizationMenu component (59 lines) — toolbar menu UI
├── Table rendering
├── Pagination and sorting
├── Expand-row state management
└── Optional toolbarEntries support for consumer-provided actions

Extracted Pieces

1. useTableToolbar Hook

File: useTableToolbar.ts
Responsibility: Owns table-header visibility state and synchronizes it with user preferences

Behavior:

  • initializes local header state from the provided header definitions
  • loads saved visible-column ids from preferences once preference data is ready
  • persists selected header ids whenever visibility changes
  • exposes onToggleHeader(headerId) for the UI layer

Why extracted:

  • preference loading/saving is independent from table rendering
  • hook logic is much easier to unit test than inline useEffect blocks in JSX-heavy code
  • the main component can now focus on rendering, pagination, sorting, and row expansion

Tests: useTableToolbar.unit.test.ts (8 tests)


2. ColumnCustomizationMenu Component

File: ColumnCustomizationMenu/index.tsx
Responsibility: Renders the Carbon toolbar menu for showing/hiding columns

Behavior:

  • displays the “Edit columns” toolbar action
  • renders one checkbox per table header
  • delegates column toggling via onToggleHeader
  • stays presentation-focused, with no persistence logic inside the component

Why extracted:

  • menu markup was adding noise to the main table component
  • the column chooser is a self-contained UI unit with a clear public API
  • extraction makes future toolbar changes easier without touching table internals

Tests: ColumnCustomizationMenu/index.unit.test.tsx (5 tests)


Refactored Main Component

File: index.tsx

Responsibilities:

  1. Render loading, empty, and populated table states
  2. Manage row expansion and stale async expansion responses
  3. Coordinate sorting and pagination callbacks
  4. Orchestrate toolbar rendering and column customization

Key changes:

  • replaced inline column preference logic with useTableToolbar
  • replaced inline toolbar menu JSX with ColumnCustomizationMenu
  • added optional toolbarEntries?: ReactNode[] prop so consumers can inject extra toolbar actions
  • preserved existing sorting, expansion, pagination, and empty-state behavior

Public API Impact

Existing consumers

Existing TableResource usage remains compatible.

New capability

Consumers can now provide additional toolbar content:

<TableResource
	id="waste-search-results"
	headers={headers}
	content={content}
	loading={loading}
	error={error}
	displayToolbar
	toolbarEntries={[
		<Button key="export" kind="ghost">Export</Button>,
		<Button key="refresh" kind="ghost">Refresh</Button>,
	]}
/>

This was the only intentional API addition.

Test Structure

TableResource/
├── index.unit.test.tsx (13 tests)
│   ├── loading, empty, and error states
│   ├── sorting interactions
│   ├── pagination interactions
│   ├── row expansion behavior
│   └── toolbar rendering scenarios
├── useTableToolbar.unit.test.ts (8 tests)
│   ├── default header selection
│   ├── preference loading
│   ├── preference persistence
│   └── toggle behavior
└── ColumnCustomizationMenu/index.unit.test.tsx (5 tests)
		├── menu rendering
		├── checkbox rendering
		├── checked state
		└── toggle callbacks

Total test coverage around the refactor: 26 tests

Code Metrics

Metric Before After Change
Main component lines ~402 ~323 -20%
Extracted modules 0 2 +2
Toolbar extensibility None toolbarEntries ✅ Added
Preference logic location Inline Hook ✅ Extracted
Column menu UI Inline Component ✅ Extracted

Quality Assurance

✅ Existing table behavior preserved
✅ New toolbar extension point added
✅ Column visibility persistence preserved
✅ Dedicated tests added for extracted pieces
✅ No new dependencies introduced

Benefits Realized

  1. Cleaner orchestration — TableResource now reads as a table component again, not a table-plus-preferences blob.
  2. Reusable toolbar logic — preference-backed header management is encapsulated and testable.
  3. Extensible toolbar design — consumers are no longer limited to the built-in column menu.
  4. Safer maintenance — toolbar changes are less likely to affect pagination, sorting, or row expansion.

Notes

Line counts reflect the refactor completion state on March 13, 2026. Subsequent edits may have moved the current file lengths slightly without changing the architecture documented here.


Refactoring completed: March 13, 2026
Backward compatibility: Maintained, with one additive prop (toolbarEntries)
Primary outcome: Leaner table orchestration + reusable toolbar/persistence modules

Waste Plus Wiki

Home

Architecture

Codes

Decisions

Knowledge Base

Development

Changes

Clone this wiki locally