Skip to content

Commit

Permalink
[Locked Figure Aria] Implement locked line aria label behavior on gra…
Browse files Browse the repository at this point in the history
…ph (#1683)

## Summary:
- Add `ariaLabel` field to LockedLineType
- Add the aria label behavior to the LockedLine on the mafs graph

Issue: https://khanacademy.atlassian.net/browse/LEMS-2376

## Test plan:
`yarn jest packages/perseus/src/widgets/interactive-graphs/interactive-graph.test.tsx`

Storybook
- Go to http://localhost:6006/iframe.html?args=&id=perseuseditor-widgets-interactive-graph--mafs-with-locked-figure-labels-all-flags&viewMode=story
- Use a screen reader to navigate through the preview graph
- Using the screenreader controls (VO + arrow keys) should be able to navigate to
  the locked line. It should read out as "Point PQ".


https://github.com/user-attachments/assets/a6fafd5b-9d3e-4b1a-94ca-7404bb60e7ab

Author: nishasy

Reviewers: benchristel, catandthemachines, anakaren-rojas

Required Reviewers:

Approved By: benchristel

Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #1683
  • Loading branch information
nishasy authored Sep 30, 2024
1 parent 039e0a3 commit 2d7cada
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changeset/fresh-sheep-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": minor
"@khanacademy/perseus-editor": minor
---

[Locked Figure Aria] Implement locked line aria label behavior on graph
1 change: 1 addition & 0 deletions packages/perseus/src/perseus-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ export type LockedLineType = {
showPoint1: boolean;
showPoint2: boolean;
labels?: LockedLabelType[];
ariaLabel?: string;
};

export type LockedVectorType = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const GraphLockedLayer = (props: Props) => {
key={`line-${index}`}
range={props.range}
{...figure}
flags={flags}
/>
);
case "vector":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,7 @@ describe("InteractiveGraphQuestionBuilder", () => {
showPoint1: true,
showPoint2: true,
labels: [{text: "a label"}],
ariaLabel: "an aria label",
})
.build();
const graph = question.widgets["interactive-graph 1"];
Expand Down Expand Up @@ -902,6 +903,7 @@ describe("InteractiveGraphQuestionBuilder", () => {
size: "medium",
},
],
ariaLabel: "an aria label",
},
]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ class InteractiveGraphQuestionBuilder {
showPoint1?: boolean;
showPoint2?: boolean;
labels?: LockedFigureLabelOptions[];
ariaLabel?: string;
},
): InteractiveGraphQuestionBuilder {
const line: LockedLineType = {
Expand All @@ -332,6 +333,7 @@ class InteractiveGraphQuestionBuilder {
color: options?.color ?? "grayH",
size: label.size ?? "medium",
})),
ariaLabel: options?.ariaLabel,
points: [
{
...this.createLockedPoint(...point1, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,52 @@ describe("locked layer", () => {
});
});

it("should render locked line with aria label when one is provided", () => {
// Arrange
const lockedLineWithAriaLabelQuestion =
interactiveGraphQuestionBuilder()
.addLockedLine([0, 0], [2, 2], {
ariaLabel: "Line A",
})
.build();
const {container} = renderQuestion(lockedLineWithAriaLabelQuestion, {
flags: {
mafs: {
segment: true,
"locked-figures-aria": true,
},
},
});

// Act
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const point = container.querySelector(".locked-line");

// Assert
expect(point).toHaveAttribute("aria-label", "Line A");
});

it("should render locked line without aria label by default", () => {
// Arrange
const simpleLockedLinequestion = interactiveGraphQuestionBuilder()
.addLockedLine([0, 0], [2, 2])
.build();
const {container} = renderQuestion(simpleLockedLinequestion, {
flags: {
mafs: {
segment: true,
},
},
});

// Act
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const point = container.querySelector(".locked-line");

// Assert
expect(point).not.toHaveAttribute("aria-label");
});

it("should render locked vectors", async () => {
// Arrange
const {container} = renderQuestion(segmentWithLockedVectors, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ export const segmentWithLockedFigures: PerseusRenderer =
showPoint1: true,
showPoint2: true,
labels: [{text: "B"}],
ariaLabel: "Line PQ",
})
.addLockedVector([0, 0], [8, 2], {
color: "purple",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,30 @@ import {getIntersectionOfRayWithBox} from "../graphs/utils";
import {X, Y, calculateAngleInDegrees} from "../math";

import type {LockedLineType} from "../../../perseus-types";
import type {APIOptions} from "../../../types";
import type {Interval} from "mafs";

type Props = LockedLineType & {
flags?: APIOptions["flags"];
range: [Interval, Interval];
};

const LockedLine = (props: Props) => {
const {color, lineStyle, kind, points, showPoint1, showPoint2, range} =
props;
const {
color,
lineStyle,
kind,
points,
showPoint1,
showPoint2,
ariaLabel,
flags,
range,
} = props;
const [point1, point2] = points;

const hasAria = ariaLabel && flags?.["mafs"]?.["locked-figures-aria"];

let line;

if (kind === "ray") {
Expand Down Expand Up @@ -101,7 +114,11 @@ const LockedLine = (props: Props) => {
}

return (
<g className={kind === "ray" ? "locked-ray" : "locked-line"}>
<g
className={kind === "ray" ? "locked-ray" : "locked-line"}
aria-label={hasAria ? ariaLabel : undefined}
aria-hidden={!hasAria}
>
{line}
{showPoint1 && (
<Point
Expand Down

0 comments on commit 2d7cada

Please sign in to comment.