From 0766162e666539d02757fb036b2cc7f7660c13f1 Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Fri, 3 Jan 2025 11:50:17 -0800 Subject: [PATCH 1/8] add aria labels to sinusoid function graph --- packages/perseus/src/strings.ts | 22 +++++++++++++++ .../interactive-graphs/graphs/sinusoid.tsx | 28 +++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/perseus/src/strings.ts b/packages/perseus/src/strings.ts index 2443644c8c..8076debf63 100644 --- a/packages/perseus/src/strings.ts +++ b/packages/perseus/src/strings.ts @@ -258,6 +258,9 @@ export type PerseusStrings = { tsX: string; tsY: string; }) => string; + srSinusoidGraphAriaLabel: string; + srSinusoidExtremumPoint: ({x, y}: {x: string; y: string}) => string; + srSinusoidMidlineIntersection: ({x, y}: {x: string; y: string}) => string; // The above strings are used for interactive graph SR descriptions. }; @@ -550,6 +553,21 @@ export const strings: { message: "The angle measure is %(angleMeasure)s degrees with a vertex at %(vertexX)s comma %(vertexY)s, a point on the initial side at %(isX)s comma %(isY)s and a point on the terminal side at %(tsX)s comma %(tsY)s", }, + srSinusoidGraphAriaLabel: { + context: + "Screenreader accessible label for a sinusoid on a coordinate plane", + message: "A sinusoid function on a coordinate plane.", + }, + srSinusoidExtremumPoint: { + context: + "Screenreader accessible label for the extremum point (max point) on a sinusoid function.", + message: "Extremum Point at %(x)s comma %(y)s.", + }, + srSinusoidMidlineIntersection: { + context: + "Screenreader accessible label for the midline intersection on a sinusoid function.", + message: "Midline Intersection at %(x)s comma %(y)s.", + }, // The above strings are used for interactive graph SR descriptions. }; @@ -767,5 +785,9 @@ export const mockStrings: PerseusStrings = { tsY, }) => `The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the initial side at ${isX} comma ${isY} and a point on the terminal side at ${tsX} comma ${tsY}.`, + srSinusoidGraphAriaLabel: "A sinusoid function on a coordinate plane.", + srSinusoidExtremumPoint: ({x, y}) => `Extremum Point at ${x} comma ${y}.`, + srSinusoidMidlineIntersection: ({x, y}) => + `Midline Intersection at ${x} comma ${y}.`, // The above strings are used for interactive graph SR descriptions. }; diff --git a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx index d8ec98d7ef..8613db65be 100644 --- a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx @@ -1,7 +1,8 @@ import {color} from "@khanacademy/wonder-blocks-tokens"; -import {Plot} from "mafs"; +import {Plot, type vec} from "mafs"; import * as React from "react"; +import {usePerseusI18n} from "../../../components/i18n-context"; import {X, Y} from "../math"; import {actions} from "../reducer/interactive-graph-action"; @@ -15,6 +16,8 @@ import type { InteractiveGraphElementSuite, } from "../types"; +import { srFormatNumber } from "./screenreader-text"; + export function renderSinusoidGraph( state: SinusoidGraphState, dispatch: Dispatch, @@ -59,8 +62,26 @@ function SinusoidGraph(props: SinusoidGraphProps) { coeffRef.current = coeffs; } + const {strings, locale} = usePerseusI18n(); + + function getMoveablePointAriaLabel( + index: number, + coordinate: vec.Vector2, + ): string { + const coordsObj = { + x: srFormatNumber(coordinate[0], locale), + y: srFormatNumber(coordinate[1], locale) + } + + return index === 1 + ? strings.srSinusoidExtremumPoint(coordsObj) + : strings.srSinusoidMidlineIntersection(coordsObj); + } + return ( - <> + computeSine(x, coeffRef.current)} color={color.blue} @@ -68,6 +89,7 @@ function SinusoidGraph(props: SinusoidGraphProps) { {coords.map((coord, i) => ( @@ -75,7 +97,7 @@ function SinusoidGraph(props: SinusoidGraphProps) { } /> ))} - + ); } From a5897acb43f5180299d66c72d9bc5400f33cabab Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Fri, 3 Jan 2025 12:00:33 -0800 Subject: [PATCH 2/8] lint fix --- .../widgets/interactive-graphs/graphs/sinusoid.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx index 8613db65be..8484ba7239 100644 --- a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx @@ -7,6 +7,7 @@ import {X, Y} from "../math"; import {actions} from "../reducer/interactive-graph-action"; import {MovablePoint} from "./components/movable-point"; +import {srFormatNumber} from "./screenreader-text"; import type {Coord} from "../../../interactive2/types"; import type { @@ -16,8 +17,6 @@ import type { InteractiveGraphElementSuite, } from "../types"; -import { srFormatNumber } from "./screenreader-text"; - export function renderSinusoidGraph( state: SinusoidGraphState, dispatch: Dispatch, @@ -70,8 +69,8 @@ function SinusoidGraph(props: SinusoidGraphProps) { ): string { const coordsObj = { x: srFormatNumber(coordinate[0], locale), - y: srFormatNumber(coordinate[1], locale) - } + y: srFormatNumber(coordinate[1], locale), + }; return index === 1 ? strings.srSinusoidExtremumPoint(coordsObj) @@ -79,9 +78,7 @@ function SinusoidGraph(props: SinusoidGraphProps) { } return ( - + computeSine(x, coeffRef.current)} color={color.blue} From 7406ad144a7c6594c6100a4cb55ac39dc2721a61 Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Fri, 3 Jan 2025 13:33:47 -0800 Subject: [PATCH 3/8] update tests --- .../src/widgets/interactive-graphs/mafs-graph.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/perseus/src/widgets/interactive-graphs/mafs-graph.test.tsx b/packages/perseus/src/widgets/interactive-graphs/mafs-graph.test.tsx index d9b4f0d03f..fe607d10bc 100644 --- a/packages/perseus/src/widgets/interactive-graphs/mafs-graph.test.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/mafs-graph.test.tsx @@ -359,8 +359,8 @@ describe("MafsGraph", () => { />, ); - expectLabelInDoc("Point 1 at -1 comma 1"); - expectLabelInDoc("Point 2 at 0 comma 0"); + expectLabelInDoc("Midline Intersection at -1 comma 1."); + expectLabelInDoc("Extremum Point at 0 comma 0."); }); it("renders ARIA labels for each point (point)", () => { From 45aa2c4d916c5d23309e8d3aaaf58f84748cf1d2 Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Fri, 3 Jan 2025 13:34:13 -0800 Subject: [PATCH 4/8] docs(changeset): add aria labels for sinusoid function graphs --- .changeset/olive-shoes-cross.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/olive-shoes-cross.md diff --git a/.changeset/olive-shoes-cross.md b/.changeset/olive-shoes-cross.md new file mode 100644 index 0000000000..31de7987b2 --- /dev/null +++ b/.changeset/olive-shoes-cross.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus": minor +--- + +add aria labels for sinusoid function graphs From ce8f7662c32ddc7b56cbcbc160a80b5d009bd3e2 Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Tue, 7 Jan 2025 13:59:04 -0800 Subject: [PATCH 5/8] remove context and message object --- packages/perseus/src/strings.ts | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/perseus/src/strings.ts b/packages/perseus/src/strings.ts index 8076debf63..fb131f87d7 100644 --- a/packages/perseus/src/strings.ts +++ b/packages/perseus/src/strings.ts @@ -553,21 +553,9 @@ export const strings: { message: "The angle measure is %(angleMeasure)s degrees with a vertex at %(vertexX)s comma %(vertexY)s, a point on the initial side at %(isX)s comma %(isY)s and a point on the terminal side at %(tsX)s comma %(tsY)s", }, - srSinusoidGraphAriaLabel: { - context: - "Screenreader accessible label for a sinusoid on a coordinate plane", - message: "A sinusoid function on a coordinate plane.", - }, - srSinusoidExtremumPoint: { - context: - "Screenreader accessible label for the extremum point (max point) on a sinusoid function.", - message: "Extremum Point at %(x)s comma %(y)s.", - }, - srSinusoidMidlineIntersection: { - context: - "Screenreader accessible label for the midline intersection on a sinusoid function.", - message: "Midline Intersection at %(x)s comma %(y)s.", - }, + srSinusoidGraphAriaLabel: "A sinusoid function on a coordinate plane.", + srSinusoidExtremumPoint: "Extremum Point at %(x)s comma %(y)s.", + srSinusoidMidlineIntersection: "Midline Intersection at %(x)s comma %(y)s.", // The above strings are used for interactive graph SR descriptions. }; From fcf3324dea52b72706f1877cac113f6cb1adf78b Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Tue, 14 Jan 2025 15:35:56 -0800 Subject: [PATCH 6/8] update x coordinate to include pi readings --- .../interactive-graphs/graphs/sinusoid.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx index 8484ba7239..5ca44215eb 100644 --- a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx @@ -67,9 +67,21 @@ function SinusoidGraph(props: SinusoidGraphProps) { index: number, coordinate: vec.Vector2, ): string { + const x = coordinate[0]; + const y = coordinate[1]; + + const convertedXCoordinate = + x === 0 + ? `0` + : x % 2 === 0 + ? `${x / 2} pi` + : x % 1 === 0 + ? `${x}/2 pi` + : `${x * 2}/4 pi`; + const coordsObj = { - x: srFormatNumber(coordinate[0], locale), - y: srFormatNumber(coordinate[1], locale), + x: convertedXCoordinate, + y: srFormatNumber(y, locale), }; return index === 1 From 040aa5807ddada9ad01a35a36b5813f3d27defdf Mon Sep 17 00:00:00 2001 From: Anakaren Rojas Date: Wed, 15 Jan 2025 10:33:33 -0800 Subject: [PATCH 7/8] update snapshots --- .../__snapshots__/explanation.test.ts.snap | 8 ++++---- .../__snapshots__/graded-group-set-jipt.test.ts.snap | 12 ++++++------ .../__snapshots__/graded-group-set.test.ts.snap | 4 ++-- .../__snapshots__/graded-group.test.ts.snap | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/perseus/src/widgets/explanation/__snapshots__/explanation.test.ts.snap b/packages/perseus/src/widgets/explanation/__snapshots__/explanation.test.ts.snap index e96e0672b6..3383f7cfa0 100644 --- a/packages/perseus/src/widgets/explanation/__snapshots__/explanation.test.ts.snap +++ b/packages/perseus/src/widgets/explanation/__snapshots__/explanation.test.ts.snap @@ -21,12 +21,12 @@ exports[`Explanation should snapshot when expanded: expanded 1`] = ` aria-controls=":r1:" aria-disabled="false" aria-expanded="true" - class="button_vr44p2-o_O-shared_lwskrm-o_O-default_qjb97o-o_O-small_14crccx-o_O-inlineStyles_1s8anjv" + class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1hl5pu8-o_O-small_14crccx-o_O-inlineStyles_1s8anjv" role="button" type="button" > Hide explanation! @@ -94,12 +94,12 @@ exports[`Explanation should snapshot: initial render 1`] = ` aria-controls=":r0:" aria-disabled="false" aria-expanded="false" - class="button_vr44p2-o_O-shared_lwskrm-o_O-default_qjb97o-o_O-small_14crccx-o_O-inlineStyles_1s8anjv" + class="button_vr44p2-o_O-shared_lwskrm-o_O-default_1hl5pu8-o_O-small_14crccx-o_O-inlineStyles_1s8anjv" role="button" type="button" > Explanation diff --git a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap index fcf253b7dd..6d4b738751 100644 --- a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap +++ b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set-jipt.test.ts.snap @@ -251,12 +251,12 @@ exports[`graded-group-set should render all graded groups 1`] = ` />