Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor examples so we can support multiple per chart type #3017

Open
wants to merge 5 commits into
base: feat/theme-builder-docs-migration
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type ButtonProps = {
size?: "sm" | "md";
};

const Button = ({
export const Button = ({
onClick,
children,
className = "",
Expand All @@ -19,13 +19,16 @@ const Button = ({
size = "md",
...props
}: ButtonProps) => {
const baseClasses =
"py-2 px-4 font-semibold rounded-md cursor-pointer text-sm border-2 border-solid border-button-border bg-button-bg text-button-fg hover:bg-button-bg-hover hover:text-button-fg-hover disabled:bg-grayscale-300 disabled:text-grayscale-400 disabled:cursor-not-allowed";

return (
<button
onClick={onClick}
disabled={disabled}
aria-label={ariaLabel || undefined}
className={clsx(
"border-none rounded-md cursor-pointer text-sm bg-button-bg text-button-fg hover:underline disabled:bg-grayscale-300 disabled:text-grayscale-400 disabled:cursor-not-allowed disabled:hover:no-underline",
baseClasses,
size === "md" && "py-2 px-5 font-bold",
size === "sm" && "py-1.5 px-3 font-semibold",
className,
Expand All @@ -36,5 +39,3 @@ const Button = ({
</button>
);
};

export default Button;
29 changes: 29 additions & 0 deletions website/src/hooks/useClickOutside.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect, useLayoutEffect, useRef } from "react";

export function useClickOutside(cb: (e: Event) => void) {
const ref = useRef<HTMLDivElement>(null);
const refCb = useRef(cb);

useLayoutEffect(() => {
refCb.current = cb;
});

useEffect(() => {
const handler = (e: Event) => {
const element = ref.current;
if (element && !element.contains(e.target as Node)) {
refCb.current(e);
}
};

document.addEventListener("mousedown", handler);
document.addEventListener("touchstart", handler);

return () => {
document.removeEventListener("mousedown", handler);
document.removeEventListener("touchstart", handler);
};
}, []);

return ref;
}
20 changes: 8 additions & 12 deletions website/src/pages/themes/_components/chart-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo } from "react";
import React, { useEffect, useMemo } from "react";
import Control from "./control";
import Select from "./select";
import { usePreviewOptions } from "../_providers/previewOptionsProvider";
Expand All @@ -13,7 +13,7 @@ const ChartPanel = ({
config: { title, description, selectLabel, types },
}: ChartPanelProps) => {
const [chartType, setChartType] = React.useState(Object.keys(types)[0]);
const { setExampleConfigs } = usePreviewOptions();
const { setExampleContent } = usePreviewOptions();
const selectOptions = Object.keys(types).map((key) => ({
label: types[key].label,
value: key,
Expand All @@ -27,18 +27,14 @@ const ChartPanel = ({
);
const controls = types[chartType]?.controls || [];

const onChartTypeChange = useCallback(
(newValue: string) => {
setChartType(newValue);
const examples = types[newValue] ? [types[newValue]] : [];
setExampleConfigs(examples);
},
[setExampleConfigs, types],
);
const onChartTypeChange = (newValue: string) => {
setChartType(newValue);
};

useEffect(() => {
onChartTypeChange(Object.keys(types)[0]);
}, [types, onChartTypeChange]);
const examples = types[chartType]?.content || [];
setExampleContent(examples);
}, [chartType, setExampleContent, types]);

return (
<>
Expand Down
17 changes: 12 additions & 5 deletions website/src/pages/themes/_components/color-palette-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ const ColorPaletteSelector = ({
updateColorScale(value);
};

const handleColorChange = (newColor, i, cScale) => {
onColorChange({
newColor,
index: i,
colorScale: cScale,
});
if (colorScale !== cScale) {
updateColorScale(cScale);
}
};

const isSelected = colorScale === value;

return (
Expand All @@ -54,11 +65,7 @@ const ColorPaletteSelector = ({
key={i}
color={color}
onColorChange={(newColor) =>
onColorChange({
newColor,
index: i,
colorScale: colorScaleType as string,
})
handleColorChange(newColor, i, colorScaleType)
}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,70 @@
import React from "react";
import React, { useCallback } from "react";
import ColorPicker from "./color-picker";
import clsx from "clsx";
import Toggle from "./toggle";
import {
defaultColorScale,
usePreviewOptions,
} from "../_providers/previewOptionsProvider";

type ColorScaleOverrideSelectorProps = {
id: string;
label?: string;
value?: string | string[];
onChange: (value: string[] | undefined) => void;
hideDefaultToggle?: boolean;
className?: string;
};

const ColorScaleOverrideSelector = ({
id,
label = "Color Scale",
value,
onChange,
hideDefaultToggle = false,
className,
}: ColorScaleOverrideSelectorProps) => {
const { colorScale, updateColorScale } = usePreviewOptions();
const hasCustomValue = Array.isArray(value);
const [initialCustomValue] = React.useState(
hasCustomValue ? value : undefined,
);

const setColorScaleToDefault = useCallback(() => {
if (colorScale !== defaultColorScale) {
updateColorScale(defaultColorScale);
}
}, [colorScale, updateColorScale]);

const onCheckboxChange = (isChecked) => {
if (isChecked) {
onChange(initialCustomValue);
} else {
onChange(undefined);
}
setColorScaleToDefault();
};

const handleColorChange = (newColor, index) => {
const newValue = [...(value as string[])];
newValue[index] = newColor;
onChange(newValue);
setColorScaleToDefault();
};

return (
<label className={clsx("p-0 m-0", className)}>
<span className="block mb-3 text-sm font-bold">{label}</span>
<Toggle
id="color-scale-override-toggle"
label="Use custom color scale"
checked={hasCustomValue}
onChange={onCheckboxChange}
className="mb-3"
size="sm"
/>
{!hideDefaultToggle && (
<Toggle
id={id}
label="Use custom color scale"
checked={hasCustomValue}
onChange={onCheckboxChange}
className="mb-3"
size="sm"
/>
)}
{hasCustomValue && (
<div className="flex flex-wrap gap-2 mt-3">
{value.map((color, i) => (
Expand Down
24 changes: 21 additions & 3 deletions website/src/pages/themes/_components/control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getConfigValue } from "../_utils";
import { useTheme } from "../_providers/themeProvider";
import Accordion from "./accordion";
import ColorScaleOverrideSelector from "./color-scale-override-selector";
import PreviewColorScaleSelect from "./theme-preview/preview-color-scale-select";

export type ColorChangeArgs = {
newColor?: string;
Expand Down Expand Up @@ -85,9 +86,16 @@ const Control = ({ type, control, className }: ControlProps) => {
case "section":
return (
<section className="mb-8">
<h3 className="text-lg font-bold text-secondary mb-4">
{control.label}
</h3>
<div className="mb-4">
<h3 className="text-lg font-semibold text-secondary mb-0">
{control.label}
</h3>
{control.description && (
<p className="text-sm text-grayscale-400">
{control.description}
</p>
)}
</div>
{control.controls?.map((nestedControl, i) => (
<Control
key={nestedControl.label + i}
Expand Down Expand Up @@ -130,10 +138,20 @@ const Control = ({ type, control, className }: ControlProps) => {
case "colorScale":
return (
<ColorScaleOverrideSelector
id={id}
label={control.label}
value={configValue as string}
onChange={handleChange}
className={className}
hideDefaultToggle={control.hideDefaultToggle}
/>
);
case "colorScalePreview":
return (
<PreviewColorScaleSelect
key={control.label}
label={control.label}
className={className}
/>
);
case "colorPicker":
Expand Down
26 changes: 26 additions & 0 deletions website/src/pages/themes/_components/examples/area.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import { VictoryArea, VictoryAxis, VictoryChart } from "victory";

import { ExampleConfig } from "./example";

export const AreaExamples: ExampleConfig[] = [
{
title: "VictoryArea",
content: (props) => (
<VictoryChart theme={props.theme} domainPadding={20}>
<VictoryAxis label="X Axis" />
<VictoryAxis dependentAxis label="Y Axis" />
<VictoryArea
{...props}
data={[
{ x: 1, y: 2, label: "A" },
{ x: 2, y: 3, label: "B" },
{ x: 3, y: 5, label: "C" },
{ x: 4, y: 4, label: "D" },
{ x: 5, y: 7, label: "E" },
]}
/>
</VictoryChart>
),
},
];
16 changes: 16 additions & 0 deletions website/src/pages/themes/_components/examples/axis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";
import { VictoryAxis, VictoryChart } from "victory";

import { ExampleConfig } from "./example";

export const AxisExamples: ExampleConfig[] = [
{
title: "VictoryAxis",
content: (props) => (
<VictoryChart theme={props.theme} domainPadding={20}>
<VictoryAxis label="X Axis" {...props} />
<VictoryAxis dependentAxis label="Y Axis" {...props} />
</VictoryChart>
),
},
];
41 changes: 41 additions & 0 deletions website/src/pages/themes/_components/examples/bar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from "react";
import { VictoryBar, VictoryAxis, VictoryChart } from "victory";

import { ExampleConfig } from "./example";

export const BarExamples: ExampleConfig[] = [
{
title: "VictoryBar",
content: (props) => (
<VictoryChart theme={props.theme} domainPadding={20}>
<VictoryAxis label="X Axis" />
<VictoryAxis dependentAxis label="Y Axis" />
<VictoryBar
{...props}
data={[
{
x: 1,
y: 2,
},
{
x: 2,
y: 3,
},
{
x: 3,
y: 5,
},
{
x: 4,
y: 4,
},
{
x: 5,
y: 7,
},
]}
/>
</VictoryChart>
),
},
];
26 changes: 26 additions & 0 deletions website/src/pages/themes/_components/examples/box-plot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable no-magic-numbers */

import React from "react";
import { VictoryBoxPlot } from "victory";

import { ExampleConfig } from "./example";

export const BoxPlotExamples: ExampleConfig[] = [
{
title: "VictoryBoxPlot",
content: (props) => (
<VictoryBoxPlot
{...props}
data={[
{ x: 1, y: [1, 2, 3, 5, 8] },
{ x: 2, y: [3, 2, 8, 10, 12] },
{ x: 3, y: [2, 8, 6, 5, 10] },
{ x: 4, y: [1, 3, 2, 9, 5] },
{ x: 5, y: [3, 2, 9, 5, 7] },
]}
labels
labelOrientation="right"
/>
),
},
];
Loading