Repository navigation
feat(app-shell): ⌘K recent rows show their object's type and icon (objectui#12852) - #12877
Conversation
…jectui#12852) Each row of the command palette's recent group drew the same search glyph and its title alone, so two recent records that share a title (an organisation and its environment) rendered identically. A row now shows its object's label on the right and its object's icon on the left, as Home's "Recently accessed" row does. The object is read off the stored address by the existing recentItemObject; an address that names no object gives a row with no type and the neutral record glyph. Claude-Session: https://claude.ai/code/session_01SRHG3vksxM8h9PHq9mPEUW Co-authored-by: Claude <noreply@anthropic.com>
…i#12852) The recent rows' object lookup read `useMetadata().objects` at render, which starts the object list's load while the palette is still closed (CommandPalette.studioScope-11863 "reads nothing until the palette opens"). Read it inside the row function, which runs only for drawn rows. Claude-Session: https://claude.ai/code/session_01SRHG3vksxM8h9PHq9mPEUW Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SRHG3vksxM8h9PHq9mPEUW Co-authored-by: Claude <noreply@anthropic.com>
✅ 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
|
席位核对 — ACCEPT · objectui#12852 · head
|
| row | main 5ff64ef |
this branch |
|---|---|---|
| Objectstack | search icon, no type | dollar icon, 商机 |
| Objectstack | search icon, no type | check-square icon, 任务 |
| Sarah Johnson | search icon, no type | user icon, 联系人 |
No /api/v1/meta request after opening the palette, on either side.
Screenshots, read by the seat (never-merged claude/issue-12852-evidence at 7122f5c):
- before: five identical search-glyph rows, two of them "Objectstack";
- after: 商机 / 任务 / 联系人 / 线索 / 产品 on the right, each with its own icon.
Sent to the maintainer at 2026-10-17T10:59Z.
Tests:
CommandPalette.recentItemType-12852.test.tsx, 5 cases:- two same-titled records of different objects differ in type and icon (the card's own acceptance);
- zh-CN types;
- CONTROL: an underivable href shows no type;
- CONTROL: an unknown object gets its machine name;
- CONTROL: membership, order, count and
onSelect.
- Five ablations, each red and each restored.
- 15 files and 76 tests across the palette, Home recent and record-visit pins passed. app-shell
type-checkandbuild, eslint,check:i18n-keys,check:i18n-drift, changeset presence andcheck:new-line-citationsall exit 0.
Changeset: @object-ui/app-shell patch; user-facing prose.
CI: running at this record. Landing waits for green.
Rulings
- The neutral glyph is
FileText, Home's record glyph: A, as built. The dispatch said to match Home'sRecentApps. A search glyph on a recent row says nothing about what the row is. - The non-record kind label is not written: A. The group lists records only (
type === 'record', measured), so the card's 页面 example cannot appear there, and a branch nothing reaches is not built. If the group is ever widened, that card addsrecentItemTypeLabelbeside Home's identical use. - The cloud console's two "Objectstack" rows (an organisation and its environment) get a type exactly when the cloud console stores them as
/apps/APP/OBJECT/record/ID, the one shape objectui'sRecordDetailViewwrites. Another shape shows no type, by ruling 2. The cloud repo is outside this session. The seat notes this on the card forrepo:cloudto read, and no follow-up is filed until a measurement shows another shape. - The row reads
useMetadata().objects, not the palette's app-scoped prop: A. Recent items are cross-app, so the app scope would give other apps' records a machine-name type. The read happens only while the palette is open with recent rows, never at console open (pinned bystudioScope-11863), so objectui#12811's narrowed open stands.
Implemented-by: cloud session session_01SRHG3vksxM8h9PHq9mPEUW, branch claude/issue-12852-recent-item-type
Generated by Claude Code
Landing · head
|
Fixes #12852
Clause-②: no
What changed
In the command palette (⌘K), every row of the recently viewed group drew the same search icon and its title alone, so two recent records with the same title rendered identically. Each row now shows:
One file changes (
packages/app-shell/src/chrome/CommandPalette.tsx), plus a new test beside it and an@object-ui/app-shellpatch changeset.RecentItemsProvider's stored entry shape,recentItemTypeLabel.ts,useRecentItemLabel.ts, the locale packs andpackages/components/src/uiare untouched. The group's heading, order, count (5),onSelectand every existingdata-testidstay as they were; the type text carries a newdata-testidofpalette-recent-type.How each row's type and icon are derived
href, through the existingrecentItemObject(its/apps/APP/OBJECT/record/IDparse). The helper is imported, not copied.useNavTargetLabel(the object's current label in the viewer's language), else the object's machine name. This is the rule Home's Recently accessed trail uses.getIcon, as the palette's record-search groups use it, elseFileText, the record glyph of Home'sRECENT_ICON.useMetadata().objectsis read inside the row function, never at render, so a closed palette still reads no metadata (CommandPalette.studioScope-11863, 'reads nothing until the palette opens').Stored shapes that cannot carry a type
A record entry whose
hrefis not/apps/APP/OBJECT/record/IDnames no object, so its row shows no type and the neutralFileTexticon. The type is never guessed from the label or the id. objectui writes record entries in one place,RecordDetailView, always in that shape. So only an entry written by another producer into the synced preference can lack a type, for example a non-/appsroute.Group membership, as measured
The group still lists
recentItems.filter(it => it.type === 'record').slice(0, 5). Only records appear in it, so a 页面 (page) entry cannot appear, and the card's 页面 example does not apply to this group. The filter is unchanged.Live before and after
Setup: hotcrm
objectstack dev --freshbackend, consoles frommain5ff64efand from this branch, zh-CN, light theme. Acrm_opportunityand acrm_taskwere both renamed 'Objectstack' (locally only), and a contact was visited too. Then ⌘K was opened with an empty input.main: the two 'Objectstack' rows are identical; every row has the search icon and no type.Screenshots (evidence branch
claude/issue-12852-evidence, not merged):Tests (on 210ce40)
CommandPalette.recentItemType-12852.test.tsxchecks:Each new pin was ablated once (icon, type text, label vs machine name, the neutral control, the count). Each run went red, was restored and showed an empty
git diff HEAD.Gates on 210ce40:
@object-ui/app-shelltype-check and build: exit 0.check:i18n-keys,check:i18n-drift,check-changeset-presenceandcheck:new-line-citations: exit 0.Deviations
None in the code. The neutral icon is Home's record glyph (
FileText), not the old search icon, so the palette and Home draw the same thing.Session:
https://claude.ai/code/session_01SRHG3vksxM8h9PHq9mPEUWGenerated by Claude Code