0
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?

【react-tooltip】FontAwesomeIcon に data-tooltip-id を指定しない(一部解説有り)

Posted at

発生した現象

FontAwesomeIcon にツールチップを表示させるために data-tooltip-iddata-tooltip-content を指定したところ、アイコンがフォーカス可能になってしまい、また、Blocked aria-hidden on an element because its descendant retained focus というエラーが発生してしまいました。

ブラウザは Chrome 138 を使用しました。Firefox 141 ではこのような現象は発生しませんでした。

image.png

image.png

このように、フォーカス可能になり、また、開発者ツールに警告が表示されています。

App.tsx
import React from 'react';
import { Tooltip } from 'react-tooltip';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faUser } from "@fortawesome/free-solid-svg-icons";

export function App() {
  return (
    <div>
      This is icon:
      <FontAwesomeIcon
        data-tooltip-id="my-tooltip"
        data-tooltip-content="Hello!"
        icon={faUser}
      />
      <Tooltip id="my-tooltip" />
    </div>);
}

解決策

  • FontAwesomeIcon を span で囲む
  • span 側に data-tooltip-iddata-tooltip-content を指定する
App.tsx
import React from 'react';
import { Tooltip } from 'react-tooltip';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faUser } from "@fortawesome/free-solid-svg-icons";

export function App() {
  return (
    <div>
      This is icon:
      <span
        data-tooltip-id="my-tooltip"
        data-tooltip-content="Hello!"
      >
        <FontAwesomeIcon
          icon={faUser}
        />
      </span>
      <Tooltip id="my-tooltip" />
    </div>);
}

直接の原因(詳しく知りたい人向け)

なぜこのような問題が発生してしまったのでしょうか。詳しく見ていきたいと思います。

FontAwesomeIcon を配置すると、svg 要素に以下の属性が指定されます。

<svg
  aria-hidden="true"
  focusable="false"
  >

まず、 focusable="false" によって画像がフォーカス可能ではないということが明示されます。また、 aria-hidden="true" が指定されることで、スクリーンリーダーなどによる読み上げが避けられます。装飾目的でアイコンを使用する場合は、このようにすることで、冗長な読み上げを回避できるようになります。

しかし、その svg 要素対して react-tooltipaddEventListener('focus', ...) を呼び出すと、Chrome がその要素をフォーカス可能であると認識してしまいます。

// svg 要素に focus イベントリスナを追加
svgElement.addEventListener('focus', someHandler);

これによって、矛盾が発生し、ブラウザは警告を出すようになります。

具体的には以下のようなコードで現象を再現することができます。

App.tsx
import { useRef, useEffect } from "react";

export function App() {
  const ref = useRef();

  useEffect(() => {
    if (ref.current != null) {
      ref.current.addEventListener('focus', () => {
        console.log("focus!");
      });
    }
  }, [ref]);

  return (
    <div>
      This is svg:
      <svg
        ref={ref}
        viewBox="0 0 100 100"
        aria-hidden="true"
      >
        <path fill="red" d="M10 10L90 10L90 90L10 90" />
      </svg>
    </div>
  );
}

Chorome でこのコードを実行し、SVG 画像をクリックすると、以下のようなエラーが発生します。

image.png

Blocked aria-hidden on an element because its descendant retained focus.
The 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.
Element with focus: <svg>
Ancestor with aria-hidden: <svg>

では、なぜ svg の場合だけ addEventListener でフォーカス可能になるのか【未解決】

では、なぜフォーカス可能になったのでしょうか。

たとえば、 div などの要素でも、 tabIndex= を明示的に指定すればフォーカス可能になります。しかし、Chrome 138 において、svg に対してはそのようなことをしなくても、 addEventListener('focus', ...) を指定するだけでフォーカス可能になりました。これはなぜなのでしょうか。

この点については調べましたがよく分かりませんでした! そういうブラウザの仕様なのかもしれません。いかがでしたか?

Which HTML elements can receive focus?

There isn't a definite list, it's up to the browser.

0
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
0
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?