Skip to content

Commit

Permalink
Merge 54d9525 into 88f87c4
Browse files Browse the repository at this point in the history
  • Loading branch information
nasaownsky committed Apr 15, 2022
2 parents 88f87c4 + 54d9525 commit b06840a
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 92 deletions.
1 change: 1 addition & 0 deletions spotlight-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@types/react-simple-maps": "^1.0.3",
"@types/styled-components": "^5.1.5",
"@types/topojson": "^3.2.2",
"@vx/pattern": "^0.0.199",
"@w11r/use-breakpoint": "^1.8.0",
"assert-never": "^1.2.1",
"body-scroll-lock": "^3.1.5",
Expand Down
3 changes: 1 addition & 2 deletions spotlight-client/src/Notes/Notes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ const Wrapper = styled.ol`
font-size: ${rem(13)};
font-weight: 500;
line-height: 1.7;
list-style: decimal outside;
list-style: none;
margin-top: ${rem(40)};
padding-left: 1em;
`;

const Item = styled.li`
Expand Down
5 changes: 3 additions & 2 deletions spotlight-client/src/charts/BarChartTrellis.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const testData = [
{
label: "Group 1",
records: [
{ label: "Category A", color: "red", value: 30, pct: 0.3 },
{ label: "Category B", color: "blue", value: 70, pct: 0.7 },
{ label: "Category A", color: "red", value: 300, pct: 0.3 },
{ label: "Category B", color: "blue", value: 700, pct: 0.7 },
],
},
{
Expand All @@ -54,6 +54,7 @@ test("renders charts", () => {
).toHaveStyle("fill: red");
expect(
screen.getByRole("img", { name: "Category A bar value 40%" })
// if value is less than certain threshold (e.g. n=100), then the bar is rendered as a hatch
).toHaveStyle("fill: red");
expect(
screen.getByRole("img", { name: "Category B bar value 70%" })
Expand Down
144 changes: 79 additions & 65 deletions spotlight-client/src/charts/BarChartTrellis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import ResponsiveTooltipController, {
ResponsiveTooltipControllerProps,
} from "./ResponsiveTooltipController";
import { formatAsPct } from "../utils";
import { highlightFade } from "./utils";
import { isSmallData, highlightFade } from "./utils";
import { animation } from "../UiLibrary";
import { CategoricalChartRecord, CommonDataPoint } from "./types";
import MeasureWidth from "../MeasureWidth";
import { useCreateHatchDefs } from "./useCreateHatchDefs";

export const singleChartHeight = 300;

Expand Down Expand Up @@ -71,6 +72,7 @@ export function BarChartTrellis({
getTooltipProps,
}: BarChartTrellisProps): React.ReactElement {
const [highlightedLabel, setHighlightedLabel] = useState();
const { getHatchDefs, generateHatchFill } = useCreateHatchDefs();

// ResponsiveTooltipController expects this to be a stable reference
const setHighlighted = useCallback(
Expand All @@ -84,73 +86,85 @@ export function BarChartTrellis({
<ChartWrapper ref={measureRef}>
{width === 0
? null
: data.map(({ label, records: chartData }, index) => (
<ResponsiveTooltipController
key={label}
getTooltipProps={getTooltipProps}
hoverAnnotation
setHighlighted={setHighlighted}
>
<OrdinalFrame
axes={[
{
baseline: false,
orient: "left",
tickFormat: formatAsPct,
tickSize: 0,
},
]}
backgroundGraphics={
barAxisLabel ? (
// this functions as an axis label, but there is no Semiotic API for this;
// it's hidden from screen readers either way, so not a real a11y concern
<BarAxisLabel
// Semiotic axis labels use this class, we want to pick up those styles here
className="axis-title"
x={
MARGIN.left +
(width - MARGIN.left - MARGIN.right) / 2
: data.map(({ label, records: chartData }, index) => {
const hatchDefs = getHatchDefs(chartData);

return (
<ResponsiveTooltipController
key={label}
getTooltipProps={getTooltipProps}
hoverAnnotation
setHighlighted={setHighlighted}
>
<OrdinalFrame
axes={[
{
baseline: false,
orient: "left",
tickFormat: formatAsPct,
tickSize: 0,
},
]}
backgroundGraphics={
barAxisLabel ? (
// this functions as an axis label, but there is no Semiotic API for this;
// it's hidden from screen readers either way, so not a real a11y concern
<BarAxisLabel
// Semiotic axis labels use this class, we want to pick up those styles here
className="axis-title"
x={
MARGIN.left +
(width - MARGIN.left - MARGIN.right) / 2
}
y={singleChartHeight - MARGIN.bottom / 3}
>
{barAxisLabel}
</BarAxisLabel>
) : undefined
}
baseMarkProps={{
transitionDuration: { fill: animation.defaultDuration },
}}
data={chartData}
margin={MARGIN}
oAccessor="label"
// @ts-expect-error Semiotic types can't handle a styled component here but it's fine
oLabel={(barLabel) => (
<ColumnLabel
transform={
angledLabels
? `rotate(-45) translate(-10)`
: undefined
}
y={singleChartHeight - MARGIN.bottom / 3}
>
{barAxisLabel}
</BarAxisLabel>
) : undefined
}
baseMarkProps={{
transitionDuration: { fill: animation.defaultDuration },
}}
data={chartData}
margin={MARGIN}
oAccessor="label"
// @ts-expect-error Semiotic types can't handle a styled component here but it's fine
oLabel={(barLabel) => (
<ColumnLabel
transform={
angledLabels
? `rotate(-45) translate(-10)`
: undefined
{formatBarLabel(barLabel as string)}
</ColumnLabel>
)}
oPadding={2}
rAccessor="pct"
rExtent={[0, 1]}
size={[width, singleChartHeight]}
style={(d: CommonDataPoint) => {
if (isSmallData(chartData)) {
return {
fill: generateHatchFill(d.label, highlightedLabel),
};
}
>
{formatBarLabel(barLabel as string)}
</ColumnLabel>
)}
oPadding={2}
rAccessor="pct"
rExtent={[0, 1]}
size={[width, singleChartHeight]}
style={(d: CommonDataPoint) => ({
fill:
highlightedLabel && highlightedLabel !== d.label
? highlightFade(d.color)
: d.color,
})}
// Semiotic centers titles by default; this x offset will align left
title={<ChartTitle x={0 - width / 2}>{label}</ChartTitle>}
type="bar"
/>
</ResponsiveTooltipController>
))}
return {
fill:
highlightedLabel && highlightedLabel !== d.label
? highlightFade(d.color)
: d.color,
};
}}
// Semiotic centers titles by default; this x offset will align left
title={<ChartTitle x={0 - width / 2}>{label}</ChartTitle>}
type="bar"
additionalDefs={hatchDefs}
/>
</ResponsiveTooltipController>
);
})}
</ChartWrapper>
)}
</MeasureWidth>
Expand Down
2 changes: 1 addition & 1 deletion spotlight-client/src/charts/BubbleChart.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jest.mock("../MeasureWidth/MeasureWidth");
const testData = [
{ label: "thing 1", color: "red", value: 10, pct: 0.1086956522 },
{ label: "thing 2", color: "blue", value: 50, pct: 0.5434782609 },
{ label: "thing 3", color: "green", value: 32, pct: 0.347826087 },
{ label: "thing 3", color: "green", value: 320, pct: 0.347826087 },
];

test("renders bubbles for data", () => {
Expand Down
27 changes: 20 additions & 7 deletions spotlight-client/src/charts/BubbleChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ import styled from "styled-components/macro";
import ColorLegend from "./ColorLegend";
import ResponsiveTooltipController from "./ResponsiveTooltipController";
import { formatAsPct } from "../utils";
import { useHighlightedItem, highlightFade } from "./utils";
import { useHighlightedItem, highlightFade, isSmallData } from "./utils";
import { CategoricalChartRecord } from "./types";
import { animation, colors, typefaces } from "../UiLibrary";
import MeasureWidth from "../MeasureWidth";
import { useCreateHatchDefs } from "./useCreateHatchDefs";

const margin = { top: 0, left: 0, right: 0, bottom: 40 };

Expand Down Expand Up @@ -66,6 +67,7 @@ const BUBBLE_VALUE_Y_OFFSET = 8;

const LegendWrapper = styled.div`
bottom: 0;
right: 0;
position: absolute;
`;

Expand All @@ -79,6 +81,9 @@ export default function BubbleChart({
height,
}: BubbleChartProps): React.ReactElement {
const { highlighted, setHighlighted } = useHighlightedItem();
const { getHatchDefs, generateHatchFill } = useCreateHatchDefs();

const hatchDefs = getHatchDefs(data);

return (
<MeasureWidth>
Expand Down Expand Up @@ -121,15 +126,23 @@ export default function BubbleChart({
)
}
nodeSizeAccessor={getRadius}
nodeStyle={(d) => ({
fill:
highlighted && highlighted.label !== d.label
? highlightFade(d.color)
: d.color,
})}
nodeStyle={(d) => {
if (isSmallData(data)) {
return {
fill: generateHatchFill(d.label, highlighted?.label),
};
}
return {
fill:
highlighted && highlighted.label !== d.label
? highlightFade(d.color)
: d.color,
};
}}
nodes={data}
renderKey="label"
size={[width, height]}
additionalDefs={hatchDefs}
/>
</ResponsiveTooltipController>
<LegendWrapper>
Expand Down
4 changes: 2 additions & 2 deletions spotlight-client/src/charts/ProportionalBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import ProportionalBar from "./ProportionalBar";
jest.mock("../MeasureWidth/MeasureWidth");

const testData = [
{ label: "thing 1", color: "red", value: 10, pct: 0.1639344262 },
{ label: "thing 2", color: "blue", value: 51, pct: 0.8360655738 },
{ label: "thing 1", color: "red", value: 1000, pct: 0.1639344262 },
{ label: "thing 2", color: "blue", value: 510, pct: 0.8360655738 },
];

test("renders data", () => {
Expand Down
26 changes: 19 additions & 7 deletions spotlight-client/src/charts/ProportionalBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import { animation, colors, zIndex } from "../UiLibrary";
import ColorLegend from "./ColorLegend";
import ResponsiveTooltipController from "./ResponsiveTooltipController";
import { CategoricalChartRecord, ItemToHighlight } from "./types";
import { useHighlightedItem, highlightFade } from "./utils";
import { useHighlightedItem, highlightFade, isSmallData } from "./utils";
import { useCreateHatchDefs } from "./useCreateHatchDefs";

const ProportionalBarContainer = styled.figure`
width: 100%;
Expand Down Expand Up @@ -90,11 +91,14 @@ export default function ProportionalBar({
highlighted: localHighlighted,
setHighlighted: setLocalHighlighted,
} = useHighlightedItem();
const { getHatchDefs, generateHatchFill } = useCreateHatchDefs();

const noData = data.length === 0 || sum(data.map(({ value }) => value)) === 0;

const highlighted = localHighlighted || externalHighlighted;

const hatchDefs = getHatchDefs(data);

return (
<MeasureWidth>
{({ measureRef, width }) => (
Expand Down Expand Up @@ -125,13 +129,21 @@ export default function ProportionalBar({
rAccessor="value"
renderKey="label"
size={[width, height]}
style={(d: ValuesType<ProportionalBarProps["data"]>) => ({
fill:
highlighted && highlighted.label !== d.label
? highlightFade(d.color)
: d.color,
})}
style={(d: ValuesType<ProportionalBarProps["data"]>) => {
if (isSmallData(data)) {
return {
fill: generateHatchFill(d.label, highlighted?.label),
};
}
return {
fill:
highlighted && highlighted.label !== d.label
? highlightFade(d.color)
: d.color,
};
}}
type="bar"
additionalDefs={hatchDefs}
/>
</ResponsiveTooltipController>
</ProportionalBarChartWrapper>
Expand Down
6 changes: 6 additions & 0 deletions spotlight-client/src/charts/RateTrend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import MeasureWidth from "../MeasureWidth";
import { DataSeries, ItemToHighlight, TooltipContentFunction } from "./types";
import { RateFields } from "../metricsApi";
import { TooltipContentProps } from "../Tooltip";
import { STATISTIC_THRESHOLD } from "../constants";

type ChartData = DataSeries<RateFields & { [key: string]: number }>[];

Expand Down Expand Up @@ -215,6 +216,11 @@ export default function RateTrend({
highlightFade(d?.color, { useOpacity: true })
: d?.color,
strokeWidth: 2,
strokeDasharray:
d?.coordinates[0].rateDenominator <
STATISTIC_THRESHOLD
? "5,7"
: 0,
};
}}
lines={data}
Expand Down

0 comments on commit b06840a

Please sign in to comment.