Skip to content

Commit

Permalink
Accessibility and Usability Enhancements for Explanation Widget (#1060)
Browse files Browse the repository at this point in the history
## Summary:
The Explanation widget should be consistent regardless of its content type, as well as across device platforms. Therefore, the `<Clickable>` element is now changed to a Wonder Blocks `<Button>`. Additionally, minor custom formatting that was tied to the content type (i.e. article) or the platform (i.e. mobile) has been removed.

The widget should also follow accessibility best practices. The attribute `aria-controls` has been added to the button to indicate what will be affected when it is toggled. Although [this attribute is not currently being used](w3c/aria#995) by assistive technologies, it is [highly recommended by the ARIA working group](w3c/aria#995 (comment)) that this attribute be applied in cases such as this. Therefore, in addition to the attribute being added to the button, the content that is shown/hidden by the button is now rendered in the DOM at all times in order to be referenced by the `aria-controls` attribute.

Interactions with the widget should respond in an intuitive manner. When activation of an element causes something else to happen on the page, an [animation can ease the cognitive aspects](https://www.nngroup.com/articles/animation-usability/) of following that change. Therefore, CSS transitions have been applied to properties of the content wrapper to change the show/hide action to be a reveal/conceal action (see the Before and After videos for a comparison). In order to honor the preferences of the user, the widget checks the `prefers-reduced-motion` media preference before applying the transitions.

Other interesting changes:
* Refactored the widget to take advantage of the common visuals across use cases.
   * Removed unneeded logic branches.
   * Removed unneeded styling.
   * Removed unneeded unit tests.
   * Moved styling logic outside of the JSX block.
* Added a new Storybook story (with new test data) to show a normal use case.
* Fixed unit tests for Graded Group widget which improperly referenced the Explanation widget.
   * Changed the test data to use the GG widget's internal Explain/Hide button.
   * Updated the snapshots.
* Added UI regression tests to guard against CSS mishaps that alter keyboard interactions.

Issues: LP-5838, LEMS-199, LEMS-259, LP-11557 (possibly), LEMS-277, LC-212, MOB-5434 (possibly)

## Test plan:
1. Open the Perseus Storybook (locally: http://localhost:6006/?path=/story/perseus-widgets-explanation--question-1).
   * Notice the change in appearance of the "Explanation" button.
1. Activate the "Explanation" button (either by clicking it or by tabbing to it and pressing Enter/Spacebar keys).
   * Notice that the widget content is revealed via an animation.
   * Activating the button (now showing "Hide") again causes the content to be concealed, but slightly faster than when it is revealed.
1. Change your accessibility settings to prefer reduced motion.
   * In MacOS, open System Settings => Accessibility => Display => Reduce motion
1. Activate the "Explanation" button again.
   * Notice that the widget content is shown without any animation.
   * Don't forget to reset your accessibility settings.

## Affected Behavior:

### Before - Current UX

https://github.com/Khan/perseus/assets/13896410/dcb1fcdc-c4cd-4e01-b342-e4a7f39ba583



### After - New UX

https://github.com/Khan/perseus/assets/13896410/a8622fba-c61e-4107-9a87-80fe1f6829bb

Author: mark-fitzgerald

Reviewers: jeremywiebe, benchristel, mark-fitzgerald

Required Reviewers:

Approved By: jeremywiebe

Checks: ✅ codecov/project, ✅ codecov/patch, ✅ Upload Coverage, ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Extract i18n strings (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ gerald, ✅ Jest Coverage (ubuntu-latest, 20.x)

Pull Request URL: #1060
  • Loading branch information
mark-fitzgerald authored Mar 14, 2024
1 parent 113a6ac commit 857ea95
Show file tree
Hide file tree
Showing 15 changed files with 503 additions and 694 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-dots-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": minor
---

Accessibility and Usability Enhancements for Explanation Widget
2 changes: 2 additions & 0 deletions config/cypress/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import "cypress-jest-adapter";
// eslint-disable-next-line import/no-unassigned-import
import "cypress-wait-until";
// eslint-disable-next-line import/no-unassigned-import
import "cypress-real-events";

if (Cypress.env("CYPRESS_COVERAGE")) {
// @ts-expect-error - TS1378 - (trust me!) Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', or 'nodenext', and the 'target' option is set to 'es2017' or higher.
Expand Down
2 changes: 1 addition & 1 deletion config/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"esModuleInterop": true,
// be explicit about types included
// to avoid clashing with Jest types
"types": ["cypress", "node"]
"types": ["cypress", "node", "cypress-real-events"]
},
"include": ["**/*.ts", "**/*.tsx"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"css-loader": "^6.8.1",
"cypress": "^13.6.5",
"cypress-jest-adapter": "^0.1.1",
"cypress-real-events": "^1.12.0",
"cypress-wait-until": "^3.0.1",
"eslint": "^8.40.0",
"eslint-config-prettier": "^8.8.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/perseus/src/styles/perseus-renderer.less
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@

.perseus-renderer > .paragraph > ul:not(.perseus-widget-radio),
.perseus-renderer > .paragraph > ol {
margin: -11px 0px 22px 0px; // first-level lists need padding
margin: 0px 0px 22px 0px; // first-level lists need padding
}

.paragraph ul:not(.perseus-widget-radio, .indicatorContainer) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as React from "react";

import {RendererWithDebugUI} from "../../../../../testing/renderer-with-debug-ui";
import {question1, question2} from "../__testdata__/explanation.testdata";
import {
ipsumExample,
question1,
question2,
} from "../__testdata__/explanation.testdata";

export default {
title: "Perseus/Widgets/Explanation",
Expand All @@ -16,3 +20,7 @@ export const Question1 = (args: StoryArgs): React.ReactElement => {
export const Question2 = (args: StoryArgs): React.ReactElement => {
return <RendererWithDebugUI question={question2} />;
};

export const IpsumExample = (args: StoryArgs): React.ReactElement => {
return <RendererWithDebugUI question={ipsumExample} />;
};
42 changes: 42 additions & 0 deletions packages/perseus/src/widgets/__testdata__/explanation.testdata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,45 @@ export const randomExplanationGenerator = (): PerseusRenderer => {
},
};
};

export const ipsumExample: PerseusRenderer = {
content: `Unidentified vessel travelling at sub warp speed, bearing 235.7.
Fluctuations in energy readings from it, Captain.
All transporters off.
A strange set-up, but I'd say the graviton generator is depolarized.
The dark colourings of the scrapes are the leavings of natural rubber,
a type of non-conductive sole used by researchers experimenting with electricity.
The molecules must have been partly de-phased by the anyon beam.
\n[[\u2603 explanation 1]]\n\nSensors indicate no shuttle or other ships in this sector.
According to coordinates, we have travelled 7,000 light years and are located near [the system J-25](#).
Tractor beam released, sir. Force field maintaining our hull integrity.
Damage report? Sections 27, 28 and 29 on decks four, five and six destroyed.
`,
images: {},
widgets: {
"explanation 1": {
graded: true,
version: {
major: 0,
minor: 0,
},
static: false,
type: "explanation",
options: {
hidePrompt: "Hide",
widgets: {},
explanation: `It indicates a [synchronic distortion](#) in the areas emanating triolic waves.
The cerebellum, the cerebral cortex, the brain stem,
the entire nervous system has been depleted of electrochemical energy.
Any device like that would produce high levels of triolic waves.
These walls have undergone some kind of [selective molecular polarization](#).
I haven't determined if our phaser energy can generate a stable field.
We could alter the photons with phase discriminators.
`,
static: false,
showPrompt: "Explanation",
},
alignment: "default",
},
},
};
57 changes: 24 additions & 33 deletions packages/perseus/src/widgets/__testdata__/graded-group.testdata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const question1: PerseusRenderer = {
options: {
title: "Metabolic strategies of bacteria",
content:
"1. **Which of the following statements about metabolic strategies of bacteria are true?**\n\n [[☃ categorizer 1]]\n\n [[☃ explanation 1]]",
"1. **Which of the following statements about metabolic strategies of bacteria are true?**\n\n [[☃ categorizer 1]]",
images: {},
widgets: {
"categorizer 1": {
Expand All @@ -34,40 +34,31 @@ export const question1: PerseusRenderer = {
},
version: {major: 0, minor: 0},
},
"explanation 1": {
type: "explanation",
alignment: "default",
static: false,
graded: true,
options: {
static: false,
showPrompt: "Hint",
hidePrompt: "Hide hint",
explanation:
"Some bacteria synthesize their own fuel molecules/fix their own carbon (autotrophic), while others take in fixed carbon from their environments (heterotrophic).\n\nSome autotrophs use light energy to synthesize their own fuel molecules, while others extract energy from chemical sources.\n\nBacteria that extract energy from chemical sources and use it to fix carbon are called chemosynthetic organisms. These bacteria may be essential to communities where light is not available, like those around deep-sea vents. They can form the base of the food chain (act as primary producers) in these ecosystems.\n\nSome bacteria have symbiotic (mutually beneficial) relationships with other organisms, living inside these organisms and providing them with nutrients.\n\n**The following statements about the metabolic strategies of bacteria are true:**\n\n[[☃ categorizer 1]]",
widgets: {
"categorizer 1": {
type: "categorizer",
alignment: "default",
static: true,
graded: true,
options: {
static: false,
items: [
" Some bacteria conduct photosynthesis and produce oxygen, much like plants.",
"Bacteria are always autotrophic but they may get energy from either light or chemical sources.",
"Some chemosynthetic bacteria introduce energy and fixed carbon into communities where photosynthesis is not possible (e.g., deep-sea vents).",
"Some bacteria live symbiotically inside of host organisms and provide the host with nutrients.",
],
categories: ["True", "False"],
values: [0, 1, 0, 0],
randomizeItems: false,
},
version: {major: 0, minor: 0},
},
},
hint: {
content:
"Some bacteria synthesize their own fuel molecules/fix their own carbon (autotrophic), while others take in fixed carbon from their environments (heterotrophic).\n\nSome autotrophs use light energy to synthesize their own fuel molecules, while others extract energy from chemical sources.\n\nBacteria that extract energy from chemical sources and use it to fix carbon are called chemosynthetic organisms. These bacteria may be essential to communities where light is not available, like those around deep-sea vents. They can form the base of the food chain (act as primary producers) in these ecosystems.\n\nSome bacteria have symbiotic (mutually beneficial) relationships with other organisms, living inside these organisms and providing them with nutrients.\n\n**The following statements about the metabolic strategies of bacteria are true:**\n\n[[☃ categorizer 1]]",
images: {},
widgets: {
"categorizer 1": {
type: "categorizer",
alignment: "default",
static: true,
graded: true,
options: {
static: false,
items: [
" Some bacteria conduct photosynthesis and produce oxygen, much like plants.",
"Bacteria are always autotrophic but they may get energy from either light or chemical sources.",
"Some chemosynthetic bacteria introduce energy and fixed carbon into communities where photosynthesis is not possible (e.g., deep-sea vents).",
"Some bacteria live symbiotically inside of host organisms and provide the host with nutrients.",
],
categories: ["True", "False"],
values: [0, 1, 0, 0],
randomizeItems: false,
},
version: {major: 0, minor: 0},
},
version: {major: 0, minor: 0},
},
},
},
Expand Down
Loading

0 comments on commit 857ea95

Please sign in to comment.