Skip to content

feat(ui/tables): resizable columns with horizontal scroll + autofit#861

Open
akira69 wants to merge 5 commits intoDonkie:masterfrom
akira69:feat/ui-table-interactions-upstream-split
Open

feat(ui/tables): resizable columns with horizontal scroll + autofit#861
akira69 wants to merge 5 commits intoDonkie:masterfrom
akira69:feat/ui-table-interactions-upstream-split

Conversation

@akira69
Copy link
Copy Markdown

@akira69 akira69 commented Feb 24, 2026

Summary

This PR introduces a reusable table interaction layer for column resizing and horizontal-scroll behavior across key list/settings tables. It also guards the new saved column-width state so a malformed local-storage entry recovers to defaults instead of blanking the page.

Why This Matters

  • Wide datasets are hard to scan when columns cannot be resized to fit real content.
  • Auto-fit on double-click removes repetitive manual resizing.
  • Stable horizontal scrolling and persisted widths improve day-to-day table usability.
  • Persisted width state should not be able to white-page a list screen.

What Changed

Reusable table interaction primitive

  • Added a shared ResizableTable wrapper for AntD tables.
  • Added drag-based header column resize handles.
  • Added double-click auto-fit on the resize handle.
  • Added per-table column width persistence through existing saved-state flow.
  • Ensured table horizontal scroll width tracks effective column minimum width.

Hardening

  • Guarded saved column-width state parsing in useSavedState so invalid persisted JSON falls back to defaults and self-heals on reload.

Wired pages

  • Filament list table
  • Spool list table
  • Vendor list table
  • Settings → Extra Fields table

Files of interest

  • client/src/components/column.tsx
  • client/src/components/resizableTable.tsx
  • client/src/pages/filaments/list.tsx
  • client/src/pages/settings/extraFieldsSettings.tsx
  • client/src/pages/spools/list.tsx
  • client/src/pages/vendors/list.tsx
  • client/src/utils/overrides.css
  • client/src/utils/saveload.ts

Scope / Independence

  • Standalone UI/table behavior PR.
  • No backend API/query/index changes.
  • No migration/schema/data changes.
  • Search/filter/performance dropdown behavior remains in #862.

Testing Performed

  • cd client && npm ci
  • cd client && ./node_modules/.bin/eslint src/utils/saveload.ts src/components/resizableTable.tsx src/components/column.tsx src/pages/filaments/list.tsx src/pages/spools/list.tsx src/pages/vendors/list.tsx src/pages/settings/extraFieldsSettings.tsx
  • cd client && ./node_modules/.bin/prettier --check src/utils/saveload.ts src/components/resizableTable.tsx src/components/column.tsx src/pages/filaments/list.tsx src/pages/spools/list.tsx src/pages/vendors/list.tsx src/pages/settings/extraFieldsSettings.tsx
  • cd client && VITE_APIURL=/api/v1 npm run build
  • Local runtime: uv run uvicorn spoolman.main:app --host 0.0.0.0 --port 9861
  • Seeded local validation data via the local API for vendor, filament, spool, and vendor extra-field rows
  • Playwright on http://localhost:9861/filament
    • verified resize handles render
    • dragged the Name column wider and confirmed the width updated immediately
    • double-clicked the Name column handle and confirmed auto-fit returned it to content width
    • reloaded and confirmed the saved width persisted
    • injected malformed saved width JSON and confirmed the page recovered and rewrote the state to {} instead of blanking
  • Playwright on http://localhost:9861/filament at 800x900
    • confirmed horizontal overflow is present
    • confirmed the Actions column is hidden below lg
  • Playwright on http://localhost:9861/filament at 1000x900
    • confirmed horizontal overflow is present
    • confirmed the Actions column remains pinned while the table body scrolls horizontally
  • Playwright smoke checks
    • http://localhost:9861/spool
    • http://localhost:9861/vendor
    • http://localhost:9861/settings/extra/vendor
    • confirmed resize handles render with populated rows on each page
  • Playwright on http://localhost:9861/spool
    • confirmed drag-resize on spool list columns (Material, Price)
    • confirmed double-click auto-fit on the Location column
    • confirmed resized widths persist after reload
  • Playwright on http://localhost:9861/vendor
    • confirmed drag-resize on the Name column
    • confirmed double-click auto-fit on the Name column
    • confirmed resized widths persist after reload
  • Playwright on http://localhost:9861/settings/extra/vendor
    • confirmed drag-resize on the Name column
    • confirmed double-click auto-fit on the Name column
    • confirmed resized widths persist after reload
  • Explicit reset-path validation
    • widened the filament Name column
    • removed the saved width entry from browser storage
    • reloaded and confirmed the column returned to its default width

Test Checklist

  • Filament list renders resize handles
  • Filament list drag-resize updates column width immediately
  • Filament list double-click auto-fit adjusts the column to content width
  • Filament list saved width persists after reload
  • Filament list recovers from malformed saved width JSON without blanking
  • Filament list shows horizontal overflow at narrower desktop widths
  • Filament list keeps the Actions column pinned while horizontally scrolling at desktop widths
  • Filament list hides the Actions column below lg
  • Spool list renders resize handles with populated rows
  • Vendor list renders resize handles with populated rows
  • Settings → Extra Fields (vendor) renders resize handles with populated rows
  • Spool list drag-resize and auto-fit were manually exercised
  • Vendor list drag-resize and auto-fit were manually exercised
  • Settings → Extra Fields drag-resize and auto-fit were manually exercised
  • Clearing browser storage was explicitly tested as a reset path
  • Mobile/touch resize behavior was tested on an actual touch device

@akira69 akira69 force-pushed the feat/ui-table-interactions-upstream-split branch from 778fdd4 to 2a1b736 Compare February 25, 2026 15:18
@akira69 akira69 marked this pull request as ready for review February 25, 2026 20:23
@akira69 akira69 marked this pull request as draft February 26, 2026 16:47
@akira69 akira69 marked this pull request as ready for review February 26, 2026 17:12
@akira69 akira69 closed this Mar 2, 2026
@akira69 akira69 reopened this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant