Repository navigation
feat(components,plugin-list): a list block in a narrow page region draws a compact list (objectui#12703) - #12797
Merged
objectstack-fleet[bot] merged 4 commits intoOct 16, 2026
Conversation
… blocks (objectui#12703) The page renderer measures each region's grid against the page body and publishes `compact` (narrower than half the page) or `full` through `usePageRegionPosture`; unknown width (no layout, no ResizeObserver) reads as no posture, so the full rendering stays the default. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
…e compact list (objectui#12703) The `list-view` block reads its page region's posture; in a region narrower than half the page `ListView` (host prop `compact`) draws a header with the title and record count over two-line rows (the view's first visible column, the second muted), without the toolbar, view tabs, row-number column, pager or record-count bar. Wide regions, unknown widths and every other host of `ListView` keep the full list. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
…i#12703) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
plugin-list README: the `compact` host prop the list-view page block sets. components README: usePageRegionPosture() and its (page - 24) / 2 cut. React Pages guide: a list-view block in a narrow region renders the compact list; measured, never authored; "View all" is a follow-up. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contributor
Author
Review: ACCEPT (part 1 of objectui#12703) — objectui PR #12797 ·
|
objectstack-fleet
Bot
deleted the
claude/issue-12703-compact-list-block
branch
October 16, 2026 21:56
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.
Part of #12703
Clause-②: yes —
@object-ui/componentsexports a new hookusePageRegionPostureand typePageRegionPosture, and@object-ui/plugin-list'sListViewPropsgains the optional host propcompact(the dispatch's provisionalno, corrected by measurement).What this does
A
list-viewblock in a page region narrower than half the page now draws a compact list: a header with its title and record count over two-line rows (the view's first visible column, its second muted below). It draws no toolbar, no view tabs, no#row-number column, no pager and no record-count bar. A region half the page or wider keeps today's full list, and so does any region whose width is not known.Part of, not a closing keyword: the ruled "View all" footer link is NOT in this PR. Opening the object list needs a destination the renderer cannot build on its own; the report on the card asks the PM to choose the mechanism. That half stays open.How the posture is decided (A1, measured)
A1 as stated is false: a page region does not know its width or span at render. Regions are placed by CSS (
asideismd:w-80next to aflex-1main), and the 12-column grid from objectui#12624 spans BLOCKS inside a region, not regions. So the page renderer now measures:PageRendererwatches its max-width body element (the element its regions are laid out in), and eachRegionContentwatches its own grid, both throughResizeObserverwith a firstgetBoundingClientRectreading in a layout effect. Nothing reads the window.pageRegionPostureFor(region, page)returnscompactwhen the region is narrower than(page - 24) / 2, which is half the page less thegap-6between side-by-side regions. A half-and-half cell (thedashboardtemplate) therefore staysfull.usePageRegionPosture()(new export of@object-ui/components). It isnulloutside a page region, before a measurement, withoutResizeObserver, and on the server.nullmeans full.ListViewBlock(thelist-viewregistration) reads the posture and passes the newcompacthost prop toListView.ListViewis unchanged for every other host, so the object list page is untouched. The compact posture applies to a paged grid, the view whose rowsListViewfetches a page of. A board, a calendar or a grouped grid keeps its own rendering. Rows render values through the shared cell renderers (getCellRenderer), and a row click goes through the samenavigation.handleClicka grid row uses.Studio: the non-design page preview renders through
SchemaRendererandPageRenderer, so it shows the posture with no change. The design-mode canvas (PageBlockCanvas) draws block cards, not the page renderer, and per the ruling no second designer rendering was built.PagePreview.tsxis untouched.Files
packages/components/src/renderers/layout/page-region-posture.tsx(new): the rule, the page width store, the region provider, the hook.packages/components/src/renderers/layout/page.tsx,page-block-grid.tsx(agridRefprop),packages/components/src/index.ts(the export).packages/plugin-list/src/ListViewBlock.tsx,ListView.tsx(thecompactprop and its branches),ListViewCompact.tsx(new: header and rows)..changeset/12703-compact-list-block.md.Evidence (all at
f61f6f2e7)pnpm exec vitest run --maxWorkers=1 packages/plugin-list/src/__tests__/ListViewBlock.compactRegion-12703.test.tsx: 6 passed. This pins (a) the aside block (320 of 1200) with no toolbar trigger, no tablist, no grid (so no#column), no count bar, and two two-line rows (first column over second); (b) its header title and count; (c) CONTROL: the main block (856 of 1200) on the same page with toolbar and grid,showRowNumbers: true, and exactly one grid on the page; unknown width keeps the full list; (d) CONTROL: the object list pageListViewand the block with no page are both full.packages/components/src/__tests__/page-region-posture-12703.test.tsx: 8 passed (the rule's thresholds, aside compact and main full, stacked aside full, a block nested in apage:cardreads the region, noResizeObservergives unknown, no regions gives none, no page gives none).pageRegionPostureFormutated to always returnfullthroughablation-replace.mjs(anchor 1 to 0, blob761c974f5b56to0dc11caf582a). Pin (a) went RED, and so did control (c), because with both blocks full the page holds two grids instead of one. Restored: blob equals HEAD andgit diff HEADis empty.usePageRegionPosture()with'narrow'inListViewBlock.tsxgivesTS2367 ... types 'PageRegionPosture | null' and '"narrow"' have no overlap. Restored, andgit diff HEADis empty.pnpm --filter '@object-ui/plugin-list^...' build, thentype-checkfor@object-ui/componentsand@object-ui/plugin-list: exit 0, both script names echoed.packages/plugin-list/dir: 144 files, 1493 tests passed.packages/components, narrowed and declared: the 22 test files that render the page renderer (selected bygit grepfor regions, PageRenderer, the block grid or a page type) passed, 224 tests. The other component tests are declared to CI.packages/app-shelltests that name PageView, PagePreview ordata-region: 41 files, 350 tests passed.eslinton the 9 changed ts/tsx files, run as the packagelintscripts run it (eslint ., no--max-warnings): 0 errors. There is no type-aware linting (noparserOptions.projectineslint.config.js), so this diff cannot change the verdict on any untouched file.check:phantom-deps,self-import,unreferenced-sources,doc-example-readers,handler-key-reads,side-effects-array,element-data-source-declaration,spec-symbols,action-forward-parity,designer-field-key-parity,icon-record-names,i18n-keys,i18n-drift,i18n-designer-parity,control-bytes,new-line-citations, pluscheck-hand-rolled-comment-mask,check-changeset-fixedandcheck-changeset-presence.check:spec-floorsexits 1 withno-artifactfor unbuilt packages, which is expected on main; recorded, not fixed.Acceptance notes
main(4f82b81): the Sales Home page hasheader,mainand anasideof widthmedium. At 1024 px with the app sidebar open, the page body is about 736 px wide and the aside is 320 px, so the aside is compact andmain(about 392 px, above 356) stays full.list-viewnodes still writeproperties.objectNameandviewType, which objectuimainno longer reads (objectui#12099; the platform converts stored nodes). No compact-specific change follows from that here.labeland falls back to the object label. In Sales Home the block'spage:cardalso has a title ("Upcoming Events"), so the card title and the list title both appear. That follows the ruling ("the block header shows its title"); the card can drop one of the two.pagination.pageSize.packages/plugin-list/README.md(thecompacthost prop),packages/components/README.md(usePageRegionPosture(), null means full, the(page - 24) / 2cut) andcontent/docs/guide/react-pages.md(alist-viewin a narrow region renders the compact list, measured and not authored, with "View all" as a follow-up) are updated inf04480a34, per the revised claim.Generated by Claude Code