Calendarについて

React Ariaの実装読むぞ


目次
  1. 使用例
  2. 本題
    1. i18n
    2. 読み上げ
      1. useCalendarGrid
      2. useCalendarCell
  3. まとめ
Warn

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

Note

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

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

使用例 #

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

function Calendar(props) {
  let { locale } = useLocale();
  let state = useCalendarState({
    ...props,
    locale,
    createCalendar,
  });

  let { calendarProps, prevButtonProps, nextButtonProps, title } = useCalendar(
    props,
    state
  );

  return (
    <div {...calendarProps} className="calendar">
      <div className="header">
        <h2>{title}</h2>
        <Button {...prevButtonProps}>&lt;</Button>
        <Button {...nextButtonProps}>&gt;</Button>
      </div>
      <CalendarGrid state={state} />
    </div>
  );
}

本題 #

i18n #

再び i18n です。 React Aria の Calendar には 2 種類あり、普通に選択する Calendar と、日付の範囲を選択する Calendar です。後者はホテル予約とかで見るやつです。 範囲選択でも、選択した範囲を示すのに適切なフォーマットにしたテキストをアナウンスする必要があるので、i18n が行われています。

そこで登場するのがuseDateFormatterから得られるDateFormatterオブジェクトのformatRangeメソッドです。これは内部でIntl.DateTimeFormatformatRangeメソッドを使っています。

Intl.DateTimeFormatformatRangeメソッドについてはこちらの記事をご覧ください。 https://zenn.dev/sajikix/articles/intl-advent-calendar-24-07#formatrange()-%E3%81%A8-formatrangetoparts()

日付の演算は独自のCalendarDateオブジェクトを利用するのですが、フォーマットについては Intl のメソッドを使う関係上、一度Dateオブジェクトに変換してから渡すような実装になっているようです。

読み上げ #

Calendar の操作について、補足説明的な読み上げがされたり、逆に冗長な読み上げを防ぐためにスキップされたりしています。

useCalendarGrid #

Calendar のヘッダー(曜日の部分)は、スクリーンリーダーによる読み上げがされないようにしています。これによって、日付部分に素早く移動することができるようにしています。代わりに、各日付のボタンにフォーカスしたタイミングで「2024 年 12 月 23 日月曜日」のように、日付と一緒に曜日が読み上げられるようになっています。

useCalendarCell #

useRangeCalendarで範囲選択が可能になっているとき、操作についての補足説明が読み上げられます。 state.anchorDateとは、選択されている開始日時です。開始日時が選択されているとき、他の日付にフォーカスすると日付情報と共に「クリックして日付範囲の選択を終了」と読み上げられます。 逆に、まだ開始日時を選択していないときには「クリックして日付範囲の選択を開始」と読み上げられます。 これらの説明はaria-descriptionとして付与されます。

ただ、スクリーンリーダーユーザー向けの読み上げなので、「クリックして」ではなくてキーボード操作を想定した読み上げにした方が良いのではと思いました(useNumberField のときのような翻訳ミスではなくて、en-USでも"Click to start selecting date range"などとなっています)。

まとめ #

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