From e49d6d6b0b3a736925c711149139e0ae0d9c383a Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Tue, 14 Jan 2025 15:10:12 -0800 Subject: [PATCH 01/14] docs(changeset): [Storybook] Configure Aphrodite to Not Append !important to Styles --- .changeset/forty-months-promise.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/forty-months-promise.md diff --git a/.changeset/forty-months-promise.md b/.changeset/forty-months-promise.md new file mode 100644 index 0000000000..d267d4e431 --- /dev/null +++ b/.changeset/forty-months-promise.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus-dev-ui": patch +--- + +[Storybook] Configure Aphrodite to Not Append !important to Styles From 698506a69ab4f8f4445c6640e5ba3c65ba500611 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Tue, 14 Jan 2025 15:11:23 -0800 Subject: [PATCH 02/14] Add alias to vite config file to ensure that Aphrodite doesn't append !important. --- dev/vite.config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/vite.config.ts b/dev/vite.config.ts index b1f6268979..17006dd633 100644 --- a/dev/vite.config.ts +++ b/dev/vite.config.ts @@ -4,6 +4,7 @@ import {resolve, dirname, join} from "node:path"; import react from "@vitejs/plugin-react"; import glob from "fast-glob"; import {defineConfig} from "vite"; +import path from "path"; // Create aliases for each package in the Perseus monorepo, so Vite knows // where to look when a file imports e.g. @khanacademy/perseus. @@ -27,6 +28,10 @@ export default defineConfig({ hubble: resolve(__dirname, "../vendor/hubble/hubble.js"), raphael: resolve(__dirname, "../vendor/raphael/raphael.js"), jsdiff: resolve(__dirname, "../vendor/jsdiff/jsdiff.js"), + aphrodite: resolve( + __dirname, + "../node_modules/aphrodite/no-important", + ), ...packageAliases, }, }, From 908d55b798d7a5bbf89c46aecb31d5997c7610c4 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Tue, 14 Jan 2025 15:22:13 -0800 Subject: [PATCH 03/14] Remove unnecessary import statement. --- dev/vite.config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/vite.config.ts b/dev/vite.config.ts index 17006dd633..2fdf22f2da 100644 --- a/dev/vite.config.ts +++ b/dev/vite.config.ts @@ -4,7 +4,6 @@ import {resolve, dirname, join} from "node:path"; import react from "@vitejs/plugin-react"; import glob from "fast-glob"; import {defineConfig} from "vite"; -import path from "path"; // Create aliases for each package in the Perseus monorepo, so Vite knows // where to look when a file imports e.g. @khanacademy/perseus. From 9c2bed1b176fe04e545023c02a73c7ed4bc42fee Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Thu, 16 Jan 2025 16:26:36 -0800 Subject: [PATCH 04/14] Update Storybook's configuration of Vite to wrap cascade layers around the imported LESS files. --- .storybook/main.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.storybook/main.ts b/.storybook/main.ts index f8fd25a5e5..ac91e117f7 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -3,6 +3,24 @@ import {mergeConfig} from "vite"; import type {StorybookConfig} from "@storybook/react-vite"; +// This is a temporary plugin option to mimic what is in PROD in regard to cascade layers. +// Perseus LESS files are wrapped in the 'shared' layer in Webapp. +// To get the same ordering of precedence in Storybook, the imported LESS files need to be wrapped accordingly. +// Once the LESS files have cascade layers included (a more involved task for a later time), +// then the following plugin option should be removed. +const lessWrapper = { + name: 'wrap-less-in-layer', + transform: (code: string, pathname: string) => { + if (pathname.endsWith(".less")) { + const layerStatements = "@layer reset, shared, legacy;\n@layer shared"; + return { + code: `${layerStatements} { ${code} }`, + map: null, + } + } + } +}; + const config: StorybookConfig = { framework: "@storybook/react-vite", @@ -53,6 +71,7 @@ const config: StorybookConfig = { }, // Fix from: https://github.com/storybookjs/storybook/issues/25256#issuecomment-1866441206 assetsInclude: ["/sb-preview/runtime.js"], + plugins: [...viteConfig.plugins, lessWrapper], }); }, staticDirs: ["../static"], From 4a233c9fc3aec54e16d548bf4a683b9248d4d92b Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Thu, 16 Jan 2025 16:32:59 -0800 Subject: [PATCH 05/14] Prettier. --- .storybook/main.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index ac91e117f7..29955c6363 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -9,16 +9,17 @@ import type {StorybookConfig} from "@storybook/react-vite"; // Once the LESS files have cascade layers included (a more involved task for a later time), // then the following plugin option should be removed. const lessWrapper = { - name: 'wrap-less-in-layer', - transform: (code: string, pathname: string) => { + name: "wrap-less-in-layer", + transform: (code: string, pathname: string) => { if (pathname.endsWith(".less")) { - const layerStatements = "@layer reset, shared, legacy;\n@layer shared"; + const layerStatements = + "@layer reset, shared, legacy;\n@layer shared"; return { code: `${layerStatements} { ${code} }`, map: null, - } + }; } - } + }, }; const config: StorybookConfig = { From 8f8b6e103b4f6b0d2c4312269bf790faa4ac8aa5 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Tue, 21 Jan 2025 10:28:15 -0800 Subject: [PATCH 06/14] Notes regarding dynamic styling --- .../widgets/radio/choice-icon/choice-icon.tsx | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx index 5f5e004090..cfbfa5394a 100644 --- a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx +++ b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx @@ -73,19 +73,24 @@ function getDynamicStyles( color: string; borderRadius: number; } { + // TODO: Rewrite this logic into the Aphrodite styling (at the bottom of this document). + // Make sure that stories exist that test all variations of this function. + // Add stories if any are missing. let backgroundColor: string | undefined; let borderColor: string; let color: string; - if (!showCorrectness && pressed) { + if (!showCorrectness && (pressed || checked)) { // never show color changes while being pressed borderColor = WBColor.blue; color = WBColor.blue; backgroundColor = "transparent"; - } else if (checked) { - const bg = showCorrectness && correct ? WBColor.green : WBColor.blue; + } else if (checked) { // not being pressed, option is checked + // first handle showCorrectness + // then handle correct/incorrect + const bg = correct ? WBColor.green : WBColor.red; color = styleConstants.white; backgroundColor = bg; borderColor = bg; - } else { + } else { // not checked, not being pressed borderColor = WBColor.offBlack64; color = WBColor.offBlack64; } @@ -111,16 +116,16 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { hovered, multipleSelect, pos, - previouslyAnswered, + previouslyAnswered, // Used in "review mode"/"show rationale" to show that option was previously chosen pressed, } = props; const dynamicStyles = getDynamicStyles( - checked, - showCorrectness, - pressed, - multipleSelect, - correct, + checked, // Learner selected the choice + showCorrectness, // Lets learner see if the choice is correct or not + pressed, // Is learner in the process of choosing option (aka mousedown) + multipleSelect, // Single-select are circles, multi-select are square + correct, // Choice is correct ); return ( From e735556980fcfe76129c56ea4c06f50dce237a0b Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Thu, 23 Jan 2025 17:36:12 -0800 Subject: [PATCH 07/14] Adjust cross-out line to be better positioned. Adjust styling logic to use classes instead of inline styling. --- .storybook/main.ts | 2 +- .../widgets/radio/choice-icon/choice-icon.tsx | 88 ++++++++++++++----- .../radio/choice-icon/cross-out-line.tsx | 4 +- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 29955c6363..eb08bdbeb3 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -6,7 +6,7 @@ import type {StorybookConfig} from "@storybook/react-vite"; // This is a temporary plugin option to mimic what is in PROD in regard to cascade layers. // Perseus LESS files are wrapped in the 'shared' layer in Webapp. // To get the same ordering of precedence in Storybook, the imported LESS files need to be wrapped accordingly. -// Once the LESS files have cascade layers included (a more involved task for a later time), +// Once the LESS files have cascade layers included (LEMS-2801), // then the following plugin option should be removed. const lessWrapper = { name: "wrap-less-in-layer", diff --git a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx index cfbfa5394a..71ad9ab2fa 100644 --- a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx +++ b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx @@ -79,7 +79,7 @@ function getDynamicStyles( let backgroundColor: string | undefined; let borderColor: string; let color: string; - if (!showCorrectness && (pressed || checked)) { // never show color changes while being pressed + if (!showCorrectness && pressed) { // never show color changes while being pressed borderColor = WBColor.blue; color = WBColor.blue; backgroundColor = "transparent"; @@ -128,6 +128,27 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { correct, // Choice is correct ); + const choiceStyling = [ + styles.choiceBase, + multipleSelect ? styles.multiSelectShape : styles.singleSelectShape, + showCorrectness ? styles.choiceHasIcon : styles.choiceHasLetter, + checked ? styles.choiceIsChecked : styles.choiceIsUnchecked, + ]; + if (showCorrectness && correct && checked) { + choiceStyling.push(styles.choiceCorrect); + } else if (showCorrectness && !correct && (checked || previouslyAnswered)) { + choiceStyling.push(styles.choiceIncorrect); + } else if (checked) { + // Show filled neutral blue color (showCorrectness is false) + choiceStyling.push(styles.choiceNeutral); + } else if (pressed) { + // Show outlined neutral blue color (showCorrectness is false) + choiceStyling.push(styles.activeNeutral); + } else { + // choice is not checked + choiceStyling.push(styles.uncheckedColors); + } + return (
+ { + // TODO: Need to account for loss of dynamicStyles variable + } {crossedOut && }
); @@ -175,8 +190,7 @@ const styles = StyleSheet.create({ alignItems: "center", justifyContent: "center", }, - circle: { - // Make the circle + choiceBase: { width: CHOICE_ICON_SIZE, height: CHOICE_ICON_SIZE, boxSizing: "border-box", @@ -189,7 +203,6 @@ const styles = StyleSheet.create({ // "bold font family" so that characters which fall back to the default // font get bolded too. fontWeight: "bold", - fontSize: 12, // Center the icon wrapper. display: "flex", @@ -203,20 +216,53 @@ const styles = StyleSheet.create({ lineHeight: "1px", }, - circleCorrect: { - fontSize: CHOICE_ICON_SIZE, + choiceHasLetter: { + fontSize: 12, }, - circleIncorrect: { + choiceHasIcon: { fontSize: CHOICE_ICON_SIZE, - borderColor: styleConstants.gray68, - color: styleConstants.gray68, }, - circleIncorrectAnswered: { + choiceIsChecked: { + color: WBColor.white, + }, + + choiceIsUnchecked: { + color: WBColor.offBlack64, + }, + + choiceCorrect: { + backgroundColor: WBColor.green, + borderColor: WBColor.green, + }, + + choiceIncorrect: { backgroundColor: WBColor.red, borderColor: WBColor.red, - color: WBColor.white, + }, + + choiceNeutral: { + backgroundColor: WBColor.blue, + borderColor: WBColor.blue, + }, + + activeNeutral: { + color: WBColor.blue, + borderColor: WBColor.blue, + backgroundColor: "transparent", + }, + + multiSelectShape: { + borderRadius: 3, + }, + + singleSelectShape: { + borderRadius: CHOICE_ICON_SIZE, + }, + + uncheckedColors: { + borderColor: WBColor.offBlack64, }, }); diff --git a/packages/perseus/src/widgets/radio/choice-icon/cross-out-line.tsx b/packages/perseus/src/widgets/radio/choice-icon/cross-out-line.tsx index ef8bf48b99..384a0740d7 100644 --- a/packages/perseus/src/widgets/radio/choice-icon/cross-out-line.tsx +++ b/packages/perseus/src/widgets/radio/choice-icon/cross-out-line.tsx @@ -43,8 +43,8 @@ const styles = StyleSheet.create({ crossOutLine: { // Center the icon within the container. position: "absolute", - top: `0px`, - left: `0px`, + top: `2px`, + left: `2px`, }, }); From 5da033d633e7ececa61b8150e11c31212a5bf0cb Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Fri, 24 Jan 2025 16:06:33 -0800 Subject: [PATCH 08/14] Remove refactored code. --- .../widgets/radio/choice-icon/choice-icon.tsx | 81 ++++--------------- 1 file changed, 14 insertions(+), 67 deletions(-) diff --git a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx index 71ad9ab2fa..a50d54f3be 100644 --- a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx +++ b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx @@ -57,55 +57,6 @@ function ChoiceInner(props: ChoiceInnerProps) { return ; } -// Handle dynamic styling of the multiple choice icon. Most -// MC icon styles are constant, but we do allow the caller -// to specify the selected color, and thus must control styles -// related to the selected state dynamically. -function getDynamicStyles( - checked: boolean, - showCorrectness: boolean, - pressed: boolean, - multipleSelect: boolean, - correct?: boolean | null, -): { - backgroundColor: string | undefined; - borderColor: string; - color: string; - borderRadius: number; -} { - // TODO: Rewrite this logic into the Aphrodite styling (at the bottom of this document). - // Make sure that stories exist that test all variations of this function. - // Add stories if any are missing. - let backgroundColor: string | undefined; - let borderColor: string; - let color: string; - if (!showCorrectness && pressed) { // never show color changes while being pressed - borderColor = WBColor.blue; - color = WBColor.blue; - backgroundColor = "transparent"; - } else if (checked) { // not being pressed, option is checked - // first handle showCorrectness - // then handle correct/incorrect - const bg = correct ? WBColor.green : WBColor.red; - color = styleConstants.white; - backgroundColor = bg; - borderColor = bg; - } else { // not checked, not being pressed - borderColor = WBColor.offBlack64; - color = WBColor.offBlack64; - } - - // define shape - let borderRadius; - if (multipleSelect) { - borderRadius = 3; - } else { - borderRadius = CHOICE_ICON_SIZE; - } - - return {backgroundColor, borderColor, color, borderRadius}; -} - const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { const { checked, @@ -120,33 +71,38 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { pressed, } = props; - const dynamicStyles = getDynamicStyles( - checked, // Learner selected the choice - showCorrectness, // Lets learner see if the choice is correct or not - pressed, // Is learner in the process of choosing option (aka mousedown) - multipleSelect, // Single-select are circles, multi-select are square - correct, // Choice is correct - ); - + // Core styling const choiceStyling = [ styles.choiceBase, multipleSelect ? styles.multiSelectShape : styles.singleSelectShape, showCorrectness ? styles.choiceHasIcon : styles.choiceHasLetter, checked ? styles.choiceIsChecked : styles.choiceIsUnchecked, ]; + + // Color styling + // Handle dynamic styling of the multiple choice icon. Most + // MC icon styles are constant, but we do allow the caller + // to specify the selected color, and thus must control styles + // related to the selected state dynamically. + let crossOutColor: string; if (showCorrectness && correct && checked) { choiceStyling.push(styles.choiceCorrect); + crossOutColor = WBColor.green; } else if (showCorrectness && !correct && (checked || previouslyAnswered)) { choiceStyling.push(styles.choiceIncorrect); + crossOutColor = WBColor.red; } else if (checked) { // Show filled neutral blue color (showCorrectness is false) choiceStyling.push(styles.choiceNeutral); + crossOutColor = WBColor.blue; } else if (pressed) { // Show outlined neutral blue color (showCorrectness is false) choiceStyling.push(styles.activeNeutral); + crossOutColor = WBColor.blue; } else { // choice is not checked choiceStyling.push(styles.uncheckedColors); + crossOutColor = WBColor.offBlack64; } return ( @@ -172,10 +128,7 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { - { - // TODO: Need to account for loss of dynamicStyles variable - } - {crossedOut && } + {crossedOut && } ); }; @@ -208,12 +161,6 @@ const styles = StyleSheet.create({ display: "flex", alignItems: "center", justifyContent: "center", - // HACK(emily): I don't know why adding this line height makes the text - // appear centered better than any other value, but it does. In - // particular, at large zoom levels this line height does almost - // nothing, but at the default size this shifts the letter down one - // pixel so it is much better centered. - lineHeight: "1px", }, choiceHasLetter: { From eb6816e75c7db58ede0a39f72c8d984243071b4d Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Fri, 24 Jan 2025 16:14:27 -0800 Subject: [PATCH 09/14] docs(changeset): [Storybook] Configure Aphrodite to Not Append !important to Styles [Radio] Bugfix - Incorrect choice showing as blue instead of red --- .changeset/dry-turtles-leave.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/dry-turtles-leave.md diff --git a/.changeset/dry-turtles-leave.md b/.changeset/dry-turtles-leave.md new file mode 100644 index 0000000000..ebf0de5464 --- /dev/null +++ b/.changeset/dry-turtles-leave.md @@ -0,0 +1,7 @@ +--- +"@khanacademy/perseus-dev-ui": patch +"@khanacademy/perseus": patch +--- + +[Storybook] Configure Aphrodite to Not Append !important to Styles +[Radio] Bugfix - Incorrect choice showing as blue instead of red From 62396f84603b2be7810e7b7135604afff8f5fbb1 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Fri, 24 Jan 2025 16:17:30 -0800 Subject: [PATCH 10/14] Remove older changeset file. --- .changeset/forty-months-promise.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/forty-months-promise.md diff --git a/.changeset/forty-months-promise.md b/.changeset/forty-months-promise.md deleted file mode 100644 index d267d4e431..0000000000 --- a/.changeset/forty-months-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@khanacademy/perseus-dev-ui": patch ---- - -[Storybook] Configure Aphrodite to Not Append !important to Styles From 8eaeb12e899d3c1c77dc3a65095e41d3d453ae98 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Fri, 24 Jan 2025 16:34:11 -0800 Subject: [PATCH 11/14] Update unit tests and snapshots. --- .../server-item-renderer.test.tsx.snap | 1 - .../graded-group-set-jipt.test.ts.snap | 3 - .../graded-group-set.test.ts.snap | 1 - .../group/__snapshots__/group.test.tsx.snap | 17 ++-- .../matrix/__snapshots__/matrix.test.ts.snap | 24 ------ .../__snapshots__/numeric-input.test.ts.snap | 4 - .../__snapshots__/radio.test.ts.snap | 84 +++++++------------ .../radio/__tests__/choice-icon.test.tsx | 21 ++--- 8 files changed, 41 insertions(+), 114 deletions(-) diff --git a/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap b/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap index bddd4e50e9..55bc9e0197 100644 --- a/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap +++ b/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap @@ -45,7 +45,6 @@ exports[`server item renderer should snapshot: initial render 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Mock Widget" - aria-required="false" class="input_1ck1z8k-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-defaultFocus_9n1kv3" id="mock-widget 1" role="textbox" 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 69683fcef0..fcf253b7dd 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 @@ -66,7 +66,6 @@ exports[`graded-group-set should render all graded groups 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" - aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" @@ -309,7 +308,6 @@ exports[`graded-group-set should render all graded groups 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" - aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" @@ -552,7 +550,6 @@ exports[`graded-group-set should render all graded groups 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" - aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" diff --git a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap index 21fb82790f..89358bc011 100644 --- a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap +++ b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap @@ -132,7 +132,6 @@ exports[`graded group widget should snapshot 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" - aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" diff --git a/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap b/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap index 562be3c1cf..147294fc07 100644 --- a/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap +++ b/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap @@ -189,10 +189,9 @@ exports[`group widget should snapshot: initial render 1`] = ` style="border-color: transparent; border-radius: 50%;" >
{ describe.each([[true], [false]])("multipleSelect: %s", (multipleSelect) => { - it("renders with the correct border radius", () => { + it("renders with the correct shape", () => { // Arrange - let expectedRadius; - if (multipleSelect) { - expectedRadius = 3; - } else { - expectedRadius = CHOICE_ICON_SIZE; - } + const expectedClass = multipleSelect + ? "multiSelectShape" + : "singleSelectShape"; // Act renderChoiceIcon({multipleSelect}); @@ -42,11 +38,10 @@ describe("choice icon", () => { const choiceWrapper = screen.getByTestId( `choice-icon__library-choice-icon`, ); + const choiceAttrib = choiceWrapper.getAttribute("class"); // Assert - expect(choiceWrapper).toHaveStyle( - `border-radius: ${expectedRadius}px`, - ); + expect(choiceAttrib).toContain(expectedClass); }); }); @@ -65,7 +60,7 @@ describe("choice icon", () => { const choiceAttrib = choiceWrapper.getAttribute("class"); // Assert - expect(choiceAttrib).toContain("circleCorrect"); + expect(choiceAttrib).toContain("choiceCorrect"); }); it("shows a dash for incorrect answers", () => { @@ -83,6 +78,6 @@ describe("choice icon", () => { const choiceAttrib = choiceWrapper.getAttribute("class"); // Assert - expect(choiceAttrib).toContain("circleIncorrect"); + expect(choiceAttrib).toContain("choiceIncorrect"); }); }); From b8e20bc6752a69cf0cf9ede7ceeeedb75f8f7aff Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Mon, 27 Jan 2025 08:40:19 -0800 Subject: [PATCH 12/14] Update snapshots --- .../server-item-renderer.test.tsx.snap | 1 + .../graded-group-set-jipt.test.ts.snap | 3 +++ .../graded-group-set.test.ts.snap | 1 + .../group/__snapshots__/group.test.tsx.snap | 2 ++ .../matrix/__snapshots__/matrix.test.ts.snap | 24 +++++++++++++++++++ .../__snapshots__/numeric-input.test.ts.snap | 4 ++++ 6 files changed, 35 insertions(+) diff --git a/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap b/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap index 55bc9e0197..bddd4e50e9 100644 --- a/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap +++ b/packages/perseus/src/__tests__/__snapshots__/server-item-renderer.test.tsx.snap @@ -45,6 +45,7 @@ exports[`server item renderer should snapshot: initial render 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Mock Widget" + aria-required="false" class="input_1ck1z8k-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-defaultFocus_9n1kv3" id="mock-widget 1" role="textbox" 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..69683fcef0 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 @@ -66,6 +66,7 @@ exports[`graded-group-set should render all graded groups 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" + aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" @@ -308,6 +309,7 @@ exports[`graded-group-set should render all graded groups 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" + aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" @@ -550,6 +552,7 @@ exports[`graded-group-set should render all graded groups 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" + aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" diff --git a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap index 89358bc011..21fb82790f 100644 --- a/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap +++ b/packages/perseus/src/widgets/graded-group-set/__snapshots__/graded-group-set.test.ts.snap @@ -132,6 +132,7 @@ exports[`graded group widget should snapshot 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="Your answer:" + aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" diff --git a/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap b/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap index 147294fc07..759343146e 100644 --- a/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap +++ b/packages/perseus/src/widgets/group/__snapshots__/group.test.tsx.snap @@ -754,6 +754,7 @@ exports[`group widget should snapshot: initial render 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="value rounded to the nearest ten" + aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" @@ -974,6 +975,7 @@ exports[`group widget should snapshot: initial render 1`] = ` aria-disabled="false" aria-invalid="false" aria-label="value rounded to the nearest hundred" + aria-required="false" autocapitalize="off" autocomplete="off" autocorrect="off" diff --git a/packages/perseus/src/widgets/matrix/__snapshots__/matrix.test.ts.snap b/packages/perseus/src/widgets/matrix/__snapshots__/matrix.test.ts.snap index 67d1245ce0..9619fe72b8 100644 --- a/packages/perseus/src/widgets/matrix/__snapshots__/matrix.test.ts.snap +++ b/packages/perseus/src/widgets/matrix/__snapshots__/matrix.test.ts.snap @@ -89,6 +89,7 @@ exports[`matrix widget should snapshot on mobile: first mobile render 1`] = ` Date: Thu, 30 Jan 2025 13:10:23 -0800 Subject: [PATCH 13/14] [LEMS-2227-adjust-aphrodite-to-not-use-important] Adding console message for debugging. --- packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx index a50d54f3be..efa5ae4849 100644 --- a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx +++ b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx @@ -105,6 +105,8 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { crossOutColor = WBColor.offBlack64; } + console.log(`Using updated choice-icon.tsx`); // eslint-disable-line no-console + return (
Date: Mon, 3 Feb 2025 11:32:59 -0800 Subject: [PATCH 14/14] [LEMS-2227-adjust-aphrodite-to-not-use-important] Adjust color for previously answered incorrect choices that are still showing. --- .../perseus/src/widgets/radio/choice-icon/choice-icon.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx index efa5ae4849..2fe042cb66 100644 --- a/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx +++ b/packages/perseus/src/widgets/radio/choice-icon/choice-icon.tsx @@ -71,12 +71,16 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { pressed, } = props; + // Accounts for incorrect choice still displaying as learner tries again + const choiceIsChecked = + checked || (showCorrectness && !correct && previouslyAnswered); + // Core styling const choiceStyling = [ styles.choiceBase, multipleSelect ? styles.multiSelectShape : styles.singleSelectShape, showCorrectness ? styles.choiceHasIcon : styles.choiceHasLetter, - checked ? styles.choiceIsChecked : styles.choiceIsUnchecked, + choiceIsChecked ? styles.choiceIsChecked : styles.choiceIsUnchecked, ]; // Color styling @@ -105,8 +109,6 @@ const ChoiceIcon = function (props: ChoiceIconProps): React.ReactElement { crossOutColor = WBColor.offBlack64; } - console.log(`Using updated choice-icon.tsx`); // eslint-disable-line no-console - return (