TextFieldについて

React Ariaの実装読むぞ


目次
  1. とは
  2. 使用例
  3. 本題
    1. フィールドの a11y とバリデーション
    2. aria-multiline
    3. inputMode
  4. まとめ
Warn

この記事は他サイトから移行したものです。

Note

この記事は React Aria の実装読むぞ - Qiita Advent Calendar 2024 の 4 日目の記事です。

こんにちは、フロントエンドエンジニアの mehm8128 です。 今日は TextField について書いていきます。

useTextField とは #

テキストの入力欄を作るための hook です。

使用例 #

ドキュメントからそのまま取ってきています。

function TextField(props: AriaTextFieldProps) {
  let { label } = props;
  let ref = React.useRef(null);
  let {
    labelProps,
    inputProps,
    descriptionProps,
    errorMessageProps,
    isInvalid,
    validationErrors,
  } = useTextField(props, ref);

  return (
    <div style={{ display: "flex", flexDirection: "column", width: 200 }}>
      <label {...labelProps}>{label}</label>
      <input {...inputProps} ref={ref} />
      {props.description && (
        <div {...descriptionProps} style={{ fontSize: 12 }}>
          {props.description}
        </div>
      )}
      {isInvalid && (
        <div {...errorMessageProps} style={{ color: "red", fontSize: 12 }}>
          {validationErrors.join(" ")}
        </div>
      )}
    </div>
  );
}

本題 #

WAI-ARIA はこちらです。

フィールドの a11y とバリデーション #

React Aria ではフィールド系のコンポーネントにはラベルに加えて説明文とエラーメッセージを紐づけることができます。 説明文を入れている要素にはdescriptionPropsを、エラーメッセージを入れている要素にはerrorMessagePropsを渡すことで、useFieldによって生成されている id を用いてaria-describedbyでテキストフィールドに紐づけることができます。 また、 React Hook Form などのライブラリと一緒に使うこともでき、そのバリデーション結果のエラーメッセージを、errorMessagePropsを渡している要素に入れることで紐づけます。

エラーメッセージにはaria-errormessageが使われることもありますが、aria-errormessageは現状スクリーンリーダーによっては上手く読み上げられないことがあるため、用いられていないようです。

aria-multiline #

WAI-ARIA を見てみます。

NOTE の欄には、1 行のテキストフィールドであるinput要素は Enter キーを押すとデフォルトではフォームが送信されるけど、複数行であるtextarea要素は改行されるだけなので、それを区別するためにaria-multilineがあるという話が書かれています。 aria-multilinetrueにするとスクリーンリーダーでは「複数行」という読み上げがされるので、それによって Enter を押したときにすぐに送信されてしまうか、改行されるだけかという判断がつく、という話だと理解しました。 ただ、複数行のときにはちゃんとtextarea要素を使っていれば自動でaria-multiline="true"の挙動になってくれるので、RTE を触るときなどに気にすることになりそうです。React Aria のuseTextfieldでは下に載せたコードの部分でinputtextarea要素のみを受け入れるようにしているので、実装に明示的に含まれてはいませんでした。

inputMode #

input要素にはtype属性があり、単純な TextField ならtype="text"、チェックボックスならtype="checkbox"、数値ならtype="number"など、用途に応じて指定することで入力フィールドの見た目や機能が変わったり、モバイル時に仮想キーボードが変化したりします。例えばtype="number"だと、数字(と一部の記号)だけの仮想キーボードになります。スマホでロック画面解除のパスワードを入力するような画面を想像してもらうと分かりやすいと思います。

しかし、例えば郵便番号は数字だから数字を入力しやすいようにtype="number"にしよう、というのは間違いです。デフォルトでtype="number"には+/-ボタンのスピナーがつくのですが、郵便番号は数字を増減させて操作するタイプのものではないからです。

こういう場合に、type属性ではなくてinputModeを利用します。 inputModeは、入力フィールドの見た目や機能を変えずに、仮想キーボードのみを変化させるためのものです。例えばtype="number"のときに表示される仮想キーボードと同じものを表示させるには、inputMode="numeric"を指定します。つまり、郵便番号の場合にはtype="text"inputMode="numeric"を指定するのが適切だと考えられます。 それ以外にもtype="email"のときに出てくる仮想キーボードはinputMode="email"で表示できるなど、いくつかの種類があります。詳しくは下のリンクから HTML Standard をご覧ください。 ちなみにinputModeは明日の記事でも登場します。

まとめ #

明日の担当は @mehm8128 さんで、 NumberField についての記事です。お楽しみにー