如何移除react-modal组件的聚焦以解决无障碍检测告警
问题原因
你收到的ANDI告警是因为react-modal默认会给模态框的content根元素自动添加tabIndex="-1"属性,且打开模态框时会自动聚焦到这个元素。该元素属于可聚焦但不会被键盘Tab键遍历到的元素,因此触发了无障碍规则告警。你之前添加的属性没有生效,是因为react-modal内部会强制覆盖根元素的相关属性。
解决方法
通过react-modal自带的配置项就能直接解决,修改你的Modal组件传参即可:
- 禁用打开模态框时自动聚焦根元素的逻辑
- 移除根元素默认的
tabIndex属性,让其本身不可聚焦 - 可选优化:补充关闭按钮的无障碍属性,避免其他无障碍告警
修改后的核心代码如下:
import Modal from 'react-modal'; import React, { useState, useEffect, useCallback } from 'react'; type TProps = { isModalOpen: boolean; modalContent?: any; children?: any; toggleModal: () => void; render?: () => any; allowOverflow?: boolean; width?: string; height?: string; maxHeight?: string; maxWidth?: string; className?: string; }; export const CustomModal = (props:TProps) => { const [isModalOpen, toggleModal] = useState<boolean>(props.isModalOpen); const defaultStyle = { content: { top : '50%', left : '50%', right : 'auto', bottom : 'auto', marginRight : '-40%', transform : 'translate(calc(-37% - 0.5px), calc(-40% - 0.1px))', width : props.width || 'fit-content', maxWidth : props.maxWidth || '600px', height : props.height || '97%', boxShadow : '0px -1px 16px -9px rgba(0,0,0,0.4)', padding : '0px', inset : '40.3% auto auto 50%', overflow : `${props.allowOverflow ? 'visible' : 'auto'}`, maxHeight : props.maxHeight || '97%' } }; const handleExit = useCallback(() => { toggleModal(false); props.toggleModal() }, [props]) // 关闭按钮支持键盘触发 const handleCloseKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleExit(); } }, [handleExit]) useEffect(() => { toggleModal(props.isModalOpen); }, [props.isModalOpen]) // 避免每次渲染重复执行setAppElement useEffect(() => { Modal.setAppElement(document.body) }, []) return ( <React.Fragment> <Modal style={defaultStyle} isOpen={isModalOpen} onRequestClose={handleExit} shouldCloseOnOverlayClick={true} {/* 新增以下两个配置解决告警 */} shouldFocusAfterOpen={false} contentElementProps={{ tabIndex: undefined }} {/* 保留关闭时焦点回退到触发元素的逻辑,符合无障碍规范 */} shouldReturnFocusAfterClose={true} > <div className={`content-container ${props.className ? props.className : ''}`} data-testid={`customModalContent`}> <div className='exit-button-container'> <i className='fas fa-times' role="button" tabIndex={0} onKeyDown={handleCloseKeyDown} data-testid={`customModalCloseButton`} onClick={handleExit}/> </div> {(props.isModalOpen || isModalOpen) && props.modalContent && React.createElement(props.modalContent)} {(props.isModalOpen || isModalOpen) && props.render && props.render()} {props.children || <></>} </div> </Modal> </React.Fragment> ) }
配置说明
shouldFocusAfterOpen={false}:禁用react-modal默认的打开模态框时自动聚焦根元素的逻辑,你可以自行设置模态框内部第一个可交互元素为初始聚焦点,符合无障碍规范contentElementProps={{ tabIndex: undefined }}:覆盖react-modal默认给content根元素添加的tabIndex="-1"属性,让根元素本身不可聚焦,不会再触发ANDI的告警
内容的提问来源于stack exchange,提问作者devjake
相关产品推荐
相关产品推荐

