Repository navigation
fix(app-shell): Studio's app preview resolves locale-map app, nav-item and group labels (objectui#11100) - #11127
Conversation
…m and group labels (objectui#11100) The app label, each nav item's label and each group's label are the spec's I18nLabel (a plain string or a locale map). AppPreview read them as strings: the header ran String() over the app label ([object Object]), normalizeNav kept a label only when typeof was string (a map-labelled childless item was dropped with its target) and a map-labelled group fell to (unnamed). All three now resolve through resolveI18nLabel in the designer locale, as the areas list in the same file does. A nav item is kept whenever it has a target or children; its label only decides the text, and (unnamed) stays for a label that is truly absent. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
…ad, no new any-cast (objectui#11100) Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec 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
|
Contract reviewServed-tier: Inputs: card #11100 (body; triage ① Derived judgmentsDiff:
Nothing else in the diff. No accept-set moves on the spec side: the preview now honours what ② Semver level
Clause-②: no ③ Boundary flagsDev deviations (three), open_questions (none), one out-of-scope finding. a. PR assignee write refused. b. Attribution trailer. The two commits ( c. Base moved. The order measured d. Out-of-scope finding: Gates on the head. Check-runs on Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #11100
Clause-②: no
Studio's app preview now resolves the app label, each nav item's label and each group's label through the spec's
resolveI18nLabelin the designer locale, the way the areas list in the same file already does. A label only decides an entry's text; it no longer decides whether the entry exists.What was wrong (measured on origin/main 76e9df0,
AppPreview.tsx)String()over the app label, so a locale-map label printed[object Object].normalizeNavkept a label only whentypeof it.label === 'string', so a childless nav item with a map label was dropped together with its target.(unnamed).The spec types all three as
I18nLabel(a plain string or a per-locale map): thelabelof every navigation branch exceptseparator, and the app's ownlabel.What changed
AppPreview.tsx: the app label isresolveI18nLabel(draft.label, locale) ?? appName;normalizeNavtakes the designerlocale(threaded the wayunnamedis) and resolves each item's and group's label with it. The header no longer callsString()on a label.(unnamed)now reads only for a label that is truly absent, or a map that resolves to nothing.AppPreview.labelMaps-11100.test.tsx(7 tests) and one patch changeset for@object-ui/app-shell.Behavior change to review
An entry that names a record (has a target) but carries no label used to vanish from the preview. It is now kept and reads
(unnamed), which is what the direction on the card rules ("a nav item is kept whenever it has a target"). An entry with no label, no children and no target is still dropped, as before. Nothing else about a plain-string label moves; the plain-string control is pinned.Evidence
Tests 5 failed | 2 passed (7).git checkoutofAppPreview.tsxfrom the pinned base commit 76e9df0 (theresolveI18nLabel(draft.labelanchor count 1 to 0, theString(label)anchor 0 to 1), then the pin file again:Tests 5 failed | 2 passed (7)(direction: red, the two controls stay green). Restored withgit checkout HEAD -- FILE;git diff HEADempty and the HEAD blob hash equals the working-tree hash (5557011d1 at that step). The subject is imported by relative path fromsrc, so no rebuild sits between the mutation and the run.pnpm exec vitest run packages/app-shell/src/views/metadata-admin/previews/:Test Files 79 passed (79),Tests 1057 passed (1057), 7 of them the new pin.pnpm --filter @object-ui/app-shell type-check(tsc --noEmit && tsc -p tsconfig.test.json), after building its dependency closure withpnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build(the upstream direction): exit 0.tsc -p tsconfig.test.json --listFilesOnlynames the new test file, so the test project covers it.pnpm exec eslinton both changed files: 0 errors, 7 warnings, all theno-explicit-anycasts that were already in the file (the count is unchanged by this diff).node scripts/check-changeset-presence.mjs,node scripts/check-control-bytes.mjs,pnpm run check:new-line-citations(0 new citations),check:changeset-claims,check:pending-changeset-literals,check:test-path-roots: all exit 0.Declared narrowing (CI owns the rest)
The repo-wide lint scan and the full test and check farm are CI's. The public surface is unchanged (
AppPreview's props, no new export;normalizeNavis module-private), so no downstream sweep is owed. The pins are the evidence; the browser gallery was not driven.Acceptance notes
AppNavCanvas, whose ownnavLabelalso teststypeof label === 'string'. Probe at this head: a draft with a nav item labelled as a locale map, rendered witheditingin zh-CN, printsItem 1for that row while the landing line above it (this PR) prints the resolved客户. The canvas is a different file and an inline-rename editor, so it is reported for a separate card, not widened into this one.Generated by Claude Code