Repository navigation
fix(components,i18n): name the data table pager's four page buttons (objectui#12124) - #12142
Conversation
…objectui#12124) The data-table pager drew first / previous / next / last as icon-only Buttons with no accessible name. Each now reads its aria-label through the renderer's own useTableTranslation, from four new table.* keys added to TABLE_DEFAULT_TRANSLATIONS and to all ten locale packs. Pins: a real paged ObjectGrid's four buttons are found by role and name and driven to the page each names, provider-less (en defaults) and under zh; the objectui#12081 footer suite's chevron-icon lookup becomes the role query. Claude-Session: https://claude.ai/code/session_01TYgwmFK1q4KJ6Qq2WRLzsD 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
|
…ds are not covered (objectui#12124) The changeset said no type member is added, but the four keys add members to the exported en pack and so to TranslationKeys. It also said every paged ObjectGrid draws the data-table pager; a grouped grid with more than one page of groups draws its own group pager, which stays unnamed (objectui#12143). Claude-Session: https://claude.ai/code/session_01TYgwmFK1q4KJ6Qq2WRLzsD 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: Rendered by an isolated subagent of the seat session, read-only, from these inputs and nothing else: card objectui#12124 (body and all three comments: triage 6106865988, claim 6108325399, dev report 6109512642), PR objectui#12142 (body, file list, net diff against ① Derived judgmentsHead versus the report. The PR holds two commits: the report's Every accept-set and public-surface change the diff implies, each judged:
Check-runs on the head, read at 2026-10-11T13:49Z: 42 runs. 35 ② Semver levelChangeset
③ Boundary flags
Not governed: no path in the file list is a governed surface ( Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #12124
Clause-②: yes
The
data-tablerenderer's pager, which an ungrouped pagedObjectGriddraws, rendered first / previous / next / last as fourButton size="icon"whose only child was a chevron icon. None had an accessible name, so a screen reader announced four unnamed buttons. Each now carries anaria-labelread through the file's ownuseTableTranslation. No literal English. A grouped grid with more than one page of groups drawsObjectGrid's own group pager instead; that pager is not covered here and is tracked as objectui#12143.table.firstPagetable.previousPagetable.nextPagetable.lastPageWhat changed
packages/components/src/renderers/complex/data-table.tsx: fouraria-label={t('table.KEY')}attributes on the pager buttons, and the four rows inTABLE_DEFAULT_TRANSLATIONS, the provider-less stand-in for theenpack.packages/i18n/src/locales/*.ts: the four keys in thetableblock of all ten packs, each a real translation, placed afterpageInfo. The names follow the namespace's camelCase and thepreviousPage/nextPagespelling the packs already use elsewhere..changeset/12124-pager-button-names.md:@object-ui/i18nminor (four pack keys),@object-ui/componentspatch.Clause-②: yesis the claim's reading (comment 6108325399): the four keys widen@object-ui/i18n's published packs, soTranslationKeys(derived from theas constenpack) gains four members. Triage graded itno; the isolated contract review decides.Pins
packages/plugin-grid/src/__tests__/pagerButtonNames-12124.test.tsx, through a real pagedObjectGrid(12 rows, pages of 5):getByRole('button', { name })finds each of the four by theenpack's value, and each is driven. A click lands on the page its name promises; first and previous are disabled on page 1, next and last on the last page. So two swapped keys go red, not only a missing one.zh: each is found by the zh pack's value, each zh value differs from the en one, and no button carries the English name.packages/plugin-grid/src/__tests__/footerSummaryScope-12081.test.tsx, the objectui#12123 test. Its next-page lookupdocument.querySelector('button svg.lucide-chevron-right.h-4')?.closest('button')is nowscreen.getByRole('button', { name: en.table.nextPage }).Evidence (HEAD
cae900c)The defect, and each pin's ability to fail. Each leg was run from the committed fix and restored; after each, the file's blob equals the HEAD blob
1d85896andgit diff HEADis empty.data-table.tsxreplaced by its BASE blobfbc18df(packs and tests at HEAD); pageraria-labelcount on disk 0Unable to find an accessible element with the role "button" and name "First page", the same for"Next page"in the switched footer test, and for"下一页"under zharia-label={t('table.nextPage')}todata-ablated=…via objectstack'sscripts/ablation-replace.mjs: anchor 1 to 0, blob1d85896to475ebf9"Next page"twice,"下一页"onceablation-replaceruns, each anchor 1 to 0expect(button('firstPage')).toBeDisabled():Received element is not disabledAt HEAD the same two files run 21 passed (2 files).
Gates (all at HEAD
cae900c)pnpm --filter '@object-ui/components^...' run build, then the rest of@object-ui/plugin-grid's closure (components, fields, permissions, providers, mobile, plugin-detail). Both exited 0;packages/i18n/dist/locales/en.d.tscarriesfirstPage.pnpm --filter @object-ui/i18n type-check,@object-ui/components type-checkand@object-ui/plugin-grid type-checkall exit 0. The plugin-grid test project lists both touched test files (tsc --listFilesOnly).packages/i18n/plusRelatedList.serverpagination.test.tsx(its/next/irole query shares a screen with a data-table): 83 files passed.packages/components/in 4 shards: 94, 94, 94 and 92 passed (1 skipped), 375 files in all. Ratchetscolumn-identity.ratchet.test.tsandone-authority-per-exported-name-6273.test.ts: 2 passed. Root suitescripts/__tests__/in 3 shards: 60 (1 skipped), 59 (1 skipped) and 60 passed, 181 files in all.check:i18n-keys(everycreateSafeTranslationdefaults row repeats theenvalue),check:i18n-drift(4 keys added, 0envalues changed),check:i18n-dead-keys(report; none of the four listed),check:i18n-designer-parity: all exit 0.check-changeset-presence.mjs(13 source files of 3 released packages, 1 changeset),changeset:check,check:changeset-claims,check:pending-changeset-literals,check:new-line-citations(0 new),check:control-bytes,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:phantom-deps.eslintfrom each package dir, inline config honoured) on the 13 touched files: 0 errors. 34 warnings, all indata-table.tsxand none on a changed line; BASE'sdata-table.tsxhas the same 34.components/dist/index.js+315 B raw, +75 B gzip-9;i18n/dist/locales/en.js+134 B raw, +17 B gzip-9. The console-build delta (minified, chunked) andcheck:eager-locale-cataloguesare NOT MEASURED. Reason: both need the whole workspace plusapps/consolebuilt. No import or specifier moved, so the catalogue composition that gate weighs is unchanged by construction.performance-budget.ymlmeasures both in CI.Acceptance notes
Two findings outside this card, left untouched. Both are handed to the seat in the report.
ObjectGrid's owngroupedPager(inpackages/plugin-grid/src/ObjectGrid.tsx) draws first / previous / next / last as icon-onlyButtons with no name. It renders for every grouped grid with more than one page of groups. It already readstable.rowsPerPageandtable.pageInfo, so the four keys this change adds are the ones it needs. Not edited here: the file is outside the claim's file surface. Its own tests find these buttons by DOM position (groupedPagination.test.tsx: "The next chevron is the 3rd of the 4 nav buttons"). The in-process role-query probe is NOT MEASURED: the verify lock answered queue-timeout twice.aria-label="Row actions"in every locale. A localization gap, not a missing name. Code read only; the zh probe is NOT MEASURED for the same reason.Not in this change: the other tests that reach a pager button by position (
groupedPagination.test.tsx,serverPagination.test.tsx,data-table-manual-pagination.test.tsx) keep their lookups. The card names only the objectui#12123 test.Session:
https://claude.ai/code/session_01TYgwmFK1q4KJ6Qq2WRLzsDGenerated by Claude Code