fix(automation-control): surface deploy errors and fix stale loading rows in review modal - #2035
Draft
paustint wants to merge 84 commits into
Draft
fix(automation-control): surface deploy errors and fix stale loading rows in review modal#2035paustint wants to merge 84 commits into
paustint wants to merge 84 commits into
Conversation
Includes automated PR-review feedback and the E2E Unsubscribe locator disambiguation that the icon-button rename required.
… for repeated card actions
- arrow/Space/Enter selection and roving tab order work end to end - nested field-list filters no longer move the parent list - row-local ArrowRight reaches secondary controls
- field-list tooltips and copy badges are reachable and announced - keyboard shortcuts inside tooltips are announced to screen readers
…ty, and filter jitter - visible (inset) focus indicators in lists and comboboxes on Safari - arrow keys work in portaled combobox/picklist menus; option roles sit on the focused element - menus no longer jump as stale filters clear
…nnounced labels - load-type radios (and four more groups) had per-value names, making each its own group - groups expose role=radiogroup with the legend announced on entry
…sibility - inline history editing manages focus and alignment - save-query is a real toggle button; focus survives saving a favorite
…alogs they open - focus returns to the trigger after selecting an item - the trigger is focused BEFORE the selection callback so a modal it opens records the right return target
…sion, result-count announcements - the clear (X) button returns focus to the input - password managers no longer inject UI/screen-reader noise - settled filter result counts are announced in grids and list panels
…ng the Load/Cancel chain
Browsers expose no screen-reader detection API, so Monaco's screen reader mode is an explicit opt-in (Settings > Code Editors on web, desktop, and extension), persisted in localStorage and applied to every editor via the shared wrapper's default options; everyone else keeps Monaco's own 'auto' detection. The setting documents Alt+F1 editor accessibility help and the Ctrl(+Shift)+M tab-trap toggle.
… (M36-M56) C8 (dnd keyboard reorder) and C10 (virtualization row counts) verified in the manual pass; C9 resolved via the editor screen-reader setting. M36-M56 record the second sweep covering every remaining surface, and the open list now reflects what actually remains (jgrid retoken, nested-interactive decision, copy-button name sweep, VPAT finalization).
useAnnouncer owns the clear-then-set re-announce idiom that five features hand-rolled (with drift: one grew an isMounted guard the others lacked), and ShowingCountStatus renders the visible "Showing X of Y" line and its debounced announcement from one string — the two had already drifted apart in ListWithFilterMultiSelect. The permission manager tables now announce through one table-level region via the table context instead of mounting a live region per action column.
…s renderer The severity-to-cellClass mapping and sr-only View-details button were triplicated: byte-identical blocks in the two permission trees plus a divergent copy in the export grid that sniffed the class string for '--error'. withFindingDetailsCell owns both halves from a severity accessor; rendered DOM is unchanged.
The skip-link target, main landmark, and route-change focus wiring were copy-pasted across the web, desktop, and extension shells, and the 'main-content' id had two independent definitions (SkipToContent's default vs ui-core's constant). AppMainContent owns the main element and FocusMainContentOnRouteChange; MAIN_CONTENT_ID now lives in @jetstream/ui next to SkipToContent, its only other consumer. Shell DOM is unchanged.
The canvas shell was the only one without a skip link, main landmark, or route-change focus management — the copy-paste block never reached it. One-line adoption of AppMainContent plus SkipToContent brings it to parity with the other three shells.
…ract The stay-focusable-while-disabled idiom was hand-rolled at 14 sites in three shapes (conditional-undefined, plain boolean rendering aria-disabled="false", and a Link preventDefault variant), with the same explanatory comment pasted at seven of them and the not-browser-enforced invariant documented only in the ui-styles CSS. ariaDisabledButtonProps returns the attribute and the guarded onClick together so they cannot drift; the disabled path calls preventDefault, covering links too.
… DOM convention
PerformLoad focused a new run's tab via document.getElementById('tab-' +
id), hard-coding Tab.tsx's private anchor-id scheme — a rename there
would silently break the retry focus hand-off. TabsRef gains focusTab(id)
next to changeTab, owned by the component that renders the ids.
…guards The popover/modal/dropdown/dialog selector existed as three copies (keyboard navigation, GridBody refocus guard, GridContainer blur guard) and had already diverged — the blur guard was missing [role=dialog], the same drift that previously lost .slds-dropdown in one copy. GRID_OVERLAY_SELECTOR is now the single list; GridContainer appends its site-specific .jgrid-editor.
…r row M31 described the polling implementation that has been replaced by deterministic row ids plus an effect; C3 still called TimePicker a thin Picklist wrapper after M39 rebuilt it as a combobox.
… navigation Every accordion header was a page tab stop — 77 of them on Account's Related Objects (Subquery) list — making the rest of the query builder unreachable by keyboard. Accordion gains an opt-in singleTabStop roving-tabindex mode: ArrowUp/ArrowDown move between headers (wrapping, skipping disabled sections), Home/End jump to the ends, Enter/Space toggles natively, and Tab moves from the header into the open section's embedded controls. The tab stop starts on the initially open section so a navigator jump lands where the user left off. Other accordions keep the APG default of a tab stop per header. Logged as M57.
…pened overlays React synthetic events propagate through portals following the REACT tree, so pressing Enter/Space on a button inside a portaled overlay a cell renderer opened (the record lookup popover) reached the grid's root onKeyDown, which activated the active cell's control and toggle-closed the popover before the real button's click could fire. The handler now ignores events whose DOM target is outside the grid root — those keys belong to the overlay.
… loads The View Record button's autoFocus fired when the footer mounted AFTER the async record fetch, yanking focus from the close button mid- interaction. Focus now starts and stays on the close button, per the popover's normal initial-focus behavior. Logged as M58.
…stand-alone PR Error-row visibility, tooltip-only error messages, a visible success-vs-error summary (the assistive message already computes it), and the stale loading row are all pre-existing and deferred — captured here so the conformance trail points at the follow-up work.
…ists Every test class was two tab stops (chevron + checkbox) plus one per expanded method, so keyboard users could not get past the list — the class tree and suite-membership list are now single tab stops with arrow-key navigation. Run actions moved to the page header (matching other pages) with the Cmd/Ctrl+Enter primary-action shortcut; launch state lifted into useApexTestRunLauncher so the header owns the buttons. Launching a run now focuses the Test Runs tab instead of dropping focus to <body>, and the scroll containers no longer clip focus rings. The suite modal separates Select All from the list and saves with the same shortcut (the page-level run shortcut is suspended while it is open). Logged as M59.
The 28.5px default row crowded the badges against the row edges, and the full-height click-target wrapper defeated the cell's own flex centering, pinning cell content to the top.
DataTable's quickFilterText is inert unless includeQuickFilter is also set — the grid's global filter only engages when both are present, and only the text was passed.
…popover close A filter matching zero rows made every grid key return early, so the header row — the only way to broaden the filter again — was unreachable. Navigation keys now route to the header/summary rows, Tab-in seeds the header, and a stale active cell snaps to the header keeping its column. Closing a header-filter popover could also strand focus on the filter icon: an overlay unmounting with focus inside it fires no focusout, so the return-focus-to-cell check never ran. It now runs on focusin too, and a return target whose row was filtered away falls back to that column's header cell. Logged as M60.
…rows in review modal Rows that failed metadata retrieval were flipped to 'Deploying' along with everything else, but deployMetadata skips them so they never received a result and sat on a spinner after the deployment finished. Error rows now keep their state, get the grid's standard save-error red treatment, and show their full error message in a visible wrapping column (the tooltip remains, and now also covers retrieve errors that previously showed "unknown error"). A visible results banner shares one computed "N succeeded, X failed" summary with the assistive live region. Closes #2029
paustint
force-pushed
the
chore/wcag-a11y-scanning
branch
from
September 2, 2026 13:30
cbfa1ca to
77f52f7
Compare
paustint
marked this pull request as draft
September 5, 2026 14:22
paustint
force-pushed
the
chore/wcag-a11y-scanning
branch
8 times, most recently
from
September 14, 2026 01:14
2fcaa09 to
fcb46e4
Compare
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
TODO rebase/re-do PR after dependent PR merges. rebases on target pr caused this one to become out of date.
Fixes all four follow-ups from the deploy review modal (Automation Control → Review Changes). Branched from
chore/wcag-a11y-scanningper the issue note (shared files); retarget tomainafter #2011 merges.Changes
Deployingalong with everything else when the deploy started, butdeployMetadatafilters out rows with aretrieveError(in both the tooling-API and metadata-API paths), so they never received a result and sat on a spinner forever. They now keep theirErrorstate.save-errorred row background viarowClass, in addition to the icon + text.getWrappedTextRowHeight, same pattern as the apex-test-runner Message column). The status tooltip and copy-to-clipboard remain as secondary affordances, and all three now read from one sharedgetDeploymentItemErrorMessage— which also falls back to retrieve errors, so retrieve-failed rows no longer show "An unknown error has occurred" while holding a real message.Also marks the findings-doc entry resolved and adds unit tests for the error-message extraction (deploy-error join, retrieve-error fallback, generic fallback, non-error rows).
Closes #2029