Skip to content

App pages: a list block in a region narrower than half the page takes a compact posture, without the toolbar and the row-number column #12703

Closed

Description

@objectstack-fleet

Source

Walked on objectui main efa9cb4fa at 1024 px, HotCRM's Sales Home page (/page/sales_home_page): the "Upcoming Events" block sits in the right third of the page and mounts the full list: Filter / Sort 1 / Display toolbar, the # column, and one visible column (Subject) with the rest clipped. The block's job is "the next five events"; the toolbar is the object list's, not the page's.

Target

  1. A list block inside a page region takes a compact posture when the region is narrower than half the page (or when the page declares compact: true on the block): no view tabs, no toolbar, no # column, the first two columns of the view as a two-line row (primary text + secondary muted line), a footer link "View all →" to the object list with the block's view.
  2. The block's header carries the title and the count; the page designer in Studio shows the posture on the block card.
  3. A page region of half the page or wider keeps today's full list.

File surface

The runtime page renderer and packages/app-shell/src/views/metadata-admin/previews/PagePreview.tsx, packages/plugin-list/src/ListView.tsx (the compact posture, if it does not exist yet as a prop), the page spec in packages/spec if compact is new (the card says so and files the spec change on objectstack-ai/objectstack), tests beside.

Acceptance

  1. Tests: a list block in a 4-column region renders no toolbar and no # column; in a 12-column region it renders the full list.
  2. Screenshot of Sales Home at 1024 and 1280 px.
  3. pnpm --filter @object-ui/app-shell test, pnpm --filter @object-ui/plugin-list test green.

Constraints

  • objectui#12624 (block grids with spans) touches the same renderer; whichever lands second rebases, and the two may be taken by one lane in sequence.

Evidence

Screenshots on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui (commit 0f4e3f4ee, never merged): r4-sales-home-page.jpg.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 fourth review: objectui main efa9cb4fa, HotCRM 4f82b815 on platform 18.0.0-next.2, the vite console on :5180 against objectstack dev on :4001, the maintainer's browser pane at 1024 × 768 (dark, en). The maintainer asked for every finding to be filed on the repository it belongs to, verbatim: 「全部立卡,平台问题到 objectui,审计日志核查到 objectstack,HotCRM 转化流程到 hotcrm。」

