feat(a11y): semantic HTML, accessible buttons, and payment-element integration - #1654
feat(a11y): semantic HTML, accessible buttons, and payment-element integration#1654AbhishekChorotiya wants to merge 1 commit into
Conversation
Code Review Findings[blocking] Bare silent catch in message handlerThe Location: try {
let dict = ev.data->safeParse->getDictFromJson
// ... message handling
} catch {
| _ => ()
}Per the team's guidelines, bare Suggested fix: catch {
| ex =>
logger.error("Failed to handle fullscreen iframe message", ex)
// Or propagate to component error state
}[should-fix] Verify focus restoration targetThe Location: Ensure [should-fix] v1/v2 parity check requiredThis PR modifies payment method components (CardPayment, SavedMethods, WalletConnectButton, etc.). If the v2 API counterparts exist (e.g., CardPaymentV2.res, SavedMethodsV2.res), ensure equivalent accessibility changes are applied there for API parity. Verify the following pairs are updated consistently:
[nit] shared-code/sdk-utils promotion opportunityThe new Check imports in AccessibilityUtils.res for any web-only dependencies before deciding. |
|
The let handle = (ev: Window.event) => {
try {
let dict = ev.data->safeParse->getDictFromJson
switch dict->Dict.get("fullScreenIframeMounted")->Option.flatMap(JSON.Decode.bool) {
| Some(false) =>
triggerRef.current->Nullable.toOption->Option.forEach(el => el->AccessibilityUtils.focus)
| _ => ()
}
} catch {
| _ => ()
}
}Without origin checking, this could allow malicious cross-origin messages to trigger focus behavior. While the data handling appears safe (only checking a specific boolean field), please verify:
Consider adding origin validation matching patterns used elsewhere in the codebase for |
|
💡 Tab-index management in AddBankAccount.res The onKeyDown={ev => {
if ev->ReactEvent.Keyboard.key === "Enter" || ev->ReactEvent.Keyboard.key === " " {
openModal()
}
}}Also verify the |
95e8464 to
4b11bc9
Compare
a3451f7 to
5b281e4
Compare
…tegration Payment area as a labelled form landmark (role=form), heading hierarchy, labels; convert clickable div/span/icon controls into accessible buttons (Enter+Space) via the shared AccessibilityUtils.onActivateKeyDown helper (added here); centralize Enter+Space in SwitchViewButton; wire announcer mount + iframe focus-delegation into PaymentElement. ARIA labels localized (goBackLabel, savePaymentMethodLabel, selectCardLabel, doneLabel, etc.); announced errors via LiveError.
5b281e4 to
129445d
Compare
4b11bc9 to
b1de9da
Compare
Review SummaryPR: #1654 - feat(a11y): semantic HTML, accessible buttons, and payment-element integration Findings
No blocking issues. The semantic HTML improvements enhance accessibility across payment components. |
|
🚨 Security concern - Unvalidated postMessage origin The accessibility implementation uses Fix: Derive Several event listeners are registered without corresponding cleanup:
Fix: Ensure all useEffect(() => {
let handler = ...
Window.addEventListener("message", handler)
Some(() => Window.removeEventListener("message", handler))
}) |
|
🚨 Bare catch block swallows all errors silently In // Current (bad)
} catch {
| _ => ()
}
// Better - at minimum log the error
} catch {
| ex => loggerState.setLogError(~value=ex->Utils.formatException, ~eventName=MESSAGE_HANDLER_ERROR)
}If this is intentional (e.g., cross-origin noise filtering), add a comment explaining why errors are suppressed. |
Type of Change
Description
This PR completes the accessibility integration work across payment methods and saved-method experiences. It tightens accessible names, removes noisy action wording, improves saved-method semantics, and centralizes repeated wallet and bank-account labelling logic in the shared accessibility helpers.
The user impact is cleaner announcements, more meaningful saved-method labels, clearer wallet button names, and a more consistent assistive-technology experience across the full payment element.
This is the final PR in the split accessibility stack. It should be reviewed after the previous four PRs because it relies on the shared form-control, focus, live-region, and iframe accessibility foundations.
Closes #1653
How did you test it?
Validated as part of the completed accessibility stack. The checks cover the combined flow after all stacked PRs are applied, and the saved-method/new-method flows were checked through the local payment-element accessibility smoke flow.
npm run re:buildon the completed accessibility stack.npm run test:hookson the completed accessibility stack.npm run buildon the completed accessibility stack.Checklist
npm run re:build