React を使用してアクセス可能な ARIA ラベルを DayPicker に簡単に追加する方法

ARIA

ARIA ラベルを使用して React Calendar コンポーネントにアクセスできるようにする

アクセシビリティは最新の Web 開発の重要な側面であり、アプリケーションがすべてのユーザーにとって包括的であることを保証します。 React プロジェクトでは、次のようなコンポーネントを使用します。 カレンダー UI を表示するために、スクリーン リーダーがアクセスできるようにしようとすると、特有の課題が生じる可能性があります。

最近、動的に追加する必要があるプロジェクトに取り組みました。 の個々の日の要素に 成分。目標は、毎日の状態に基づいて、「選択された日付: 2024 年 1 月 1 日」または「利用できない日付: 2024 年 1 月 2 日」などの意味のある情報をユーザーに提供することでした。

最初は、次のような標準的なソリューションを試しました または 、しかしすぐに気づきました。 ライブラリにはそのような小道具に対するサポートが組み込まれていませんでした。次に直感的に思ったのは、レンダリング後の DOM を操作することでした。 useRef そして 。このアプローチは機能的ではありますが、脆弱であり、クラス名に大きく依存しているように感じられました。 😕

この記事では、ARIA ラベルを動的に追加するためのより堅牢なソリューションについて説明します。 日々。選択された状態、無効な状態、または使用不可の状態に対処しているかどうかに関係なく、カレンダーがアクセス可能でスクリーン リーダーに優しい状態を維持できるようにします。飛び込んでみましょう! 🚀

指示 使用例
useRef const CalendarRef = useRef(null); DayPicker コンポーネントの DOM に直接アクセスして操作するための変更可能な参照オブジェクトを作成します。
querySelectorAll CalendarRef.current.querySelectorAll(".rdp-day"); に一致するすべての要素を取得します。 さらに操作するには、DayPicker コンポーネント内のクラスを使用します。
setAttribute day.setAttribute("aria-label", ariaLabel); を動的に追加または変更します。 スクリーン リーダーにアクセシビリティを提供する属性。
components コンポーネント={{ 日: renderDay }} カスタム関数を挿入して毎日のデフォルトのレンダリングを置き換え、ARIA ラベルのカスタマイズを可能にします。
modifiers modifiers={{ 限定: CalendarDates.limited }} DayPicker 内で特定の日の状態 (制限、利用不可など) を定義し、日を視覚的および機能的に区別します。
aria-label
曜日にセマンティックな説明を追加し、スクリーン リーダーなどの支援技術で理解しやすく、ナビゲートしやすくします。
getByLabelText screen.getByLabelText("選択された日付: 1 月 1 日"); 単体テストでは、要素に基づいてクエリを実行します。 属性を使用して、アクセシビリティ ラベルが正しく適用されていることを確認します。
useEffect useEffect(() => {...}, [calendarDates]); DayPicker のレンダリング後にロジックを実行し、カレンダーの状態が変化したときに ARIA ラベルが動的に追加されるようにします。
modifiersStyles modifiersStyles={{ 限定: 限定スタイル }} カスタム スタイルを特定の日修飾子に適用し、ユーザーにとって状態が視覚的に区別できるようにします。
generateAriaLabel generateAriaLabel(日, 修飾子) 1 日の状態に基づいてコンテキスト固有の ARIA ラベルを動的に生成するユーティリティ関数。

DayPicker の動的 ARIA ラベル: 詳細ガイド

を構築するとき React で DayPicker ライブラリを使用する場合、スクリーン リーダーのアクセシビリティを確保するのは難しい場合があります。主な課題は、動的に追加することにあります。 したがって、「選択」、「無効」、または「使用不可」などの状態を伝達します。これを解決するために、レンダリング後の DOM 操作とカスタム レンダリング関数という 2 つのアプローチを採用しました。これらのソリューションがどのように機能するのか、そしてアクセシビリティを実現するために使用される主要なコンポーネントを詳しく見てみましょう。 🗓️

最初の解決策は次のものに依存します React を使用する そして 。 `useRef` を使用して DayPicker コンポーネントへの参照を作成すると、レンダリングされた DOM ノードにアクセスできます。 「useEffect」フック内で、「querySelectorAll」を使用して終日要素 (「.rdp-day」) をクエリします。毎日、クラス名をチェックしてその状態を判断します。日に「rdp-day_selected」クラスがある場合は、「選択された日付: 2024 年 1 月 1 日」のような ARIA ラベルを追加します。このメソッドにより、カレンダーの状態が変化するたびに ARIA ラベルが動的に更新されます。

