diff --git a/.changeset/shiny-dodos-eat.md b/.changeset/shiny-dodos-eat.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/shiny-dodos-eat.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/perseus-editor/package.json b/packages/perseus-editor/package.json index ab76181538c..132daa7544e 100644 --- a/packages/perseus-editor/package.json +++ b/packages/perseus-editor/package.json @@ -51,6 +51,7 @@ "devDependencies": { "@khanacademy/mathjax-renderer": "catalog:devDeps", "@khanacademy/wonder-blocks-accordion": "catalog:devDeps", + "@khanacademy/wonder-blocks-badge": "catalog:devDeps", "@khanacademy/wonder-blocks-banner": "catalog:devDeps", "@khanacademy/wonder-blocks-button": "catalog:devDeps", "@khanacademy/wonder-blocks-clickable": "catalog:devDeps", @@ -83,6 +84,7 @@ "peerDependencies": { "@khanacademy/mathjax-renderer": "catalog:peerDeps", "@khanacademy/wonder-blocks-accordion": "catalog:peerDeps", + "@khanacademy/wonder-blocks-badge": "catalog:peerDeps", "@khanacademy/wonder-blocks-banner": "catalog:peerDeps", "@khanacademy/wonder-blocks-button": "catalog:peerDeps", "@khanacademy/wonder-blocks-clickable": "catalog:peerDeps", diff --git a/packages/perseus-editor/src/components/coordinate-pair-input.tsx b/packages/perseus-editor/src/components/coordinate-pair-input.tsx index 53313e128a0..3d97332d089 100644 --- a/packages/perseus-editor/src/components/coordinate-pair-input.tsx +++ b/packages/perseus-editor/src/components/coordinate-pair-input.tsx @@ -14,6 +14,7 @@ type Props = { coord: [number, number]; labels?: [string, string]; error?: boolean; + disabled?: boolean; style?: StyleType; // TODO(LEMS-3995) simplifying styling after custom label work + change deprecated WonderBlocks component / aphrodite labelStyle?: StyleType; @@ -21,7 +22,15 @@ type Props = { }; const CoordinatePairInput = (props: Props) => { - const {coord, labels, error, style, labelStyle, onChange} = props; + const { + coord, + labels, + error, + disabled = false, + style, + labelStyle, + onChange, + } = props; const xLabel = labels ? labels[0] : "x coord"; const yLabel = labels ? labels[1] : "y coord"; @@ -71,6 +80,7 @@ const CoordinatePairInput = (props: Props) => { handleCoordChange(newValue, 0)} style={[ styles.textField, @@ -91,6 +101,7 @@ const CoordinatePairInput = (props: Props) => { handleCoordChange(newValue, 1)} style={[ styles.textField, diff --git a/packages/perseus-editor/src/components/segmented-control.tsx b/packages/perseus-editor/src/components/segmented-control.tsx new file mode 100644 index 00000000000..001244e0c73 --- /dev/null +++ b/packages/perseus-editor/src/components/segmented-control.tsx @@ -0,0 +1,223 @@ +import Clickable from "@khanacademy/wonder-blocks-clickable"; +import {View} from "@khanacademy/wonder-blocks-core"; +import { + border, + font, + semanticColor, + sizing, +} from "@khanacademy/wonder-blocks-tokens"; +import {StyleSheet} from "aphrodite"; +import * as React from "react"; + +import type {StyleType} from "@khanacademy/wonder-blocks-core"; + +/** + * A single selectable segment. Built on Wonder Blocks `Clickable` (the same + * primitive `Pill` uses) so it gets focus handling and a real `disabled` / + * `aria-disabled` state for free, while letting us render arbitrary children + * (math, icons) and set a `radio`/`checkbox` role. + * + * Disabled styling intentionally uses the WB disabled tokens so it reads as + * disabled consistently with the rest of the design system (no opacity hack). + */ +type ToggleButtonProps = { + selected: boolean; + onClick: () => void; + disabled?: boolean; + role?: "radio" | "checkbox"; + "aria-label"?: string; + children: React.ReactNode; + style?: StyleType; +}; + +export function ToggleButton({ + selected, + onClick, + disabled = false, + role = "radio", + children, + style, + "aria-label": ariaLabel, +}: ToggleButtonProps): React.ReactElement { + return ( + + {({hovered, pressed}) => ( + + {children} + + )} + + ); +} + +/** + * A row of mutually-exclusive (single-select) segments — a segmented control. + * Replaces the deprecated `Pill`-as-button pattern. Pass `disabled` to disable + * the whole group (e.g. `editingDisabled`). + */ +type Option = { + value: string; + label: React.ReactNode; + ariaLabel?: string; +}; + +type SegmentedControlProps = { + options: ReadonlyArray