Repository navigation
Commit 0bbb67b
refactor(app-shell): Explain access picks its object and operation with the shared Select (objectui#11865) (#11990)
Part of #11865
Clause-②: no
The *Explain access* slice of objectui#11865 (claim 6063378622): the
panel's two browser-native select elements, *Object* and *Operation*,
become the shared Radix `Select`. The card stays open for the other
native selects its body counts. The earlier slices are objectui#11934
(the Group panel) and objectui#11976 (the validation editor).
## What changed
- `packages/app-shell/src/views/metadata-admin/AccessExplainPanel.tsx`:
one module-private `ExplainPicker`, drawn with the shared `Select` from
`@object-ui/components`, renders both pickers. It follows the validation
editor's `RulePicker`: items carry their option's index, so "Select an
object…" (value `''`, which `SelectItem` refuses) needs no stand-in
value, and a value none of the options carries gets an item of its own.
The trigger carries the control's `id`, so each label's `htmlFor` still
names it.
- Untouched: the free-text `Input` fallback when the package lists no
objects, the user picker, the record selector, the explain request, the
props and the exports. No i18n key is added; the panel's set of
`engine.*` keys is identical to the base's (diffed).
- `AccessExplainPanel.sharedSelect-11865.test.tsx` (new), and
`AccessExplainPanel.test.tsx`, whose package-scoped dropdown test now
opens and picks through the trigger. It still checks the same three
things: the options listed, the free-text placeholder gone, and the
object the request sends.
- `.changeset/11865-explain-access-shared-select.md`:
`@object-ui/app-shell: patch`.
## Why Select and not Combobox for the object list
Triage allows `Combobox` where a list is long, and a package's object
list is open-ended, so it was built first and measured. Both readings
come from Chromium, on a scratch page that mounted this panel with a
package of 25 objects. The scratch page was deleted and never committed.
- **Shared `Combobox`** (built, then kept out of the branch): a 400 px
mouse wheel over its open list left `scrollTop` at 0, with the list's
`scrollHeight` 840 and `clientHeight` 300. The panel lives in a `Sheet`,
and there the list did not scroll under the wheel.
- **Shared `Select`**: the same wheel moved its viewport from 0 to 208,
the maximum for `scrollHeight` 840 and `clientHeight` 632. Typing
`showcase_t` in the open list jumped to `showcase_task`.
The `Combobox` also reports a re-pick of its current option as `''`. So
the object list is a `Select`, like the operation list.
## Dispatch hypotheses
- **H1, value parity: held.** The base panel was read first with a
scratch probe (not committed): a `change` on each native option, then
Explain. The new suite pins every option of both pickers against the
request body read there:
- each object sends its name;
- each of the seven operations sends its name;
- "Select an object…" leaves Explain disabled, as on the base;
- re-picking the current option sends the same request.
One caveat: the probe's `change` event fires even for the current
option, so the re-pick rows pin the primitive's behaviour, not a browser
reading of the native one.
- **H2, labels and keyboard: held.**
- `getByRole('combobox', { name: 'Object' })` and `{ name: 'Operation'
}` find the two triggers (the base probe found the native controls by
the same names).
- Enter opens each picker and Enter on an option selects it. This is
pinned in the test DOM and was also seen in Chromium.
- The panel has no disabled or read-only state. It takes no such prop,
its one mount (`StudioDesignSurface`) passes `open`, `onOpenChange` and
`packageId`, and it writes no metadata. So objectui#11781 has nothing to
reach here.
- **H3, a value outside the options: held.**
- On the base, a held object the package does not list (`crm_lead`)
showed "Select an object…" (`selectedIndex` 0), while Explain sent
`crm_lead`.
- Now the trigger shows `crm_lead`, and it is listed first. Picking it
changes nothing, and Explain still sends `crm_lead`.
- The pin reaches that state through `defaultObject`.
- **H4, first-load bytes: measured, −1 gzip byte.**
- Method: `apps/console` `vite build`, then `node
scripts/check-eager-closure-budget.mjs`, on this head and on the same
tree with the panel at its base blob `5aade6a7`, the only bundle input
the branch changes.
- Eager gzip bytes: 3390584 on head and 3390585 on base. Eager raw bytes
are equal (11491936), with the same 337 of 2459 eager chunks.
- The only eager chunk that moves is the entry `index` chunk: 0 raw
bytes, −1 gzip byte.
- The panel ships in the lazy `studioBuilder` chunk on both legs.
- The gate prints the same line on both legs: "Console eager closure is
3311.1 KB gzipped across 337 of 2459 chunks (budget: 3312.0 KB,
headroom: 0.9 KB)".
- These are local builds. The budget bot's reading on this PR is the one
that counts.
## Tests and gates, on head `0c5300d7c`
- Repo-root `pnpm exec vitest run --maxWorkers=2` over the new suite,
`AccessExplainPanel.test.tsx` and
`AccessExplainPanel.principalPerson-11862.test.tsx`, the only suites
that mount the real panel (the `StudioDesignSurface` suites stub it):
"Test Files 3 passed (3)", "Tests 28 passed (28)".
- The two repo-wide pins,
`packages/core/src/utils/__tests__/column-identity.ratchet.test.ts` and
`scripts/__tests__/one-authority-per-exported-name-6273.test.ts`: "Test
Files 2 passed (2)", "Tests 18 passed (18)".
- `pnpm --filter @object-ui/app-shell type-check` (echoes `tsc --noEmit
&& tsc -p tsconfig.test.json`) exits 0. It ran after the
`@object-ui/app-shell^...` closure build (29 projects, exit 0).
`--listFilesOnly` shows the panel in the main program and all three
panel suites in the test program.
- `pnpm exec eslint` on the three touched files exits 0. The JSON format
reports 3 files, 0 errors and 8 warnings. The base blobs of the two
existing files report the same 8 (`no-explicit-any` and
`set-state-in-effect` in untouched code), and the new suite reports
none.
- All exit 0:
- `node scripts/check-changeset-presence.mjs` ("3 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:phantom-deps`, `check:unreferenced-sources`, `check:i18n-keys`,
`check:i18n-designer-parity`, `check:metadata-write-doors`.
- Declared to CI: the full `pnpm test` farm and repo-wide `pnpm lint`.
**Reverse leg.** The implementation was committed first (`a551c491f`).
The panel was then written from its base blob, and the landing was
proven: 2 native select elements, 0 `ExplainPicker`, and a hash equal to
the base blob. The new suite and `AccessExplainPanel.test.tsx` then read
"Tests 18 failed | 5 passed (23)":
- red: all 17 new pins, and the package-scoped dropdown test;
- green: the other five existing tests.
That is the direction the suite header predicts. The trap restored the
file with `git checkout HEAD --`. The restore was proven: the hash
equals the HEAD blob and `git diff HEAD` is 0 bytes.
## Acceptance notes
- **The shared `Combobox` inside a `Sheet`.** Its open list did not
scroll under the mouse wheel, measured once in Chromium on the scratch
page above. This bears on this card's own remaining work: a later slice
that moves a long list inside a dialog or sheet to `Combobox` would meet
it. It is not filed from here, because no public entry on `main` was
measured. `ObjectRefField` and `RecipientPickerField` import the
`Combobox`, and whether either one renders inside a modal was not read.
- **The `Combobox`'s search reads the option value only.** It passes no
keywords to cmdk, so an option's label (a translated object label, for
example) is not searchable. This was read from source and not measured.
- **`defaultObject` has no caller in the tree.** In the tree, the
outside-the-options state is reached by text typed into the free-text
input before the package's object list arrives (read from source, not
measured).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 74add0c commit 0bbb67b
4 files changed
Lines changed: 334 additions & 26 deletions
File tree
- .changeset
- packages/app-shell/src/views/metadata-admin
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
201 | 201 | | |
202 | 202 | | |
203 | 203 | | |
204 | | - | |
205 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
206 | 207 | | |
207 | | - | |
208 | | - | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
209 | 212 | | |
210 | 213 | | |
211 | 214 | | |
212 | 215 | | |
213 | 216 | | |
214 | | - | |
| 217 | + | |
| 218 | + | |
215 | 219 | | |
216 | 220 | | |
217 | 221 | | |
| |||
0 commit comments