1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MUIのPopoverをonMouseLeaveで閉じるようにしたら高速開閉し続けてしまう問題の解決方法

Last updated at Posted at 2024-07-31

現象

アイコンにマウスオンでPopoverを表示、マウスを外したときに非表示にしたかったので、このように実装した。

結果、高速でPopoverが無限に開閉し続け、表示されない状態になった。

補足:
WebComponentとして実装しており、親コンポーネント側にPopoverが出てスタイルが無効化されるのを防ぐため、div要素にrefを使用しています。

const MyComponent: React.FC = () => {
  const popoverRef = useRef<HTMLDivElement>(null);
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const handleClose = (): void => {
    setIsOpen(false);
  };
  const handleOpen = (): void => {
    setIsOpen(true);
  };

  return (
    <div ref={popoverRef}>
      <PsychologyIcon 
        onMouseOver={handleOpen}
        onMouseLeave={handleClose}
      />
      <Popover
        open={isOpen}
        anchorEl={popoverRef.current}
        onClose={handleClose}
        container={() => {
          return popoverRef.current;
        }}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'left',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}>
        <div style={{ padding: '5px' }}>Popoverに表示するテキスト</div>
      </Popover>
    </div>
  )

原因と対応

1. フォーカス可能な要素にaria-hidden="true"を設定してはならない

コンソールを見ると、このようなエラーが出ていた。

Blocked aria-hidden on a <div> element because the element that just received focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden. 

MDN Web docs にも警告が書いてあるとおり、aria-hidden="true"をフォーカス要素に使用することはできません。
Popoverコンポーネントが動作するときに自動でaria-hidden="true"が挿入されますが、今回、上述の事情によりdivの中に挿入していたので、このようなエラーが発生したようです。

解決策として、inert属性を使う方法もあるようですが、今回は、Popoverコンポーネントが表示されたときに自動的にフォーカスを取得しないように、disableAutoFocusdisableEnforceFocusを追加しました。

      <Popover
        open={isOpen}
        ...
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        disableAutoFocus // Popoverが表示される際にフォーカスを自動的に取得しないようにする
        disableEnforceFocus // フォーカスの強制を無効にする
      >
        <div style={{ padding: '5px' }}>Popoverに表示するテキスト</div>
      </Popover>

2. マウスイベントがPopover上で発生してしまっている

さて、1の対応でコンソールのエラーは表示されなくなりましたが、Popoverが高速で開閉してしまう問題は解決しませんでした。
マウスイベントがPopover上で発生しないように、sx={{ pointerEvents: 'none' }}を追加したところ、正常に表示されるようになりました。

      <Popover
        open={isOpen}
        ...
        transformOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        disableAutoFocus
        disableEnforceFocus
        sx={{ pointerEvents: 'none' }}  // Popover上でマウスイベントが発生しないようにする
      >
        <div style={{ padding: '5px' }}>Popoverに表示するテキスト</div>
      </Popover>
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?