Skip to content

feat: Support sections in GridLayout#10340

Open
mehdibha wants to merge 1 commit into
adobe:mainfrom
mehdibha:grid-layout-sections
Open

feat: Support sections in GridLayout#10340
mehdibha wants to merge 1 commit into
adobe:mainfrom
mehdibha:grid-layout-sections

Conversation

@mehdibha

Copy link
Copy Markdown
Contributor

Closes

Currently you have to choose between virtualization and sections in a grid: GridLayout treats every top level collection node as a fixed size cell, so section and header nodes are never walked and a sectioned GridList/ListBox cannot be virtualized with <Virtualizer layout={GridLayout}>. ListLayout supports sections (headingSize/estimatedHeadingSize), but not grid arrangement.

This gap shows up in any sectioned grid: emoji pickers (I hit this building one in dotUI — a GridList with layout="grid", ~1,900 GridListItems grouped into GridListSections with GridListHeaders, filtered with Autocomplete), photo galleries grouped by album/date, dashboards grouped by category.

This PR adds section support to GridLayout:

  • Section nodes are walked like in ListLayout: the layout produces a hierarchical LayoutInfo for each section (parents before children, so CollectionBranch rendering and isPersistedKey ancestor checks work), sized to contain its rows.
  • Header nodes are laid out as full width rows interleaved with the uniform grid rows. Each section starts on a new row.
  • New GridLayoutOptions: headingSize and estimatedHeadingSize, mirroring ListLayout's modern option names (no deprecated *Height variants). Without headingSize, headers are measured, starting from estimatedHeadingSize (default 48) like ListLayout.
  • Headers of visible sections are always included in getVisibleLayoutInfos (matching ListLayout's behavior, e.g. for sticky positioning), and loaders inside sections are laid out as full width rows.
  • getDropTargetFromPoint ignores section/header rows when searching for drop targets.
  • Keyboard navigation across section boundaries works with the existing ListKeyboardDelegate grid logic because columns stay x-aligned across sections (covered by tests).

Backward compatibility: flat collections produce the same layout as before. update() was restructured from a precomputed rows loop into a streaming walk, preserving the existing behaviors: loader nodes still consume a grid slot and the trailing loader sentinel is laid out at the end; skeleton nodes still repeat to fill the remainder of the row and then the viewport; empty collection and preserveAspectRatio/measured-height semantics are unchanged. All existing GridLayout/GridList/ListBox tests pass unchanged, and the only public API change is the two new optional options.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

  • yarn jest packages/react-stately/test/virtualizer/GridLayout.test.ts — new geometry tests for sections/headers (plus the existing drop target tests).
  • yarn jest packages/react-aria-components/test/GridList.test.js — new virtualized grid layout with sections tests covering rendering/virtualization of offscreen sections and keyboard navigation across section boundaries (ArrowDown/Up keep the column across a section header, End reaches the last offscreen item).
  • Storybook: GridList → VirtualizedGridListGridSection — 10 sections × 25 items in a virtualized grid with headers. Scroll, click and arrow-key around; compare with the existing VirtualizedGridListGrid (flat) story for unchanged behavior.

🧢 Your Project:

dotUI

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