Summary
PaymentConsentModal.tsx:46-57 calls dialog.showModal() then immediately calls acceptButtonRef.current?.focus() synchronously. Firefox doesn't guarantee the dialog is focusable until the next frame. This is the same shape as the Firefox CI regression that caused revert 3e67772.
Additionally, the component manages show/hide via two conflicting mechanisms: it returns null when !showModal AND imperatively calls dialog.close() in a useEffect. When showModal flips false, the cleanup of the cancel-event-listener effect can be skipped, leaving orphaned event listeners on the dialog element.
Files
src/components/payment/PaymentConsentModal/PaymentConsentModal.tsx:46-57 — focus-after-showModal timing
src/components/payment/PaymentConsentModal/PaymentConsentModal.tsx:50-86 — imperative/declarative hybrid
Fix
- Wrap focus call in
requestAnimationFrame(() => acceptButtonRef.current?.focus())
- Pick ONE mode: either keep dialog mounted with
open attribute (declarative), OR remove the return null and let dialog stay mounted-but-closed (imperative). Don't mix.
Why this matters
Firefox revert 3e67772 already happened for this exact symptom. The fix is the same shape; just hasn't been applied here.
Related
- Code review findings: CR-018, CR-019
- Revert: 3e67772
Summary
PaymentConsentModal.tsx:46-57callsdialog.showModal()then immediately callsacceptButtonRef.current?.focus()synchronously. Firefox doesn't guarantee the dialog is focusable until the next frame. This is the same shape as the Firefox CI regression that caused revert 3e67772.Additionally, the component manages show/hide via two conflicting mechanisms: it returns
nullwhen!showModalAND imperatively callsdialog.close()in a useEffect. WhenshowModalflips false, the cleanup of the cancel-event-listener effect can be skipped, leaving orphaned event listeners on the dialog element.Files
src/components/payment/PaymentConsentModal/PaymentConsentModal.tsx:46-57— focus-after-showModal timingsrc/components/payment/PaymentConsentModal/PaymentConsentModal.tsx:50-86— imperative/declarative hybridFix
requestAnimationFrame(() => acceptButtonRef.current?.focus())openattribute (declarative), OR remove thereturn nulland let dialog stay mounted-but-closed (imperative). Don't mix.Why this matters
Firefox revert 3e67772 already happened for this exact symptom. The fix is the same shape; just hasn't been applied here.
Related