This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
fix(a11y): name icon-only buttons and give clickable div/span controls a keyboard path (objectui#13461) - #13494
Merged
Conversation
…ard path (objectui#13461) Names the icon-only buttons the objectui#12143 census froze in app-shell, components, fields and plugin-chatbot, plus the top bar's avatar button, through each package's translation hook. Turns the console's mouse-only clickable div/span controls into real buttons, and adds a deletions-only census of clickable div/span sites with no keyboard path. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qafSnDdNuQgZGfnFwDajn
…461) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qafSnDdNuQgZGfnFwDajn
Contributor
✅ 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
|
Contributor
Author
席位核对 — ACCEPT · PR #13494 @
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Elon · project thread
Fixes #13461
Clause-②: no
Metadata-protocol: none
What changed
Icon-only buttons in the console get an accessible name, and the console's mouse-only clickable
div/spancontrols become real buttons. A new deletions-only census keeps clickablediv/spansites from coming back.Premise re-measured (the card's counts were a script reading)
The card's 25 / 24 came from a line-window script. Re-measured on the TypeScript AST at base
c85408f:aria-labela few lines below the opening tag (the AI chat page, the invitations page, the chat dock), so they were never unnamed. The instrument that already re-derives this family isiconOnlyButtonCensus-12143.test.ts(it exists; the card says nobody filed it). This PR names every entry of itsBACKLOGinside the claim's file surface (app-shell, components, fields, plugin-chatbot: 16 sites in 12 files) and deletes those rows. The top bar's avatar button, which that census cannot see (anAvataris not an icon), is named too.div/span. The new census reads everydiv/spanwith anonClickand norole,tabIndexor key handler underpackages/*/srcandapps/*/src. Most sites are not controls: propagation guards around real buttons, scrims behind overlays, empty design-canvas backgrounds, and drag handles. Each is declared inNOT_CONTROLSwith its reason. ⛔ None gotrole="button".Repaired
spaninside the card'sbutton(unreachable by Tab, read as part of the card's name)buttonbeside the card button;organization-manage-SLUGtest idspan; the wide hit path is pointer-onlyrole="button",tabIndex,aria-pressed, Enter / Space when the edge is selectabletree-viewnode rowdivwrapped round the togglebutton; toggle unnamedcommon.expand/common.collapse) witharia-expanded; the node is abuttononly when the host passesonNodeClickfile-uploaddropzonedivrole="button",tabIndex={0}, Enter / Space opens the pickeronSelectclick handler that could never fire (the list renders only outside design mode, where the handler is undefined)Icon-only buttons named: AI live canvas close (
common.close), action result dialog secret toggle (actions.resultDialog.showValue/hideValue), permission set editor remove policy / remove tab (perm.rls.remove/perm.tabs.remove, designer table en + zh), metadata history refresh (engine.edit.refresh), sort builder remove (sortBuilder.removeSort),file-uploadandFileFieldremove (fields.file.remove),MasterDetailFieldopen / remove (fields.masterDetail.*),PasswordFieldtoggle (fields.password.*),QRCodeFieldcopy / toggle (fields.qrCode.*), legacyChatbotsend (chatbot.sendMessage), chat scroll-to-latest (chatbot.scrollToBottom, before the props spread so a caller's name wins), top bar avatar (user.accountMenu). New pack keys are in all ten packs.The census —
packages/components/src/__tests__/clickableNonControlCensus-13461.test.tsSame shape as the objectui#12143 and objectui#12145 censuses: an ordinary-suite test, ⛔ not a new CI gate. Sites are keyed by file, tag and handler (never by line);
NOT_CONTROLSandBACKLOGare deletions-only and must equal what the scan finds. It carries width guards, a matcher fixture, and a stated blind-spot list (spread attributes, other tags, whether a reason is still true).BACKLOGfreezes 16 clickable controls that still have no keyboard path. 15 are outside the claim's file surface (plugin-ai, plugin-designer, plugin-gantt, plugin-grid, plugin-view). One is in app-shell: the studio data-form preview selects a field by a click delegated from its frame, and a keyboard path for that is a design question. The 12143 census keeps its 14 remaining plugin rows (plugin-ai, plugin-detail, plugin-list, plugin-view).Verification (head after the merge of main,
ecd30ca)OrganizationsPage.tsxfromorigin/mainand the new census went red withOrganizationsPage.tsx · span · stopPropagation,navigate — declared 0, found 1. Restored withgit checkout HEAD --, andgit diff HEADwas empty.keyboardControls-13461.test.tsx(components: tree toggle name and state, node button only withonNodeClick, zh pack; dropzone Enter / Space, remove-button name),iconButtonNames-13461.test.tsx(fields: password, QR code, master-detail names, zh pack), plus anOrganizationsPage.test.tsxcase (Manage is a sibling button and does not switch org) and anAppHeader.myOrganizations.test.tsxcase (avatar button name).tree-view-nodes-mirror-6939, 8 files, 54 tests) passed.packages/i18n/whole package: 87 files passed.turbo run type-checkfor app-shell, components, fields, plugin-chatbot and i18n with their dependencies: green after a test-typing fix in fields.check:i18n-keys,check:i18n-dead-keys,check:i18n-drift,check:i18n-designer-parity,check:new-line-citations,check-changeset-presence,check-changeset-no-major,check-changeset-claims,check-pending-changeset-literalsandcheck-changeset-fixedall exit 0. ESLint on touched files: 0 errors with inline config. Onereact-hooks/static-componentserror appears under--no-inline-configinAppPreview.tsx, andorigin/main's copy of that file shows the same error.check:eager-locale-catalogues(needs a built console bundle; CI builds first). The whole-repopnpm testandpnpm lintare left to CI.Acceptance notes
Literal user-facing strings next to the touched controls are untouched (the legacy
Chatbot's empty-state line,MasterDetailField's record count,file-upload's launch copy,ResourceHistoryPage's "Back to item"). They are outside this card.The optional per-route axe pass, a required axe check and repo-wide
eslint-plugin-jsx-a11yare out of scope, per the claim.Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer)
🤖 Generated with Claude Code
https://claude.ai/code/session_018qafSnDdNuQgZGfnFwDajn