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 diff --git a/packages/perseus/src/strings.ts b/packages/perseus/src/strings.ts index cfe30d3d43..12b0066fd0 100644 --- a/packages/perseus/src/strings.ts +++ b/packages/perseus/src/strings.ts @@ -310,6 +310,9 @@ export type PerseusStrings = { point2X: string; point2Y: 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. }; @@ -537,6 +540,9 @@ export const strings = { "Ray with endpoint %(point1X)s comma %(point1Y)s going through point %(point2X)s comma %(point2Y)s.", srRayEndpoint: "Endpoint at %(x)s comma %(y)s.", srRayTerminalPoint: "Through point 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. } satisfies { [key in keyof PerseusStrings]: @@ -771,6 +777,10 @@ export const mockStrings: PerseusStrings = { `Ray with endpoint ${point1X} comma ${point1Y} going through point ${point2X} comma ${point2Y}.`, srRayEndpoint: ({x, y}) => `Endpoint at ${x} comma ${y}.`, srRayTerminalPoint: ({x, y}) => `Through point at ${x} comma ${y}.`, + 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 974eda7b24..3f00a781ff 100644 --- a/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/graphs/sinusoid.tsx @@ -1,11 +1,13 @@ import {color} from "@khanacademy/wonder-blocks-tokens"; -import {Plot} from "mafs"; +import {Plot, type vec} from "mafs"; import * as React from "react"; -import {X, Y} from "../math/coordinates"; +import {usePerseusI18n} from "../../../components/i18n-context"; +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 { SinusoidGraphState, @@ -53,8 +55,36 @@ function SinusoidGraph(props: SinusoidGraphProps) { coeffRef.current = coeffs; } + const {strings, locale} = usePerseusI18n(); + + function getMoveablePointAriaLabel( + 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: convertedXCoordinate, + y: srFormatNumber(y, locale), + }; + + return index === 1 + ? strings.srSinusoidExtremumPoint(coordsObj) + : strings.srSinusoidMidlineIntersection(coordsObj); + } + return ( - <> + computeSine(x, coeffRef.current)} color={color.blue} @@ -62,6 +92,7 @@ function SinusoidGraph(props: SinusoidGraphProps) { {coords.map((coord, i) => ( @@ -69,7 +100,7 @@ function SinusoidGraph(props: SinusoidGraphProps) { } /> ))} - + ); } 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 0f3ecfbe69..97765b97a6 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/2 pi comma 1."); + expectLabelInDoc("Extremum Point at 0 comma 0."); }); it("renders ARIA labels for each point (point)", () => {