2 番目のソリューションでは、よりクリーンで React に優しいアプローチを採用しています。 。 DayPicker では、「components」プロパティを介してカスタム コンポーネントを使用して、日要素のレンダリングをオーバーライドします。カスタム関数は、毎日とその状態修飾子をパラメーターとして受け取ります。ヘルパー関数を使用して、毎日の状態 (選択、無効など) に基づいて ARIA ラベルを動的に生成します。たとえば、「利用不可日: 2024 年 1 月 2 日」は、無効としてマークされた日に割り当てられます。このアプローチにより、DOM の操作が回避され、ソリューションの保守性が向上します。

どちらの方法にも長所と短所があります。レンダリング後の DOM 操作により、レンダリングされた出力を制御できるようになりますが、クラス名に大きく依存しており、ライブラリの更新によって変更される可能性があります。一方、「components」プロパティを使用すると、React の宣言パラダイムとよりよく調和し、コードがよりクリーンになり、デバッグが容易になります。最終的に、これらのアプローチのどちらを選択するかは、プロジェクトの要件とライブラリの制約によって決まります。いずれの場合でも、最終的にはスクリーン リーダーを使用しているユーザーがカレンダーにアクセスできるようになり、すべてのユーザーの使いやすさが向上します。 🌟

ARIA ラベルを React DayPicker コンポーネントに動的に追加する方法

React、JavaScript、最適化されたメソッドを使用した動的な ARIA ラベル管理

// Solution 1: Adding ARIA labels with post-render DOM Manipulation
import React, { useEffect, useRef } from "react";
import { DayPicker } from "react-day-picker";
import "react-day-picker/dist/style.css";

const AccessibleDayPicker = ({ calendarDates, startDate, endDate }) => {
  const calendarRef = useRef(null);

  useEffect(() => {
    if (calendarRef.current) {
      const days = calendarRef.current.querySelectorAll(".rdp-day");
      days.forEach((day) => {
        const date = day.getAttribute("aria-label");
        let ariaLabel = date;
        if (day.classList.contains("rdp-day_selected")) {
          ariaLabel = `Selected date: ${date}`;
        } else if (day.classList.contains("rdp-day_disabled")) {
          ariaLabel = `${date} is not available for selection.`;
        }
        day.setAttribute("aria-label", ariaLabel || date);
      });
    }
  }, [calendarDates]);

  return (
    <div ref={calendarRef}>
      <DayPicker
        mode="single"
        selected={calendarDates.selected}
        onDayClick={() => {}}
        showOutsideDays
        disabled={{ before: startDate, after: endDate }}
        modifiers={{
          limited: calendarDates.limited,
          unavailable: calendarDates.unavailable,
        }}
      />
    </div>
  );
};

export default AccessibleDayPicker;

DayPicker での ARIA ラベルのカスタム ラッパーの実装

機能コンポーネントを使用した React ベースの ARIA ラベルのカスタマイズ

// Solution 2: Using a Custom Wrapper to Assign ARIA Labels
import React from "react";
import { DayPicker } from "react-day-picker";

const CustomDayPicker = ({ calendarDates, startDate, endDate }) => {
  const generateAriaLabel = (date, modifiers) => {
    if (modifiers.selected) return `Selected date: ${date.toDateString()}`;
    if (modifiers.disabled) return `${date.toDateString()} is not available.`;
    return date.toDateString();
  };

  const renderDay = (day, modifiers) => (
    <div aria-label={generateAriaLabel(day, modifiers)}>
      {day.getDate()}
    </div>
  );

  return (
    <DayPicker
      mode="single"
      selected={calendarDates.selected}
      disabled={{ before: startDate, after: endDate }}
      modifiers={{
        limited: calendarDates.limited,
        unavailable: calendarDates.unavailable,
      }}
      components={{ Day: renderDay }}
    />
  );
};

export default CustomDayPicker;

ARIA ラベル割り当ての単体テスト

ARIA ラベルの整合性を確保するための Jest および React テスト ライブラリ

// Solution 3: Unit tests to validate ARIA label assignment
import React from "react";
import { render, screen } from "@testing-library/react";
import AccessibleDayPicker from "./AccessibleDayPicker";
import "@testing-library/jest-dom";

