Skip to content

feat: address the Parcelle staff-app dogfood findings#89

Merged
zvndev merged 1 commit into
mainfrom
feat/parcelle-dogfood-findings
Jul 25, 2026
Merged

feat: address the Parcelle staff-app dogfood findings#89
zvndev merged 1 commit into
mainfrom
feat/parcelle-dogfood-findings

Conversation

@zvndev

@zvndev zvndev commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes every item from the Parcelle staff-app dogfood pass: 14+ real tables migrated onto yable, including a 23k-row virtualized warehouse grid, master-detail boards, and inline blur-save editors. Each item below forced an app-side workaround.

Bugs / sharp edges

Container underflow on fully sized tables. distribute / stretch only ever grew auto-sized columns, so a table where every column has an explicit size had no participants: it pinned to its sized total and left a dead band on the right that no policy could close. Those tables now fall back to growing every visible column, and a new underflow: 'stretch-last' hands the whole remainder to the last column alone.

Widths resolve through columnSizing, so the sticky header, body, virtualized inner table, and pinned offsets all read one colgroup. That matters: the app-side CSS workaround (min-width: 100%) let the sticky header and the virtualized body resolve the slack independently and drift out of column alignment. New Playwright coverage asserts every header/body column pair stays within 1px under a sticky header plus row virtualization.

clickableRows gated onRowClick. row:click was only emitted when the rendered <Table> had clickableRows, so passing the handler to useTable alone silently did nothing, while row:dblclick and row:contextmenu always emitted unconditionally. row:click now emits unconditionally; clickableRows is purely the visual affordance and defaults on when an onRowClick handler is present. clickableRows={false} keeps the handler and drops the affordance.

Behavior change worth noting on review: anyone using clickableRows={false} to suppress the callback now gets the callback.

API and theming gaps

  • table.getToggleAllRowsSelectedHandler() / getToggleAllPageRowsSelectedHandler() mirror row.getToggleSelectedHandler(). Both ignore their event argument, so wiring one to onChange toggles rather than reading the event object as a truthy value. The old docs example (onChange={table.toggleAllPageRowsSelected}) had exactly that bug and is fixed.
  • Header/cell typography tokens: --yable-font-family-header, --yable-font-family-cell, --yable-font-weight-header, --yable-header-text-transform, --yable-header-letter-spacing. Every bundled theme now declares header typography through them instead of hardcoding it on its own .yable-th rule, which outranked any token set on the grid root. Density utilities that set --yable-font-size-header reach the header for the first time.
  • align on a column def emits data-align on header, body, and footer cells, with tabular figures when right-aligned. React and vanilla renderers both.
  • data-sorted="asc|desc" on .yable-th, replacing :has(.yable-sort-indicator[data-active='true']).
  • --yable-header-backdrop-filter (frosted sticky headers) and --yable-detail-accent-width / --yable-detail-accent-color (master-detail panel edge). Both default to visual no-ops.
  • ./package.json exported from all four packages, so require.resolve('@zvndev/yable-react/package.json') stops throwing ERR_PACKAGE_PATH_NOT_EXPORTED.

Density needed no code: <Table density> and .yable--density-* already replace hand-setting six spacing tokens, so the themes README documents them now.

Verification

  • Unit: 11/11 turbo tasks, including 14 new underflow cases, the align/data-sorted attribute tests, and a themes suite that fails if any theme reintroduces hardcoded header typography.
  • E2E: 59/59 Playwright, with 4 new tests for the underflow fix.
  • Browser: confirmed computed styles are byte-identical across all 8 themes before and after the typography refactor, and that each new token and attribute actually takes effect.
  • Typecheck and lint green. (Lint had one pre-existing prefer-const error in useAutoColumnSizing.ts; fixed with a targeted disable since it sits in a file this PR edits.)

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Everything below came out of migrating 14+ real tables (including a 23k-row
virtualized warehouse grid) onto yable, and each item is something that forced
an app-side workaround.

Bugs / sharp edges:

- Container underflow on fully sized tables. The `distribute` / `stretch`
  underflow policies only grew auto-sized columns, so a table where every column
  has an explicit `size` had no participants: it pinned to its sized total and
  left a dead band on the right. Such tables now fall back to growing every
  visible column, and a new `underflow: 'stretch-last'` hands the remainder to
  the last column alone. Widths resolve through `columnSizing`, so the sticky
  header, body, virtualized inner table, and pinned offsets stay on one
  colgroup; the CSS workaround for this let the header and the virtualized body
  resolve the slack independently and drift out of alignment.

- `clickableRows` gated `onRowClick`. `row:click` was only emitted when the
  rendered Table had `clickableRows`, so wiring the handler through `useTable`
  alone silently did nothing, while `row:dblclick` and `row:contextmenu` always
  emitted. `row:click` now emits unconditionally and `clickableRows` is purely
  the visual affordance, defaulting on when an `onRowClick` handler is present.

API and theming gaps:

- `table.getToggleAllRowsSelectedHandler()` and
  `getToggleAllPageRowsSelectedHandler()` mirror `row.getToggleSelectedHandler()`.
  Both ignore their event argument, so wiring one to `onChange` toggles instead
  of reading the event object as a truthy `value` flag.

- Header and cell typography tokens: `--yable-font-family-header`,
  `--yable-font-family-cell`, `--yable-font-weight-header`,
  `--yable-header-text-transform`, `--yable-header-letter-spacing`. Every
  bundled theme now declares its header typography through these instead of
  hardcoding it on its own `.yable-th` rule, which outranked any token set on
  the grid root.

- `align` on a column def emits `data-align` on header, body, and footer cells
  (with tabular figures when right-aligned), in both the React and vanilla
  renderers.

- `data-sorted="asc|desc"` on `.yable-th`, replacing
  `:has(.yable-sort-indicator[data-active='true'])`.

- `--yable-header-backdrop-filter` for frosted sticky headers, and
  `--yable-detail-accent-width` / `--yable-detail-accent-color` for a
  master-detail panel edge. Both default to visual no-ops.

- `./package.json` is now exported from all four packages, so
  `require.resolve('@zvndev/yable-react/package.json')` stops throwing
  ERR_PACKAGE_PATH_NOT_EXPORTED.

Density needed no code: `<Table density>` and `.yable--density-*` already
replace hand-setting six spacing tokens, so the themes README now documents them.

Verified with new unit tests, new Playwright coverage for the underflow fix
(including header/body column alignment under a sticky header plus row
virtualization), and browser checks that each new token and attribute actually
takes effect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
table Ready Ready Preview, Comment Jul 25, 2026 4:22pm
yable-demo Ready Ready Preview, Comment Jul 25, 2026 4:22pm

Request Review

@zvndev
zvndev merged commit 95c699a into main Jul 25, 2026
13 of 14 checks passed
@zvndev
zvndev deleted the feat/parcelle-dogfood-findings branch July 25, 2026 16:27
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