Repository navigation
fix(components): RefreshIndicator requires its accessible name; four views pass a translated one (objectui#10580) - #10635
Conversation
…views pass a translated one (objectui#10580)
`RefreshIndicator`'s `ariaLabel` loses its English default ("Refreshing")
and becomes required, so a caller that names nothing is a compile error.
ObjectGrid and ListView pass their existing `grid.refreshing` /
`list.refreshing`; ObjectChart and ObjectDataTable pass new
`chart.refreshing` / `dashboard.refreshing` keys, added to all ten packs.
Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy
Co-authored-by: Claude <noreply@anthropic.com>
…bjectui#10580) Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ 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: Reviewed read-only: card objectui#10580 (body and its three comments: triage Diff shape, measured by git: 21 files, +543 −8; 1 changeset added, 1 component source edited, 4 caller sources edited, 10 locale packs edited (+2 each), 5 pin files added. No file is deleted; no existing test file is touched. The REST file list is the same 21 paths. The diff consumes no ① Derived judgmentsBinding text applied, quoted verbatim: triage
② Semver levelChangeset Changeset prose, sentence by sentence:
Docs/README prose added by the diff: none (no ③ Boundary flags
Implemented-by: VERDICT: PASS |
✅ 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
|
Merge-queue eviction at 13:55Z: not this PR's failure
|
CI at
|
Contract reviewServed-tier: Re-review at the PR's new head. Reviewed read-only: card objectui#10580 (body and its five comments: triage Diff shape at the new merge-base, measured by git: 21 files, +543 −8, the same 21 paths as the REST file list: 1 changeset added, 1 component source edited, 4 caller sources edited, 10 locale packs edited (+2 each), 5 pin files added. No file is deleted and no existing test file is touched. Compared hunk for hunk with the reviewed diff ( ① Derived judgmentsBinding text, quoted verbatim. Triage
② Semver levelChangeset Changeset prose, sentence by sentence:
Docs/README prose added by the diff: none (no PR body prose added for the round (the one 「Round 2」 bullet under Gates), sentence by sentence:
Older body sentences that name ③ Boundary flags
Implemented-by: VERDICT: PASS |
✅ 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: Re-review at the PR's new head. Reviewed read-only: card objectui#10580 (body and its six comments: triage The merge, measured by git. The tree of Diff shape at the new merge-base: 21 files, +543 −8 by both git and REST, the same 21 paths: 1 changeset added, 1 component source edited, 4 caller sources edited, 10 locale packs edited (+2 each), 5 pin files added. No file deleted, no existing test touched. Compared line for line with the previously reviewed diff ( ① Derived judgmentsBinding text, quoted verbatim. Triage
② Semver levelChangeset Changeset prose, sentence by sentence:
Docs/README prose added by the diff: none (no PR body prose added for this round (the one 「Round 3」 bullet under Gates), sentence by sentence:
Older body sentences that name ③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #10580
Clause-②: yes
RefreshIndicator's publishedariaLabelprop loses its English default ("Refreshing") and becomes required, so a caller that passes no name is a type error instead of an English accessible name. This is the "declaration enforces" option the triage allowed on this PR (triage comment5831898614), taken by the seat's claim (5832044126). The four views that passed no name now pass their translated one. It is the objectui#3546 class: text a user meets that bypasses the translation layer.What changes
packages/components/src/custom/refresh-indicator.tsx:ariaLabel: stringis required, the= "Refreshing"default is gone, and the docblock says why.ObjectGridpassest('grid.refreshing')andListViewpassest('list.refreshing'): the same keys, through the same hooks, that their pull-to-refresh text already reads. No new grid or list key.ObjectChartpassest('chart.refreshing'). Thetcomes from theuseObjectTranslation()call the file already makes forlanguage. It is deliberately not the file'stt(useSafeTranslate), becausetttakes an English fallback string at every call, and the ruling is no English fallback anywhere.ObjectDataTablepassest('dashboard.refreshing')from theuseObjectTranslation()call it already makes.packages/i18n/src/locales/*.ts:chart.refreshingin thechartblock anddashboard.refreshingat thedashboardblock's top level, each placed after that block'sloadingkey, in all ten packs. Each pack's value is the translation its owngrid.refreshingalready carries..changeset/10580-refresh-indicator-translated-name.md:minorfor@object-ui/components, with the break stated as BREAKING (this repo marks its own breaking changesminor), andpatchforplugin-grid,plugin-list,plugin-charts,plugin-dashboardandi18n. The changeset prose states the contract change, so a contract review is owed.Caller census (H4)
git grep -n 'RefreshIndicator'over the whole tree, re-run on the merged head641ed9f, finds five render sites. After this PR every one passes a translated name:ObjectGrid,ListView,ObjectChart,ObjectDataTable, andObjectGantt, which already passedt('gantt.aria.refreshing')and is unchanged. Before this PR no other package, app, example, docs snippet or test rendered it.RefreshIndicatorPropshas no other code reader; its one other mention is a docblock inMetricWidget.tsx. No docs page renders the component, socheck:doc-snippetsandcheck:doc-typeshave nothing of it to read and were not run. The sibling objectstack checkout has zeroRefreshIndicatorhits. The merge oforigin/mainbrought in no new render site.H5
ariaLabel=""still type-checks, because the prop is a plainstring. As ruled, no runtime check was added: the type is the gate.Pins
packages/components/src/__tests__/refresh-indicator-required-name-10580.test.tsxRefreshIndicatorwith noariaLabelsits under@ts-expect-error, checked by the package'stsc -p tsconfig.test.json. DOM: the bar is named with exactly the passed string, and a caller that casts past the type gets noaria-labelat all, so there is no English fallback left.packages/plugin-grid/src/__tests__/ObjectGrid.refreshIndicatorLocale-10580.test.tsxde: the bar is namedWird aktualisiert…during a bus-driven re-read.encontrol:Refreshing….packages/plugin-list/src/__tests__/ListView.refreshIndicatorLocale-10580.test.tsxzh:刷新中…during a toolbar-refresh re-read.encontrol:Refreshing….packages/plugin-charts/src/ObjectChart.refreshIndicatorLocale-10580.test.tsxzh:刷新中…during a bus-driven re-read.encontrol:Refreshing….packages/plugin-dashboard/src/__tests__/ObjectDataTable.refreshIndicatorLocale-10580.test.tsxja:更新中…during a filter-change re-read.encontrol:Refreshing….In every view pin the second query is held open by hand, so the bar is read while the query really is in flight.
ObjectGantt.refreshInPlace-7237.test.tsxwas run unchanged and stays green.Reverse verification (each leg ran from a committed state, with trap restore and restore proven by hash)
adeecd6, with the pins taken from HEAD7a1b619. The 5 pin files then gave exit 1,Tests 9 failed | 3 passed (12). The failure dump readsaria-label="Refreshing"on the progress bar. On-disk proof of the mutation: the default literal counted 1 and the grid caller's name counted 0. After the restore (git checkout HEAD --),git diff HEADwas 0 bytes and all 15 paths were hash-equal to their HEAD blobs. The same 5 files at HEAD gave exit 0,Tests 12 passed (12).ariaLabel?: stringwas written back on disk (optional count 1, required count 0).tsc -p tsconfig.test.jsoninpackages/componentsthen gave exit 2,error TS2578: Unused '@ts-expect-error' directive.at the pin. After the restore it gave exit 0.--listFilesshows the pin file in that program (1 hit).dist/*.d.ts, whoserefresh-indicator.d.tsdeclaresariaLabel: string;). WithObjectGrid'sariaLabeldropped on disk,tsc --noEmitinpackages/plugin-gridgave exit 2,TS2741: Property 'ariaLabel' is missing in type '{ active: boolean; }' but required in type 'RefreshIndicatorProps'.It was restored hash-equal.Gates
Pre-merge head
b240863:pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/: exit 0,157 passed (157)files,1489 passedtests.… packages/plugin-list/ packages/plugin-charts/: exit 0,172 passed (172),1982 passed.… packages/plugin-dashboard/ packages/i18n/: exit 0,201 passed (201),2424 passed.… packages/components/src/custom/plus the components pin plusObjectGantt.refreshInPlace-7237.test.tsx: exit 0,2 passed (2),11 passed.src/custom/holds no test file.Merged head
641ed9f, after the merge oforigin/main6516320, which moved all ten packs andpackages/components:pnpm exec vitest run --maxWorkers=2 packages/i18n/plus the 5 pins plus the gantt pin: exit 0,77 passed (77),1197 passed.pnpm turbo run type-check --filter @object-ui/components --filter @object-ui/i18n --filter @object-ui/plugin-grid --filter @object-ui/plugin-list --filter @object-ui/plugin-charts --filter @object-ui/plugin-dashboard --filter @object-ui/plugin-gantt --concurrency=2: exit 0,22 successful, 22 total, with all 7 type-check tasks executed (cache miss).pnpm check:i18n-keys,check:i18n-drift,check:i18n-dead-keys(norefreshingcandidate),check:control-bytes,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:new-line-citations,check:changeset-claims,check:pending-changeset-literals,changeset:check,node scripts/check-changeset-presence.mjs: all exit 0.pnpm exec eslintover the 20 changed.ts/.tsxfiles: exit 0, 0 errors.Lint, narrowed and declared. The repo-wide
pnpm lintwas not run locally; CI owns it. Evidence that the narrowing excludes nothing: (1)eslint.config.jsapplies to**/*.{ts,tsx}, and every one of this diff's 20.ts/.tsxfiles is in that population; (2)--format jsonreports 20 files linted, 0 errors; (3) the config has noparserOptions,projectServiceorproject:(0 hits) and no import plugin (0 hits), so linting is not type-aware and this diff cannot move the verdict of any file it does not touch.origin/main4a3d500as1a89050(merge only; this PR's own diff is unchanged at 21 files, +543 / −8). There, theplugin-listsuite plus the five pins and theObjectGantt7237 pin (104 files, 1166 tests), and the seven type-checks, re-ran green. The merge-queue eviction at 13:55Z was the objectui#10645 test, which is not this PR's (os-dev-report round 2, comment5834284916).origin/main7baede3(it carries PR objectui#10677, the change for objectui#10645) ata6512a7, with no conflicts; the five pins, theObjectGantt7237 pin and the seven type-checks re-ran green there (os-dev-report round 3, comment5836351479).Acceptance notes
ObjectChartwith noI18nProvider: the bar is namedchart.refreshing, the key itself.ObjectDataTablereads its name the same way (useObjectTranslation().t) and was not measured separately. Grid, list and gantt still resolve English there through their owncreateSafeTranslationdefaults maps. This is what "no English fallback" means at the two new call sites. The console mountsI18nProviderinapps/console/src/main.tsx, so it does not reach the console. The changeset says so.RefreshIndicatorspreads...propsafteraria-label, so a caller's ownaria-labelattribute still overridesariaLabel. That was true before this PR and is unchanged.chartblock inen.tsstill describes the pack as budgeted inside theframeworkchunk.scripts/check-eager-closure-budget.mjsnow gives the pack its owni18n-locale-enceiling. The comment has drifted and is not touched here.de,grid.refreshingreadsWird aktualisiert…whilelist.refreshingreadsAktualisiere…. The two new keys use the former. This is polish and is not touched here.Generated by Claude Code