Skip to content

feat(app-shell): Data pillar — object header buttons, seven flat tabs with a 1000 px fold, flush Records body (objectui#12450) - #12477

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-12450-data-pillar-layout
Oct 15, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-12450-data-pillar-layout

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12450
Clause-②: no

The Data pillar's content column, after the layout skeleton (objectui#12459): the object header gets its two icon buttons, the five power panels become flat tabs that fold back into "Advanced ▾" below a 1000 px content column, and the Records tab loses the framed card and body padding around the list. Part of epic objectui#12446 (decisions 1, 3 and B).

What changed

Object header (DataPillar in StudioDesignSurface.tsx)

  • Adds an Object settings icon button. It opens the Settings panel, so it still works when Settings is folded into Advanced.
  • Adds a More actions icon button with a menu. Both buttons are 32 px and carry an aria-label.
  • Add field moves from the header row into the More menu. The artboard has no header Add field. The grid's "+" column header and the form designer's own button still add fields.
  • More is drawn only when its one entry is offered: a writable package, the object loaded, and the Records or Form tab.

Tab row

  • Ruling B (maintainer, 2026-10-15): seven flat tabs — Records, Form, Validations, Hooks, Actions, API, Settings — when the content column is at least 1000 px wide. Narrower, the last five fold into "Advanced ▾", which keeps its objectui#11794 name rule.
  • A CSS container query decides the fold. The content column is @container. The five flat tabs carry hidden @min-[1000px]:inline-flex and the trigger carries @min-[1000px]:hidden.
  • So the fold also follows the field inspector: at 1280 px with the inspector open, the column is 740 px and the tabs fold. There is no JS width read.
  • The rule and its class strings live in the new dataTabsFold.ts.
  • Premise B re-checked on cf430cd before building: advancedDataTabs held exactly rules (Validations), hooks, actions, api and settings.

Records body

  • The grid view's main drops px-6 py-4 and the list's rounded-lg border card. The toolbar, grid and footer run flush with the column.
  • Error and held-edit strips keep a 24 px inset in that view. Every other view keeps the padded body; the Form tab body is untouched (objectui#12451).

Records toolbar (renderStudioGridList)

  • The Studio list uses the wide form, compactToolbar: false: Hide fields, Filter, Group and Sort as labelled buttons, then Refresh, Search and Add record.
  • The console list pages keep the bundled Display form (objectui#12423).
  • Density is turned off, because the artboard has no density control.
  • The toggles move from the retired bare show* spellings to userActions. The slot's own userActions still wins.

List search button (packages/plugin-list, the toolbar's producer)

  • The icon-only Search trigger gets an aria-label, in the same two-attribute shape as Refresh. Card acceptance 3 asks for one on every icon-only toolbar button.
  • With a keyword active, the button's accessible name is now "Search: KEYWORD" instead of the bare keyword.
  • This file is outside the claim's file surface. The dispatch allows a fix at the producer when the producer is in another package. It is one attribute.

Deviations from the artboard (data-records.png)

  1. Toolbar arrangement. The controls sit in the list's right-aligned rounded cluster. The artboard has left-aligned 28 px outline chips after an "N records" count, then Search and Refresh, a divider, and Add record as a primary-soft chip.
    • In the cluster Refresh comes before Search, and Add record is a ghost button.
    • Reason: the toolbar is ListView's (packages/plugin-list), not plugin-grid's as the card assumed. Its controls hold ListView-internal state: filters, sort, grouping, hidden fields, search keyword and refresh key. A host toolbar cannot drive that state, so suppression alone would remove the controls.
    • Restyling ListView's toolbar is outside the claimed surface. It is raised as an open question in the dev report.
  2. Grid metrics. The header row is 48 px on the background surface; the artboard has 36 px on the sidebar surface. Body rows measure 41 px; the artboard has 40 px.
    • The # column is a 40 px cell with the number centred, about 16 px into the column. The artboard has a 48 px column with a 24 px inset, so card acceptance 1 (title edge = row-number edge at 24 px) is not met.
    • A vertical divider follows only the frozen first column.
    • Lookup cells render as primary links, not 20 px initials avatars, and the autonumber column is not mono.
    • Reason: these are ObjectGrid / data-table internals (packages/plugin-grid, packages/components). The card's surface admits plugin-grid only for a toolbar option. Same open question.
  3. Footer. "N records" only, at 8 px by 16 px padding, with no range on the right. The artboard has "N records" plus "1–10 of 10" at 10 px by 24 px. Reason: this is ListView's record-count bar. Same open question.
  4. More button. It is not drawn on a read-only package, before the object loads, or on the five power panels. Add field is its only entry and is not offered there.
  5. Sample data. The screenshots use a writable "Acme CRM" base seeded on a local backend.
    • Under objectstack dev, HotCRM's package is read-only and the server refuses to duplicate it (DUPLICATE_SOURCE_NOT_A_BASE). A read-only package draws no More button.
    • So the object, columns and rows differ from the artboard's HotCRM sample.
    • The shell header (app chip, pillar control with More, Create app) is the skeleton's, and objectui#12452's and objectui#12453's to change.

Screenshots (1280 px, local console on its own backend)

  • After, light: docs/design/studio-redesign/after/12450-data-records-light.png
  • After, dark: docs/design/studio-redesign/after/12450-data-records-dark.png
  • The fold, light, 1180 px viewport (940 px column): docs/design/studio-redesign/after/12450-data-records-folded-light.png
  • Before: docs/design/studio-redesign/after/skeleton-data-records-light.png and -dark.png, from cf430cd, as filed by the skeleton change. These were not re-shot.

Measured in that browser run (Chromium, 1280 × 900):

  • With a 1040 px content column, the seven tabs are displayed and the Advanced trigger is not.
  • With a 940 px column, Records and Form plus Advanced are displayed.
  • With the field inspector open at 1280 px (a 740 px column), the tabs fold.
  • Every displayed toolbar button has a visible label or an aria-label (Refresh, Search).

Tests (all at 4c06d3a, from the worktree root, through the shared verify lock)

  • pnpm exec vitest run packages/app-shell/src/views/studio-design/ in two runs:
    • the 98 files that are not StudioDesignSurface.*: Test Files 98 passed (98), Tests 773 passed (773);
    • the 76 StudioDesignSurface.* files: Test Files 76 passed (76), Tests 511 passed (511).
  • pnpm exec vitest run packages/plugin-list/: Test Files 133 passed (133), Tests 1432 passed (1432). Run after the plugin-list change; that file has not changed since.
  • Tests that read the search trigger, in app-shell and plugin-list (6 files): 214 passed.
  • New: DataPillar.flatTabs-12450.test.tsx (9 tests).
    • It pins the flat state: the order of the seven tabs, the content column as the query container, the five flat tabs' fold classes, the trigger's class, and that both class strings name DATA_TABS_FOLD_WIDTH.
    • It also pins that a flat tab opens its panel while the folded trigger mirrors it, the header buttons' aria-labels, More holding Add field, and the read-only control.
  • Ablated once: the flat tabs' className={DATA_TAB_FLAT_ONLY} was replaced with className={undefined} through ablation-replace.mjs.
    • The anchor went from 1 to 0 and the blob changed.
    • Result: Tests 1 failed | 8 passed (9), and the failure is the fold-class pin.
    • It was restored to the HEAD blob, with git diff HEAD empty.
  • Kept for the folded state, unchanged: DataPillar.advancedKeepsName-11794.test.tsx, green.
  • Existing suites whose harness changed, assertions untouched:
    • Each step that added a field through the header now opens More first (shared helper __tests__/dataPillarAddField.ts). Each step that clicked a power panel by name now clicks its flat tab.
    • Three suites mock the menu as passthrough buttons, which would now draw a second button of the same name.
    • Two suites asked "is Add field offered" through the header button's title. They now read the More trigger, which is drawn exactly when Add field is offered. DataPillar.flatTabs-12450 pins that both ways.
    • The files: DataPillar.authorRefusal-11785, choiceWithoutOptions-11253, designerRegistryPopulated, gridProjection, heldIncomplete-11786, inspectorBelongsToView-11781, panelGate, picklistServedOptions-10202, and StudioDesignSurface.autosaveInFlight-11204, autosaveSwitch-11232, cancelledLoad-11331, draftVersionConflict-11773, formFields, gridColumns.
    • Three of these are on the card's stay-green list: gridProjection, gridColumns and inspectorBelongsToView-11781. All are green. hiddenSystemFields-11780, surfaceRequest and listViewInspector-11823 are unchanged and green.
  • pnpm --filter @object-ui/app-shell --filter @object-ui/plugin-list type-check: both echo type-check and exit 0. Dependency closure built first. tsconfig.test.json --listFiles lists the new test and helper.
  • eslint on every touched file in both packages: 0 errors. The warnings are existing patterns on untouched lines.
  • pnpm --filter @object-ui/plugin-list --filter @object-ui/app-shell build: exit 0. The aria-label is in plugin-list/dist/index.js, and the fold classes are in app-shell/dist/.../dataTabsFold.js.
  • Gates, exit 0 each: check-changeset-presence, check-changeset-no-major, check:i18n-keys, check:i18n-drift, check:i18n-designer-parity, check:control-bytes, check:new-line-citations (0 new) and check:test-path-roots. check-governed-queue-guard --test reports NOT GOVERNED.

Acceptance notes

  • Stretched last row (seen, not filed). In Studio on HotCRM's crm_account at 1280 × 900, the grid drew 6 of the 9 rows the footer counts, and the 6th row stretched to the bottom. The before-screenshot from cf430cd shows the same shape. The 8-row Acme object does not do it. Not root-caused and not filed. Carrier: none.
  • Narrow-screen labels (inference from source, not measured). Below the sm breakpoint, the list toolbar's Filter and Sort buttons hide their labels and carry no aria-label, in both toolbar forms. Carrier: none.
  • Merge state. origin/main moved three commits after cf430cd; none of them touches this diff's files.

i18n: engine.studio.data.objectSettings and engine.studio.data.moreActions are added in en and zh. Changeset: .changeset/12450-data-pillar-layout.md (app-shell minor, plugin-list patch).

The dev run's session is session_01SJn1GEkrbbBQkhGC26wEDw (seat domain:ui#4).


Generated by Claude Code

…000 px fold, flush Records body (objectui#12450)

Claude-Session: https://claude.ai/code/session_01SJn1GEkrbbBQkhGC26wEDw
Co-authored-by: Claude <noreply@anthropic.com>
…r panels by their flat tab (objectui#12450)

Claude-Session: https://claude.ai/code/session_01SJn1GEkrbbBQkhGC26wEDw
Co-authored-by: Claude <noreply@anthropic.com>
…(objectui#12450)

Claude-Session: https://claude.ai/code/session_01SJn1GEkrbbBQkhGC26wEDw
Co-authored-by: Claude <noreply@anthropic.com>
…(objectui#12450)

Claude-Session: https://claude.ai/code/session_01SJn1GEkrbbBQkhGC26wEDw
Co-authored-by: Claude <noreply@anthropic.com>
…, and the folded tab row (objectui#12450)

Claude-Session: https://claude.ai/code/session_01SJn1GEkrbbBQkhGC26wEDw
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 70 chunks) 3079.9 KB 3119.4 KB
Main entry chunk (gzip) 73.2 KB 350 KB
Entry file index-CHH4QvDa.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 20.90KB 7.67KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 592.70KB 142.91KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 251.43KB 70.46KB
fields (index.js) 282.89KB 72.11KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.67KB 11.85KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.94KB 16.05KB
plugin-charts (index.js) 84.97KB 23.36KB
plugin-chatbot (index.js) 201.72KB 48.07KB
plugin-dashboard (index.js) 143.88KB 38.88KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 262.16KB 69.28KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 179.38KB 46.59KB
plugin-gantt (index.js) 178.36KB 45.08KB
plugin-grid (index.js) 261.92KB 72.66KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 127.50KB 32.55KB
plugin-map (index.js) 27.07KB 8.96KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 93.05KB 23.86KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT · objectui#12450 · head 4c06d3a · 2026-10-15T11:21Z

Seat domain:ui#4, session session_01SJn1GEkrbbBQkhGC26wEDw. Checked against GitHub and the diff, not against the report.

Checklist

  • Form: draft → main; first line Fixes #12450; Clause-②: no at a line start.
  • Premise B: on cf430cd the Advanced menu held exactly rules, hooks, actions, api and settings. The seat read that before dispatch and the dev read it again.
  • Diff, read in full (24 files, +469 / −70):
    • StudioDesignSurface.tsx: the five power panels are rendered as flat StudioTabs beside the "Advanced" dropdown. dataTabsFold.ts puts @container on the content column, hidden @min-[1000px]:inline-flex on the flat tabs and @min-[1000px]:hidden on the trigger, so exactly one form shows at any width.
    • The header gains Object settings (selectViewMode('settings')) and a More menu holding Add field. More is drawn only when Add field is offered.
    • The Records body drops the framed card and the padding.
    • renderStudioGridList replaces the bare show* flags with userActions plus compactToolbar: false and rowHeight: false. On main, ListView derives showSearch from ua?.search and never reads schema.showSearch, so the bare flags were dead spellings. A view's own userActions still wins.
    • packages/plugin-list/src/ListView.tsx: one aria-label on the icon-only Search trigger.
  • Changeset prose, checked sentence by sentence:
    • flat at 1000 px and folded below, with the trigger keeping its name: matches dataTabsFold.ts and the dropdown.
    • "an Object settings button, which opens the Settings panel, and a More button. Add field moves … into the More menu": matches.
    • "still in the grid's '+' column header and in the form designer": the grid authoring context and its header "+" are unchanged.
    • "drops the framed card and the body padding": matches.
    • "the list's wide form … There is no density control": matches compactToolbar: false and rowHeight: false.
    • "accessible name is 'Search: KEYWORD'": matches the aria-label.
    • Bumps: minor for @object-ui/app-shell, patch for @object-ui/plugin-list.
  • Contract faces: none. No Clause-②: yes, no packages/spec, no governed path, and no exported signature changes. No contract-review record is owed.
  • Tests: the new pin DataPillar.flatTabs-12450 has 9 cases; the ablation (the fold class removed) turns one red. The seat scanned the 14 harness-edited suites: every expect( line is unchanged except cancelledLoad-11331's four presence reads, which move from findByTitle(ADD_FIELD) to findByTestId(ADD_FIELD). They ask the same question, whether Add field is offered, through the More trigger that is drawn only when it is. advancedKeepsName-11794 is unmodified.
  • Screenshots against data-records.png: the header buttons, the seven flat tabs and the flush body match. The folded pair at 1180 px shows "Advanced ▾". The toolbar arrangement, the grid metrics and the footer range do not match; see the open question below.
  • CI at this record: on 4c06d3a, 18 success, 3 skipped, 15 in progress. Landing waits for every check, except the base-wide Spec Main Shape Gate red that PR objectui#12470's landing note documents.

Accepted deviations

  1. packages/plugin-list/src/ListView.tsx is outside the claim, which named packages/plugin-grid. The toolbar's producer is plugin-list, and the order's producer clause covers it. The claim's file surface reads as amended by this record.
  2. Harness-only edits to 14 suites, including three on the stay-green list (gridProjection, gridColumns, inspectorBelongsToView-11781). No assertion changed, as read above.
  3. The screenshots use a writable local "Acme CRM" base, because HotCRM is read-only under objectstack dev and draws no More button.
  4. Card acceptance 1 is not met (the title edge equal to the row-number edge at 24 px), and neither are the artboard's toolbar arrangement, grid metrics and footer range. These live inside ListView and ObjectGrid, outside the card's surface. Whether to build them, and where, is decision D, which the seat records on the epic [epic] Studio design surface layout redesign: one skeleton for the shell and the four pillars (Data, Automations, Interfaces, Access), from the 2026-10-15 design canvas #12446 for the maintainer. Every option there carries that remainder on a card other than Data pillar: the object header moves into the content column, Records / Form / Validations / Hooks / Actions / API / Settings become one underline tab row, and the Records toolbar and grid lose their nested containers #12450, so Fixes #12450 stays.

Out-of-scope findings

Artboard acceptance: the epic PM session keeps it (6189330242). The seat's own comparison is above.

Implemented-by: os-dev subagent of session_01SJn1GEkrbbBQkhGC26wEDw, branch claude/issue-12450-data-pillar-layout
Reviewed-by: seat domain:ui#4, session_01SJn1GEkrbbBQkhGC26wEDw


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Landing · head 4c06d3a · 2026-10-15T12:25Z


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation package: app-shell plugin tests

Projects

None yet

2 participants