Repository navigation
refactor(app-shell): the Studio design surface picks with the shared Select (objectui#11865, slice o) - #12024
Merged
objectstack-fleet[bot] merged 3 commits intoOct 9, 2026
Conversation
…ct (objectui#11865, slice o) StudioDesignSurface drew five pickers as browser-native selects: the nav-item inspector's Link object, its target picker (NavTargetSelect) and a url entry's Open in, plus New object's record sharing and New automation's trigger. Each now uses the shared Radix Select through one module-private StudioPicker: items carry option indexes, so the '' options need no empty SelectItem, and a value no option carries is shown as its own item. Every pick hands onPick the same value the native change did. The new pin reads every option's write against literals a scratch probe read on the base surface. Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU Co-authored-by: Claude <noreply@anthropic.com>
…Select (objectui#11865, slice o) Fourteen studio-design suites drove the surface's native selects with change events or read their value and options. Each now opens the primitive's list and picks an option by its label, or reads the trigger's text and the listed labels; no assertion changes meaning. The object picker carries a test id (nav-link-object), since it has no accessible name. Adds the patch changeset for @object-ui/app-shell. Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU Co-authored-by: Claude <noreply@anthropic.com>
…t the native controls The reverse leg left two pins green on the native controls (the trigger picker's name, and the record sharing default saved untouched); the header now says so, and cites the suites that pin the read-only closes. Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU Co-authored-by: Claude <noreply@anthropic.com>
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
|
objectstack-fleet
Bot
deleted the
claude/issue-11865-studio-surface-select
branch
October 9, 2026 04:34
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 #11865
Clause-②: no
Slice o of claim
6073419396on objectui#11865: the Studio design surface (StudioDesignSurface.tsx). The card stays open for slice p (ListView,ChatbotEnhanced), which a sibling PR carries.What changed
StudioDesignSurfacedrew five pickers as browser-native select elements. Counted before the first edit: the census's five lines are all real elements, each with its closing tag, and none is a comment line. Each now uses the shared RadixSelect(@object-ui/components) through one module-privateStudioPicker:StudioNavItemInspector);NavTargetSelect, for a page, dashboard, report, action, component or doc entry (Doc page and Book included);NavUrlFields);StudioPickerfollows the card's landed slices (RulePicker,CreatePicker):''options ("Choose object", "Choose", "Choose later on the Start node") need no emptySelectItem, which Radix refuses.onPickreceives the picked option's own value, the string the nativechangecarried.No native select element is left in the file, and the tag spelling is in no comment either.
Not touched: every write path (
bindObject,setTarget,setAction,setCreateOwd,setNewTriggerand the saves behind them),packages/components/src/ui/**,packages/i18n/**, the designer tables,ListView.tsx,ChatbotEnhanced.tsxand the eager-closure budget script.Files:
StudioDesignSurface.tsx, the new pinStudioDesignSurface.sharedSelect-11865.test.tsx, fourteen existing studio-design suites that drove these controls, and.changeset/11865-o-studio-surface-shared-select.md(@object-ui/app-shell: patch).The dispatch's hypotheses, measured
A scratch probe (uncommitted, deleted) mounted the base surface (
2063f7a96) and firedchangeon every option of every native control, with the fixtures the pin uses. It recorded the write, the accessible name (dom-accessibility-api) and the shown option.onNavPatch's value as JSON text, plus the keys the written entry holds asundefined. JSON erases those keys, and the unbind writestype,objectNameandobjectasundefined.private.config.changefired for the current option too, which a browser's native select does not do, so those rows pin the primitive.label htmlFornames; theidmoved onto the trigger.htmlFor) and still has none. Its trigger carriesdata-testid="nav-link-object"so suites can find it.StudioDesignSurface.navEditClosesOnReadOnly-11167("closes nav editing and the linked item’s inspector") andStudioDesignSurface.emptyPackage("hides the CTA on a read-only package"). The Automations rail's New is gated on the samereadOnlyin the source, and no suite pins it.ghost_objnow showsghost_obj, listed first. The native control showed "— Choose object —"._topnow shows_top. The native control showed "Same tab".NavTargetSelectalready listed an outside target as its own option on base, and it still does.apps/consoleCI=true vite buildunder the verify lock. Base2063f7a96:eagerGzipBytes3237430, raw 10893710, 289 of 2474 chunks eager. Head2d046a08a: 3237428, raw 10893710, 289 of 2474.indexchunk: 0 raw, −2 gzip, from renamed lazy hashes.StudioDesignSurfaceships in the lazystudioBuilderchunk on both legs.ui-componentsandvendor-radixwere already eager.check-eager-closure-budget.mjson the head build: "Console eager closure is 3161.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 43.0 KB)."Tests
New pin,
StudioDesignSurface.sharedSelect-11865.test.tsx, 79 tests:Fourteen existing suites drove the native controls with
fireEvent.change, or read.value,.optionsortoHaveValue. Each now opens the primitive's list and picks by label, or reads the trigger's text and the listed labels:navItemInspector,navItemInspectorLabel-11196,navItemInspectorLabelMaps-11148,standardNavEntries-11201andnavItemTypes-11790;navPlaceholderSave-11776,navAutosaveFlush-11189,navEditClosesOnReadOnly-11167,autosaveInFlight-11204,autosaveSwitch-11232andInterfacesPillar.heldWidget-11910;createObjectOwd,newFlowTrigger-11788andflowPresets-11861.No expected value changes meaning. One read would have gone vacuous on the trigger:
flowPresets-11861read the trigger picker's.valueas'', which a button's.valuealso is. It now reads the trigger's text.Reverse leg, from committed
a7e59648e, with a trap restore:StudioDesignSurface.tsxwas written from its base blob9d6ced42(hash proved, 5 native selects, 0StudioPicker).git checkout HEAD --, disk blob656f270dequal to the HEAD blob,git diff HEAD0 bytes.Gates (head
2d046a08a)pnpm exec vitest run --maxWorkers=2from the repo root, under the lock, over 190 files: every suite that imports or namesStudioDesignSurfaceor a pillar (188), pluspackages/core/src/utils/__tests__/column-identity.ratchet.test.tsandscripts/__tests__/one-authority-per-exported-name-6273.test.ts. Result: 'Test Files 190 passed (190)', 'Tests 1601 passed (1601)', VERDICT command-exit 0.pnpm --filter @object-ui/app-shell type-check('tsc --noEmit && tsc -p tsconfig.test.json') exits 0. It ran after the closure buildpnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' run build(Scope: 29 of 47).tsc -p tsconfig.test.json --listFilesOnlylists all 16 touched ts/tsx files.pnpm exec eslint --format jsonon the 16 touched files: 0 errors and 13 warnings, all inStudioDesignSurface.tsx. The per-rule counts equal its base blob's (stdin): set-state-in-effect 5, exhaustive-deps 6, preserve-manual-memoization 2. The test files read 0 / 0.node scripts/check-changeset-presence.mjs('16 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)');node scripts/check-changeset-no-major.mjs;pnpm check:new-line-citations('0 new citation(s)');pnpm check:control-bytes;check-changeset-fixed,check-changeset-overwrite,check:changeset-claims,check:pending-changeset-literals,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:i18n-keys,check:metadata-write-doors,check:unreferenced-sources,check:phantom-deps,check:handler-key-readsandcheck:component-surface-parity(report-only).pnpm testfarm and repo-widepnpm lint.Acceptance notes
htmlFor. Naming it is outside this control swap, and no public-door reading was taken.Generated by Claude Code