Repository navigation
feat(table): stack rows into blocks below a container width - #80
Merged
Merged
Conversation
- Added `stackBelow` prop to TTable for controlling stacking behavior below specified breakpoints. - Implemented logic to render table rows as blocks on narrow containers, enhancing accessibility and usability. - Updated styles to support stacked layout, ensuring proper display and semantics in both stacked and non-stacked modes. - Enhanced documentation for TTable to include details about new stacking behavior and its implications. - Added tests to verify the correct rendering and behavior of the stacked mode.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
TTablegainsstackBelow: under a container width the grid becomes one block per row, so nothing disappears behind a horizontal scroll on a phone.Until now the only answer on a narrow screen was the wrapper's horizontal scroll, with no affordance saying there was more to the right. Measured on a three-column ledger at 390px: the wrapper overflowed by 68px and the rightmost column — half the information on screen — was simply cut off, while the middle column was squeezed to ~110px and its text broke over four or five lines, so row heights ran from 60 to 133px.
Columns take
stack?: 'title' | 'field' | 'hidden', defaulting tofield. At most one title — the first column claiming it wins, since two headings in one block is not a block and honouring the last would make the result depend on column order in a way nobody would guess.Measured on the container, not the viewport
A table can sit in a narrow panel on a wide screen, and that is the case a media query cannot see. In one 1440px page a 372px wrapper stacks while a 742px wrapper beside it stays a table, both with zero overflow.
stackBelowtakes a breakpoint name rather than a free length, which is narrower than it looks: a container query cannot read a custom property in its condition, so an arbitrary value would need aResizeObserverper table — and this component is used two dozen times across the apps that asked for this. The pixel literals in the stylesheet are held equal totreeTokens.breakpointby the same test that already guardsTShow/THide, so they cannot drift.The accessibility half was the real work
display: blockdrops the implicit table semantics in several screen readers: rows stop being rows and cells stop being cells.roleis now declared on the table, both rowgroups, every row, every column header and every cell. Each is the element's own implicit role, so nothing changes above the breakpoint — they exist to survive the switch. Verified in the accessibility tree, stacked:Every value carries its column, which is what replaces the hidden header row.
A row link has to cover the whole block
rowState,rowHref/rowToandrowActivatablekeep working in a block — and the stretched link covers the block, not just its heading. That took two attempts. Outside stacked mode every cell after the first is raised above the link overlay so a button in the actions column stays clickable; stacked, those same cells are plain text under the title, and raising them punched a hole in the link. Inside the container query only cells that actually contain something focusable are raised — and never the first, which holds the overlay: positioning it makes it the overlay's containing block, andinset: 0then covers that cell alone. That is the exact trap the existing comment in the stylesheet warns about, and the first fix walked into it.Validation
pnpm lintpnpm typecheckpnpm test— 1174 passing, 13 newpnpm build— plusbuild:site,codegen:native:check,typecheck:strict-templates,check:themepnpm test:e2e— 11/11Measured in a browser, against the four conditions this change has to meet:
stackBelowcontainer-type: normal,display: table, header visible, overflow 0 — unchangedrowState+rowHrefin a blockrowLabelname,elementFromPointat the block centre finds the linkNotes
is a reading table, not an unmanaged gridandactivates through a real button, keeping the row a rowassertedrole === undefined. Their comments say what they were actually defending — notrole="grid"on the table, notrole="button"on the row — so they now assert the correct role instead of the absence of one. Same intent, stated more precisely.container-type: inline-sizeappliescontain: layout inline-size style, so it is set only on a wrapper carrying astack-belowmodifier rather than on every table in the library.stackSpan— two fields sharing a line inside the block — is not here. It was raised as a maybe and arrived without a measurement; worth doing if a block with many fields turns out too tall.