describe("AccessibleDayPicker ARIA labels", () => {
  test("adds ARIA labels for selected and disabled days", () => {
    const calendarDates = {
      selected: new Date(2024, 0, 1),
      unavailable: [new Date(2024, 0, 2)],
    };
    render(<AccessibleDayPicker calendarDates={calendarDates} />);

    const selectedDay = screen.getByLabelText("Selected date: Monday, January 1, 2024");
    expect(selectedDay).toBeInTheDocument();

    const unavailableDay = screen.getByLabelText("Monday, January 2, 2024 is not available.");
    expect(unavailableDay).toBeInTheDocument();
  });
});

React DayPicker でスクリーン リーダーのアクセシビリティを確保する

追加 アクセシビリティにとって動的は重要ですが、React DayPicker で包括的なエクスペリエンスを作成するにはそれだけではありません。見落とされている側面の 1 つは、 そして集中管理。スクリーン リーダーのユーザーは、カレンダーなどの対話型コンポーネントを操作するためにキーボード入力に大きく依存しています。 DayPicker は、そのままの状態で基本的なキーボード ナビゲーションをサポートしていますが、ARIA ラベルと合わせてカスタマイズすると、より直感的に操作できるようになります。

検討すべきもう 1 つの領域は、国際化 (i18n) サポートです。プロジェクトがさまざまな地域のユーザーを対象としている場合、ARIA ラベルはローカライズされた日付形式と言語を反映する必要があります。たとえば、フランスのユーザーには「2024 年 1 月 1 日」ではなく「2024 年 1 月 1 日」と聞こえるはずです。 「react-intl」やネイティブ JavaScript の「Intl.DateTimeFormat」などのライブラリは、さまざまなロケールのスクリーン リーダー用にこれらのラベルを動的にフォーマットするのに役立ちます。

最後に、その日の現在の焦点や状態を視覚的に示すことで、アクセシビリティをさらに向上させることができます。カスタムを組み合わせる `aria-current="date"` のような ARIA 属性を使用すると、視覚的および意味的なアクセシビリティの両方が保証されます。たとえば、スクリーン リーダーにコンテキストを提供しながら、今日の日付を視覚的に強調表示できます。このレベルの洗練により、DayPicker が機能するだけでなく、すべてのユーザーにとって包括的であるという点でも優れたものになります。 🎯

  1. とは何ですか DayPicker で使用されますか?
  2. ARIA ラベルはスクリーン リーダーにアクセス可能な説明を提供し、ユーザーが「選択済み」や「無効」などのその日の状態を理解できるようにします。
  3. 動的に追加するにはどうすればよいですか DOM操作を使わずに?
  4. DayPicker の使用 prop を使用すると、日のレンダリングをカスタマイズし、ARIA ラベルを直接追加できます。
  5. ローカライズできますか 海外ユーザー向け?
  6. はい、次を使用して日付を書式設定できます ARIA ラベルにローカライズされた日付形式が反映されていることを確認します。
  7. どうすれば改善できますか ARIAレーベルと並んで?
  8. DayPicker はキーボード ナビゲーションをネイティブにサポートしていますが、カスタムを追加しています 使いやすさとアクセシビリティの両方が向上します。
  9. 動的を追加するとパフォーマンスにコストがかかりますか? ?
  10. React の状態とプロパティを使用して ARIA 属性を適切に実装すると、パフォーマンスのオーバーヘッドが最小限に抑えられます。

追加 DayPicker に追加すると、支援技術の個々の日の要素の状態が記述されるため、アクセシビリティが向上します。スクリーン リーダーに依存するユーザーにシームレスなエクスペリエンスを提供し、「選択済み」や「利用不可」などの主要な状態を明確にします。 ✅

React フックとカスタム レンダリング アプローチを組み合わせることで、効果的で保守可能なソリューションを実現します。直接 DOM 操作を使用するか、宣言型 props を使用するかにかかわらず、すべてのユーザーがアクセスできる包括的なカレンダー インターフェイスを提供することに重点が置かれています。 🌟

  1. 公式で詳しく解説 コンポーネントの機能と修飾子を調べるためのライブラリのドキュメント。詳細については、こちらをご覧ください React-Day-Picker ドキュメント
  2. アクセシビリティの重要性と ARIA のベスト プラクティスについて、 。 ARIA 属性に関する詳細なガイダンスは、次の URL で参照できます。 MDN ARIA ドキュメント
  3. Web アクセシビリティとスクリーン リーダーの互換性を向上させるための概念を検討します。 で見つけることができます。 WebAIM: Web アクセシビリティを念頭に置いた