Activity

  1. added
    enhancementNew feature or request
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    and removed on Oct 16, 2026
  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 (priority:p2)
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12703-compact-list-block (part 1, merged as PR #12797 / a8add5c); part 2: claude/issue-12703-view-all-link
    Worktree: objectui-issue-12703
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: the page renderer's list-block path (packages/components/src/renderers/layout/page.tsx and whatever renders a page region's list-view / object-grid block, measured at start); packages/plugin-list/src/ListView.tsx (the compact posture, if it is not already a prop); packages/app-shell/src/views/metadata-admin/previews/PagePreview.tsx only where the designer's block card shows the posture; packages/i18n/src/locales/*.ts (new keys only, all ten packs); tests beside each; one .changeset/12703-*.md (stop on breach; explain in the report). ⛔ No new spec key: the card's optional compact: true is out of this claim, and the posture is driven by the region's width alone.
    Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate for these paths)
    Clause-②: no (provisional: the dev reports yes if a published prop or export of @object-ui/plugin-list / @object-ui/components gains a member)
    Responsibility: n/a — not a defect card (an enhancement: a compact posture for a list block in a narrow page region)
    Thread-read: none
    Serial constraints cleared: scanned every open objectui PR's file list just now. None touches the page renderer, ListView.tsx or PagePreview.tsx. objectui#12624 (block grids with spans, pm:queue, deferred by this seat because it may need a spec key) touches the same renderer and is not in flight; the card names "whichever lands second rebases". This seat's in-flight objectui#12743 (PR #12782) touches the filter builders and FilterUI, so it is disjoint.
    Revised 2026-10-16T21:20Z (contract review of PR #12797, objectui AGENTS.md #2 Docs-driven): the surface adds packages/plugin-list/README.md, packages/components/README.md and one guide file, content/docs/guide/react-pages.md or content/docs/guide/slotted-pages.md. They document the new compact host prop and usePageRegionPosture() in the same PR. Serial check: no open objectui PR touches these files (scanned 2026-10-16T21:19Z).
    Revised 2026-10-16T21:58Z for part 2 (seat ruling 6224804504, option B): the surface adds packages/react/src/context/RelatedRecordActionsContext.tsx (one new optional member, e.g. listHref(object, view?) plus its SPA open), packages/app-shell/src/views/PageView.tsx (supplies it from the app and router root it already knows), packages/plugin-list/src/ListViewCompact.tsx / ListViewBlock.tsx (the "View all" footer link), packages/i18n/src/locales/*.ts (the "View all" key, all ten packs), the docs touched in part 1 (packages/plugin-list/README.md, packages/react/README.md, content/docs/guide/react-pages.md), tests beside each, and one .changeset/12703-view-all-link.md. ⛔ The block's inline filter is never encoded in the URL. Serial check for part 2: no open objectui PR touches these files (scanned 2026-10-16T21:57Z).
    Claimed at: 2026-10-16T20:25Z

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 12703,
    "status": "needs_decision",
    "branch": "claude/issue-12703-compact-list-block",
    "pr": "#12797",
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "dispatch_md5": "8550f34ccbf170d674b172872d3e652a",
    "summary": "Implemented the width-driven compact posture, with no spec key. PageRenderer measures its max-width body and each RegionContent measures its grid (ResizeObserver plus a first getBoundingClientRect reading in a layout effect). A region narrower than (page - 24)/2, i.e. half the page less the gap-6 between side-by-side regions, is 'compact', and the answer is published through the new usePageRegionPosture() export of @object-ui/components. It is null when the width is unknown or outside a region, and null keeps the full list. The list-view block (ListViewBlock) reads it and passes a new ListView host prop compact. On a paged grid the list then draws a header (title + record count) over two-line rows (first visible column, second muted), with no toolbar, tabs, # column, pager or count bar. Wide regions, unknown widths and the object list page are unchanged. A1 as stated is FALSE: a region knows neither its span nor its width at render, because regions are placed by CSS and the #12624 12-column grid spans blocks inside a region. Hence the measurement. The ruled 'View all' footer link is NOT implemented: no seam mounted on the page route can build an object-list destination (open_questions[0]). For that reason the PR says 'Part of #12703'. Studio's non-design preview renders through PageRenderer and shows the posture as-is. The design canvas (PageBlockCanvas) is a separate rendering and was left alone per the ruling, so PagePreview.tsx is untouched.",
    "tests": "All at f61f6f2. (1) vitest --maxWorkers=1 packages/plugin-list/src/tests/ListViewBlock.compactRegion-12703.test.tsx: 6 passed. It pins (a) aside 320/1200: no toolbar-filter-trigger, no tablist, no grid spy (so no # column), no record-count-bar, two rows with first column over second; (b) header title 'Upcoming' and count '2'; (c) CONTROL main 856/1200: toolbar and grid with showRowNumbers true, exactly one grid on the page; unknown width (no ResizeObserver) gives the full list; (d) CONTROL: the object-list ListView and the block without a page are full. (2) packages/components/src/tests/page-region-posture-12703.test.tsx: 8 passed. (3) Ablation via objectstack scripts/ablation-replace.mjs, with pageRegionPostureFor forced to return 'full': anchor 1->0, blob 761c974f5b56->0dc11caf582a. Pin (a) went RED, and control (c) went RED too, because both blocks were full and two grids mounted. Restored: blob == HEAD 761c974f5b56 and git diff HEAD is empty. vitest aliases @object-ui/components to src, so no dist leg is involved. (4) Reverse type check: usePageRegionPosture() === 'narrow' in ListViewBlock gives TS2367 "types 'PageRegionPosture | null' and '\"narrow\"' have no overlap". Restored, git diff HEAD empty. (5) Closure build pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-list^...' build: VERDICT command-exit 0. type-check for @object-ui/components and @object-ui/plugin-list (both script names echoed): VERDICT command-exit 0. (6) Whole packages/plugin-list/ dir: Test Files 144 passed, Tests 1493 passed (VERDICT 0, 13m25s). (7) packages/components narrowed and DECLARED: the 22 files that git grep names for regions|PageRenderer|page-block|type page kinds: 22 passed, 224 tests. The remaining ~376 component test files are declared to CI because the whole dir does not fit the ~10 min window at maxWorkers=1. (8) app-shell files naming PageView|PagePreview|data-region: 41 files, 350 tests passed. (9) eslint on the 9 changed ts/tsx files, as the package lint scripts run it (eslint ., no max-warnings): 0 errors, 207 warnings, all pre-existing classes (no-explicit-any, only-export-components). With --no-inline-config there is 1 error: the pre-existing suppressed react-hooks/static-components on the TemplateLayout line, not mine. eslint.config.js declares no parserOptions.project (no type-aware lint), so this diff cannot change any untouched file's verdict. Screenshots at 1024/1280: NOT MEASURED, reason: they are the maintainer's browser check per the dispatch.",
    "gates": {
    "check:phantom-deps": 0,
    "check:self-import": 0,
    "check:unreferenced-sources": 0,
    "check:doc-example-readers": 0,
    "check:handler-key-reads": 0,
    "check:side-effects-array": 0,
    "check:element-data-source-declaration": 0,
    "check:spec-symbols": 0,
    "check:action-forward-parity": 0,
    "check:designer-field-key-parity": 0,
    "check:icon-record-names": 0,
    "check:i18n-keys": 0,
    "check:i18n-drift": 0,
    "check:i18n-designer-parity": 0,
    "check:control-bytes": 0,
    "check:new-line-citations": 0,
    "check-hand-rolled-comment-mask": 0,
    "check-changeset-fixed": 0,
    "check-changeset-presence": 0,
    "check:spec-floors": "1 (no-artifact for unbuilt packages, expected on main; recorded, not fixed)",
    "type-check components+plugin-list": 0,
    "vitest plugin-list dir": 0,
    "vitest components (narrowed, 22 files)": 0,
    "eslint changed files": 0
    },
    "line_budget": "n/a: no skills/** or governed surface touched",
    "files_changed": [
    "packages/components/src/renderers/layout/page-region-posture.tsx (new)",
    "packages/components/src/renderers/layout/page.tsx",
    "packages/components/src/renderers/layout/page-block-grid.tsx",
    "packages/components/src/index.ts",
    "packages/components/src/tests/page-region-posture-12703.test.tsx (new)",
    "packages/plugin-list/src/ListView.tsx",
    "packages/plugin-list/src/ListViewBlock.tsx",
    "packages/plugin-list/src/ListViewCompact.tsx (new)",
    "packages/plugin-list/src/tests/ListViewBlock.compactRegion-12703.test.tsx (new)",
    ".changeset/12703-compact-list-block.md (new)"
    ],
    "deviations": [
    "File surface, read as the page renderer's list-block path: page-region-posture.tsx and page-block-grid.tsx (a gridRef prop) sit beside page.tsx. components/src/index.ts gains the export. The block is ListViewBlock.tsx, and the compact body lives in a new ListViewCompact.tsx next to ListView.tsx. All files are in the two packages the claim names. No spec, objectstack, app-shell or i18n file was touched.",
    "Clause-②: yes (measured correction of the provisional no). The PR body's second line says so.",
    "The PR body opens with 'Part of #12703' rather than the closing keyword the dispatch named, because the ruled View-all link is the open decision.",
    "No i18n keys were added. The count reuses list.recordCount, and the only new copy ('View all') belongs to the deferred link.",
    "Ran git fetch origin main in the shared HotCRM checkout /home/user/objectstack-ai/hotcrm (refs only, working tree untouched) to read the current Sales Home page."
    ],
    "mcp_calls": "0",
    "api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches via scripts/pm/fleet-write/dispatch.mjs). The first was pr_create, executed as POST /repos/objectstack-ai/objectui/pulls (draft) plus POST /repos//issues/12797/assignees; read-back showed 7774 bytes sent and stored identical, assignee baozhoutao. The second is this os-dev-report comment, POST /repos//issues/12703/comments. Label writes: 0 (objectui labeler, none named).",
    "open_questions": [
    {
    "question": "Where does the compact list's 'View all' link go, and through which seam? On the page route the renderer holds HostNavigation.navigate (it needs an already-resolved app path, but the renderer does not know the app segment) and RelatedRecordActions.recordHref/openRecord (records only). DrillNavigation.openRecordList is published but mounted only on dashboards and reports. A page list-view's 'view' is usually inline columns/filter/sort (HotCRM copies them off the saved view), so a URL can name it only when the block binds dataSource.view.",
    "options": [
    "A: Mount the existing DrillNavigationProvider (useOpenRecordList) on PageView (app-shell, about 3 lines). The compact footer calls openRecordList(object, filter map), landing on /:object/data?filter[...]. Cost: small, no new contract. But the drill map carries only equality and range conditions, so not_in and the view's sort and columns are lost. The link would either widen silently past the block's filter or must be hidden for such blocks. Business: HotCRM's upcoming_events filter (status equals planned) survives; its sort does not. AI-safety: weak, lossy filter. Scope: smallest.",
    "B: Add one host-seam member beside recordHref, e.g. RelatedRecordActionsValue.listHref(object, view?) plus an SPA open, supplied by PageView's pageRecordActionsValue, which already knows appName and the router root. It links /apps/APP/OBJECT/view/VIEW when the block binds dataSource.view, else /apps/APP/OBJECT. Cost: medium, a published @object-ui/react member plus app-shell supply plus tests, in one PR (react + app-shell outside this claim's surface). Long-term: contract-first and exact. AI-safety: strong, the link names a real view or the object's own list and never a lossy filter. Scope: one member, no new spec key.",
    "C: Drop 'View all' from the compact posture (amend the ruling). The header count and row click remain. Cost: zero. Business: loses the 'see the rest' affordance on a capped widget."
    ],
    "recommendation": "B. Long-term, it is the only option that honours 'with the block's view' exactly when a view is named, which is contract-first. It is also the safest against AI mistakes: it never encodes a lossy copy of a filter, while A widens silently. Business need is measured: HotCRM's Sales Home rail is the pull. On scope, it is one seam member and no spec key. Pair it with a HotCRM follow-up to bind dataSource.view instead of copying the saved view's keys. If the PM rules A, the patch round must hide the link for filters the drill map cannot carry."
    }
    ],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed: HotCRM main 4f82b81 still writes list-view properties.objectName/viewType, which objectui main does not read (objectui#12099; the platform-side ADR-0087 conversion is the stated path). This is an observation from reading, not a reproduced defect.",
    "carrier: none (承接者:无) · noted, not filed: AGENTS.md #2 docs (plugin-list README, content/docs/guide) for the compact posture are outside this claim's surface."
    ]
    }

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ruling on the dev's open question · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-16T21:13Z

    Answering the needs_decision in the os-dev report 6224778976 (PR #12797). The question is where the compact list's "View all" link goes. The card's Target already rules that the link exists ("a footer link 'View all →' to the object list with the block's view"); what is left open is the seam that builds it. That is a scoping and contract-shape call inside the card's own Target, so the seat answers it under the four axes. The maintainer may veto on this card.

    Ruling:

    1. PR feat(components,plugin-list): a list block in a narrow page region draws a compact list (objectui#12703) #12797 is part 1 and lands on its own (Part of #12703): the width-driven compact posture without the link. Its published additions are the usePageRegionPosture() export of @object-ui/components and an optional compact host prop on ListView. The PR line Clause-②: yes stands, and the seat runs the contract-tier review before the queue.
    2. Part 2, option B, is a follow-up on this same card after part 1 merges:
      • Add one host-seam member beside recordHref on the related-record actions value, e.g. listHref(object, view?) plus its SPA open. PageView supplies it, since it already knows the app and the router root.
      • The link goes to /apps/APP/OBJECT/view/VIEW when the block binds dataSource.view, and otherwise to the object's own list.
      • ⛔ Never encode a copy of the block's inline filter in the URL (option A's lossy drill map). A block with only inline columns, filter or sort links to the object's list, and its own header count stays the truth for "what this block shows".
      • This is a published @object-ui/react member, so part 2 also carries Clause-②: yes and a contract-tier review.
    3. Option C is refused, because the card's Target names the link.
    4. Not filed here: the HotCRM follow-up to bind dataSource.view instead of copying the saved view's keys belongs to the HotCRM repository. The seat notes it and does not file it, because no HotCRM consumer is blocked by its absence.

    Four axes:

    • Business need: HotCRM's Sales Home rail is the measured pull.
    • Long-term soundness: the link names a real view or the object's own list (contract-first).
    • AI-error resistance: there is no silent widening past the block's filter.
    • Scope: one seam member, no spec key.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed (part 1 of 2) · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-16T21:57Z

    PR #12797 merged through the merge queue as a8add5c, which is on main. Verified by content: all 13 of the PR's files on origin/main are blob-identical to the accepted head f04480a. The squash commit's message names no model.

    What landed:

    • A list-view block in a page region narrower than half the page renders a compact list: a header with title and count over two-line rows, with no toolbar, tabs, # column or pager.
    • The posture is measured, not authored. There is no spec key.
    • @object-ui/components gains usePageRegionPosture(), and ListView gains the compact host prop, released as minor. Both are documented in the package READMEs and in content/docs/guide/react-pages.md.

    Still open on this card (part 2, per seat ruling 6224804504): the "View all" link, through one host-seam member (listHref), linking to the block's named view or the object's list. The card stays pm:dispatched, and the claim is revised in place for part 2's surface.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 12703,
    "status": "done",
    "branch": "claude/issue-12703-view-all-link",
    "pr": "#12817",
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "dispatch_md5": "5bed033e3c0dab2bec091ccd5b9307d4",
    "summary": "Part 2 per seat ruling 6224804504 (option B). RelatedRecordActionsValue (@object-ui/react) gains the optional pair listHref(objectName, viewName?) => string|null and openList(objectName, viewName?), modelled on recordHref/openRecord and documented in the interface's JSDoc. The custom page supplies it in pageRecordActionsValue, the module PageView publishes on the context: /apps/APP/OBJECT/view/VIEW when the block binds dataSource.view, else /apps/APP/OBJECT. The href carries the router basename and openList navigates by the bare route. An unknown object or a page outside an app gets null. ListViewBlock builds the destination in the compact posture only, from the bound object and the view name, and hands it to the compact list through a package-internal context. The compact list draws a footer anchor 'View all' (new key list.viewAll, all ten packs) with SPA navigation on a plain left click. There is no link when the host lacks listHref or answers null, or when the list is empty. The inline filter, columns and sort are never handed to the host: the seam has no argument for them, and TS2554 proves it. A1 holds: the bound view is readable at the block, and the console route /apps/:appName/:objectName/view/:viewId exists. Docs were updated in the three files. The PR says Fixes #12703.",
    "tests": "All at 3243f6c. (1) packages/plugin-list/src/tests/ListViewBlock.compactViewAll-12703.test.tsx: 4 passed. It pins (a) bound view: href /apps/crm/crm_event/view/upcoming, link named View all, meta-click does not call openList, left click calls openList(crm_event, upcoming) once; (b) inline filter, columns and sort: href /apps/crm/crm_event with no '?', and every listHref call equals [crm_event, undefined]; (c) CONTROL: a host without listHref, and no host, draw no footer; (d) CONTROL: the wide main region draws the full list (toolbar and grid) and no link. (2) packages/app-shell/src/views/tests/PageView.listHref-12703.test.tsx: 5 passed. It runs the real PageView under MemoryRouter basename /_console with the real page renderer and the real list-view. (e) The hrefs equal react-router Link for /apps/crm/crm_event/view/upcoming and /apps/crm/crm_event, and a left click routes there. Refusals: an unknown object or no app gives null; a view name is one encoded segment. (3) Ablation of the PageView supply via objectstack scripts/ablation-replace.mjs: the anchor 'listHref: (objectName, viewName) => {' was renamed (anchor 1->0, blob 8b2ea172e459->045b761c6355). The app-shell pin went 5/5 RED. Restored: blob == HEAD 8b2ea172e459 and git diff HEAD is empty. Plugin-list (a) uses a stand-in host and cannot see the app-shell supply, so its own ablation replaced the block hand-off with value={null}: (a) and (b) went RED, (c) and (d) stayed green. Restored: blob == HEAD e9a555068faf and the diff is empty. vitest aliases @object-ui/* to src, so there is no dist leg. (4) Reverse type check: host.listHref(objectName, viewName, bound.filter) gives TS2554 'Expected 1-2 arguments, but got 3'. Restored, and the diff is empty. (5) Closure build turbo --filter='@object-ui/app-shell^...' --concurrency=2: 28/28, VERDICT command-exit 0. type-check of react, i18n, plugin-list and app-shell (all four script names echoed): VERDICT 0. (6) vitest --maxWorkers=1: the whole packages/plugin-list dir in 3 slices gave 146 files and 1504 tests passed; the whole packages/react dir gave 112 files and 1422 tests passed; the whole packages/i18n dir gave 83 files, 1321 passed and 13 skipped. app-shell was NARROWED and DECLARED: the 34 files git grep names for PageView|pageRecordActions|RelatedRecordActions|listHref gave 269 tests passed; the remaining app-shell test files (of 1503) are declared to CI. (7) eslint --no-inline-config --format json on the 16 changed ts/tsx files gave 0 errors and 3 warnings, all react-refresh/only-export-components. One is new: the context export in ListViewCompact.tsx, a file that already exports a non-component. eslint.config.js declares no parserOptions.project, so linting is not type-aware and the diff cannot change any untouched file's verdict.",
    "gates": {
    "check:phantom-deps": 0,
    "check:self-import": 0,
    "check:unreferenced-sources": 0,
    "check:doc-example-readers": 0,
    "check:handler-key-reads": 0,
    "check:side-effects-array": 0,
    "check:element-data-source-declaration": 0,
    "check:spec-symbols": 0,
    "check:action-forward-parity": 0,
    "check:designer-field-key-parity": 0,
    "check:icon-record-names": 0,
    "check:i18n-keys": 0,
    "check:i18n-drift": 0,
    "check:i18n-designer-parity": 0,
    "check:control-bytes": 0,
    "check:new-line-citations": 0,
    "check-hand-rolled-comment-mask": 0,
    "check-changeset-fixed": 0,
    "check-changeset-presence": 0,
    "check-changeset-no-major": 0,
    "check:spec-floors": "1 (no-artifact on an unbuilt workspace, expected; recorded, not fixed)",
    "closure build app-shell^...": 0,
    "type-check react+i18n+plugin-list+app-shell": 0,
    "vitest plugin-list dir (3 slices)": 0,
    "vitest react dir": 0,
    "vitest i18n dir": 0,
    "vitest app-shell (narrowed, 34 files)": 0,
    "eslint changed files": 0
    },
    "line_budget": "n/a: no skills/** or governed surface touched",
    "files_changed": [
    "packages/react/src/context/RelatedRecordActionsContext.tsx",
    "packages/app-shell/src/views/pageRecordActions.ts",
    "packages/app-shell/src/views/tests/PageView.listHref-12703.test.tsx (new)",
    "packages/plugin-list/src/ListViewBlock.tsx",
    "packages/plugin-list/src/ListViewCompact.tsx",
    "packages/plugin-list/src/tests/ListViewBlock.compactViewAll-12703.test.tsx (new)",
    "packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts",
    "packages/react/README.md",
    "packages/plugin-list/README.md",
    "content/docs/guide/react-pages.md",
    ".changeset/12703-view-all-link.md (new; react, app-shell, plugin-list, i18n: minor)"
    ],
    "deviations": [
    "File surface: the supply lives in packages/app-shell/src/views/pageRecordActions.ts, the module PageView.tsx imports its published value from (it was extracted so PageView.tsx exports components only). PageView.tsx itself needed no edit. This file is not in the claim's literal list. I judged it the claim's 'PageView supplies it' and did not stop; it is named in the PR's Acceptance notes.",
    "'One member plus its SPA open' landed as the pair listHref / openList, mirroring recordHref / openRecord. listHref returns string|null (the recordHref convention) rather than the ruling's example 'string | undefined'.",
    "ListView.tsx is not touched: the block hands the destination to ListViewCompactRows through a package-internal React context (CompactListDestinationContext, not exported from the package index). So ListView's published props do not widen.",
    "The changeset bumps @object-ui/app-shell and @object-ui/i18n as minor beside react and plugin-list, because each gains published behaviour (the supply, the key).",
    "Commit trailers: only the dispatch's model-free pair (Co-authored-by: Claude, Claude-Session). The harness reminder's model-named trailer was ignored per the dispatch.",
    "Worktree removed after the PR opened (node_modules first, no --force)."
    ],
    "mcp_calls": "0",
    "api_writes": "4 git pushes of branch claude/issue-12703-view-all-link (empty probe and 3 commits). 2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches via objectstack scripts/pm/fleet-write/dispatch.mjs). The first was pr_create, executed as POST /repos/objectstack-ai/objectui/pulls (draft) plus POST /repos//issues/12817/assignees. Read-back: 7859 bytes sent and stored identical, assignee baozhoutao, draft true. The second is this os-dev-report comment, POST /repos//issues/12703/comments. Label writes: 0 (objectui labeler, none named).",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed: a page list-view block whose view is inline only (HotCRM copies a saved view's keys) links to the object's whole list, by ruling. The HotCRM follow-up to bind dataSource.view is the seat's noted item in 6224804504 and is not refiled here."
    ]
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT (part 2 of objectui#12703, "View all") — objectui PR #12817 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-16T23:03Z

    Reviewed on GitHub at head 718098bee, against the card's Target, the claim (6224046413, revised in place for part 2) and the seat ruling on the "View all" link (6224804504: a listHref seam, the inline filter never encoded in the URL).

    • Shape: the body says Fixes #12703; the second line is Clause-②: yes. The changeset is minor for react, app-shell, plugin-list and i18n.
    • The change:
      • RelatedRecordActionsValue (@object-ui/react) gains two optional members, listHref(objectName, viewName?) => string | null and openList(objectName, viewName?), mirroring recordHref / openRecord.
      • The console supplies them in packages/app-shell/src/views/pageRecordActions.ts: /apps/:appName/:objectName, or …/view/<encoded view name>; the basename goes through the same documentHref join as recordHref.
      • ListViewBlock hands the destination to the compact rows through a package-internal CompactListDestinationContext (not re-exported from src/index.tsx); the compact list draws a "View all" anchor (list.viewAll, all ten packs). A plain primary click navigates in the SPA; modifier and non-primary clicks keep the real href.
      • No host, a host without listHref, a null answer, or an empty list draws no link. The wide list and the object list page are unchanged.
    • Contract review (contract tier): PASS, no blocking finding. Verified with probes:
      • Ruling conformance: passing the block's filter as a third argument to host.listHref fails tsc with TS2554; the only path builder has no query string; the view name is one encoded segment.
      • The route :objectName/view/:viewId resolves a bare view name through resolveViewId, so /view/upcoming reaches crm_event.upcoming; a miss falls back to the default view.
      • Under MemoryRouter basename="/_console" both hrefs equal react-router's own <Link> hrefs, and a left click moves the location.
      • Every existing implementer of the value type still type-checks (both members are optional); tsc --noEmit exits 0 in react, plugin-list and app-shell.
    • CI fix round: the first head 3243f6c5d was red on Repo Gates (check-doc-snippet-types): the new packages/react/README.md example did not compile. 718098bee makes it a self-contained, typed block and encodes the view name like the console's own builder (a review nit). check-doc-snippet-types judges 798 of 798 blocks with 0 failures; check-doc-example-types exits 0.
    • Docs (AGENTS.md Add automated testing infrastructure and CI/CD workflows #2): packages/react/README.md (the provider and the two members), packages/plugin-list/README.md (the "View all" subsection replaces the "not part of this release" sentence), content/docs/guide/react-pages.md (the two route shapes).
    • Pins: ListViewBlock.compactViewAll-12703 (4) and PageView.listHref-12703 (5), green here at the code head.
    • Acceptance notes, not filed:
      • RecordPickerDialog and ObjectGrid's unlinked host strip recordHref / openRecord but pass listHref / openList through. Nothing under them draws a compact page block today.
      • A metadata-authored view literally named .. would collapse to the object list. Harmless.
    • Owed by the maintainer: a screenshot of the Sales Home rail with the link.
    • Trailers: every commit carries only the model-free pair.
    • CI at head: 33 success, 3 skipped, 0 failures (36 runs). Not governed (path audit), 828 changed lines.

    Next: pr_ready + automerge_enable; this lands the card.


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed (part 2 of 2, card complete) · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-16T23:18Z

    PR #12817 merged through the merge queue as 33ee9de, which is on main; Fixes #12703 closed this card. Verified by content against the accepted head 718098bee:

    What landed:

    • RelatedRecordActionsValue (@object-ui/react) gains optional listHref / openList, mirroring recordHref / openRecord. The console supplies them (/apps/APP/OBJECT, or …/view/<encoded view name>).
    • The compact list block now ends in a "View all" link to the block's bound view or the object's list. Per seat ruling 6224804504, the inline filter, columns and sort are never put in the URL.
    • No host, a null answer or an empty list draws no link.
    • Released as minor for react, app-shell, plugin-list and i18n, and documented in both package READMEs and content/docs/guide/react-pages.md.

    Both parts of the card are on main (part 1 a8add5c, part 2 33ee9de). Still owed by the maintainer: the Sales Home screenshots at 1024 and 1280 px, with the link. This seat now removes pm:dispatched.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions