Skip to content

Commit

Permalink
Style movable points and segments on Mafs graphs (#1068)
Browse files Browse the repository at this point in the history
## Summary:
See this slack thread for designs and discussion:
https://khanacademy.slack.com/archives/C067UM1QAR4/p1709847469823399

Issue: LEMS-1672

Test plan:

```
yarn dev
open http://localhost:5173
```

Check the "segment" box in the dropdown at the top of the screen to
switch to the Mafs version of the segment graph.

You should be able to move the points and line segment with the mouse
and keyboard. The hover and focus states of the points should be clearly distinct.
The line segment should be highlighted blue when focused.


https://github.com/Khan/perseus/assets/693920/08a2bc76-2021-4fb6-96fa-d402b7c795b5

Author: benchristel

Reviewers: nishasy, benchristel, #perseus, jeremywiebe, mark-fitzgerald, nedredmond

Required Reviewers:

Approved By: nishasy

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), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check builds for changes in size (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: #1068
  • Loading branch information
benchristel authored Mar 13, 2024
1 parent 59d29cd commit 881da72
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/fast-buckets-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": patch
---

Adjust styling of the movable points and line segments on the Mafs segment graph
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ describe("segment graph", () => {

// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const movablePoints = container.querySelectorAll(
"circle.mafs-movable-point-hitbox",
"circle.movable-point-hitbox",
);

// Act
Expand All @@ -166,7 +166,7 @@ describe("segment graph", () => {

// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const movablePoints = container.querySelectorAll(
"circle.mafs-movable-point-hitbox",
"circle.movable-point-hitbox",
);

// Act
Expand Down
20 changes: 9 additions & 11 deletions packages/perseus/src/widgets/interactive-graphs/graphs/segment.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Color from "@khanacademy/wonder-blocks-color";
import {MovablePoint, vec, useMovable, useTransformContext} from "mafs";
import {vec, useMovable, useTransformContext} from "mafs";
import * as React from "react";
import {useRef} from "react";

import {moveControlPoint, moveSegment} from "../interactive-graph-action";
import {MovablePoint} from "../movable-point";

import type {Segment, SegmentGraphState} from "../interactive-graph-state";
import type {MafsGraphProps} from "../types";
Expand Down Expand Up @@ -64,10 +64,10 @@ const SegmentView = (props: {
});

const {viewTransform, userTransform} = useTransformContext();
const transform = vec.matrixMult(viewTransform, userTransform);
const transformToPx = vec.matrixMult(viewTransform, userTransform);

const scaledPoint1 = vec.transform(pt1, transform);
const scaledPoint2 = vec.transform(pt2, transform);
const pt1Px = vec.transform(pt1, transformToPx);
const pt2Px = vec.transform(pt2, transformToPx);

return (
<>
Expand All @@ -79,13 +79,13 @@ const SegmentView = (props: {
>
{/* This transparent line creates a nice big click target. */}
<SVGLine
start={scaledPoint1}
end={scaledPoint2}
start={pt1Px}
end={pt2Px}
style={{stroke: "transparent", strokeWidth: 30}}
/>
<SVGLine
start={scaledPoint1}
end={scaledPoint2}
start={pt1Px}
end={pt2Px}
style={{
stroke: "var(--mafs-segment-stroke-color)",
strokeWidth: "var(--mafs-segment-stroke-weight)",
Expand All @@ -94,14 +94,12 @@ const SegmentView = (props: {
</g>
<MovablePoint
point={pt1}
color={Color.blue}
onMove={(newPoint) => {
props.onMovePoint(0, newPoint);
}}
/>
<MovablePoint
point={pt2}
color={Color.blue}
onMove={(newPoint) => {
props.onMovePoint(1, newPoint);
}}
Expand Down
55 changes: 55 additions & 0 deletions packages/perseus/src/widgets/interactive-graphs/mafs-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
--mafs-green: #00a60e; /* WB color.green */
--mafs-violet: #9059ff; /* WB color.purple */
--mafs-yellow: #ffb100; /* WB color.gold */

/* overridden on a per-point basis */
--movable-point-color: var(--mafs-blue);
--movable-point-center-radius: 6px;
--movable-point-ring-radius: calc(2px + var(--movable-point-center-radius));
--movable-point-halo-radius: calc(3px + var(--movable-point-ring-radius));
--movable-point-hover-expansion: 2px;
}

.MafsView .movable-segment {
Expand All @@ -30,3 +37,51 @@
.MafsView .movable-segment:focus {
outline: none;
}

.MafsView .movable-point-hitbox {
fill: transparent;
}

.MafsView :is(.movable-point-center, .movable-point-ring, .movable-point-halo) {
transition: r 0.15s ease-out;
}

.MafsView .movable-point-center {
r: var(--movable-point-center-radius);
}

.MafsView .movable-point-halo {
r: var(--movable-point-halo-radius);
fill: var(--movable-point-color);
opacity: 0.25;
filter: drop-shadow(0 5px 5px #0008);
}

.MafsView .movable-point-ring {
r: var(--movable-point-ring-radius);
fill: #fff;
}

.MafsView .movable-point:hover .movable-point-center {
r: calc(
var(--movable-point-hover-expansion) +
var(--movable-point-center-radius)
);
}

.MafsView .movable-point:hover .movable-point-ring {
r: calc(
var(--movable-point-hover-expansion) + var(--movable-point-ring-radius)
);
}

.MafsView .movable-point:hover .movable-point-halo {
r: calc(
var(--movable-point-hover-expansion) + var(--movable-point-halo-radius)
);
}

.MafsView .movable-point:focus-visible .movable-point-halo {
outline: 2px solid blue;
border-radius: 99px;
}
51 changes: 51 additions & 0 deletions packages/perseus/src/widgets/interactive-graphs/movable-point.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Color from "@khanacademy/wonder-blocks-color";
import {vec, useMovable, useTransformContext} from "mafs";
import * as React from "react";
import {useRef} from "react";

type Props = {
point: vec.Vector2;
onMove: (newPoint: vec.Vector2) => unknown;
};

export const MovablePoint = (props: Props) => {
const hitboxRef = useRef<SVGCircleElement>(null);
const {point, onMove} = props;

const {dragging} = useMovable({
gestureTarget: hitboxRef,
point,
onMove,
constrain: (p) => p,
});

const {viewTransform, userTransform} = useTransformContext();
const transformToPx = vec.matrixMult(viewTransform, userTransform);
const [x, y] = vec.transform(point, transformToPx);

return (
<g
ref={hitboxRef}
className="movable-point"
tabIndex={0}
style={
{
cursor: dragging ? "grabbing" : "grab",
touchAction: "none",
outline: "none",
"--movable-point-color": Color.blue,
} as any
}
>
<circle className="movable-point-hitbox" r={30} cx={x} cy={y} />
<circle className="movable-point-halo" cx={x} cy={y} />
<circle className="movable-point-ring" cx={x} cy={y} />
<circle
className="movable-point-center"
cx={x}
cy={y}
style={{fill: Color.blue}}
/>
</g>
);
};

0 comments on commit 881da72

Please sign in to comment.