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

feat: add area chart options to theme builder #2967

Merged
merged 1 commit into from
Nov 14, 2024
Merged
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
4 changes: 3 additions & 1 deletion demo/ts/components/theme-builder/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type ColorPickerProps = {
id: string;
onColorChange: (color: string) => void;
showColorName?: boolean;
className?: string;
};

const ColorPicker = ({
Expand All @@ -16,6 +17,7 @@ const ColorPicker = ({
id,
onColorChange,
showColorName = false,
className,
}: ColorPickerProps) => {
const [isPickerOpen, setIsPickerOpen] = React.useState(false);

Expand All @@ -26,7 +28,7 @@ const ColorPicker = ({
};

return (
<fieldset>
<fieldset className={className}>
{label && (
<label className="block mb-1 text-sm text-gray-900 dark:text-white font-bold">
{label}
Expand Down
2 changes: 1 addition & 1 deletion demo/ts/components/theme-builder/color-scale-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const ColorScaleOptions = ({
label="Color Scale"
className="mb-5"
/>
<div className="flex flex-wrap gap-3 mb-5">
<div className="flex flex-wrap gap-3">
{palette?.[activeColorScale as string]?.map((color, i) => (
<ColorPicker
key={i}
Expand Down
161 changes: 103 additions & 58 deletions demo/ts/components/theme-builder/config-mapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import ColorPicker from "./color-picker";
import ColorScaleOptions from "./color-scale-options";
import { getConfigValue } from "./utils";

const ConfigMapper = ({
const ControlComponent = ({
type,
field,
themeConfig,
activeColorScale,
updateThemeConfig,
activeColorScale,
handleColorScaleChange,
className,
}) => {
const handleColorChange = ({ newColor, index, colorScale }) => {
const updatedColors = themeConfig?.palette?.[colorScale]?.map((color, i) =>
Expand All @@ -20,6 +23,91 @@ const ConfigMapper = ({
updateThemeConfig(`palette.${colorScale}`, updatedColors);
};

const handleChange = (newValue) => {
updateThemeConfig(field.path, newValue);
};

const configValue = getConfigValue(themeConfig, field.path);
switch (type) {
case "colorScale":
return (
<ColorScaleOptions
palette={themeConfig?.palette}
activeColorScale={activeColorScale}
onColorChange={handleColorChange}
onColorScaleChange={handleColorScaleChange}
/>
);
case "section":
return (
<section className="mb-6">
<h3 className="text-lg text-secondary font-bold mb-4">
{field.label}
</h3>
{field.fields.map((subField, i) => (
<ControlComponent
key={subField.label + i}
type={subField.type}
field={subField}
themeConfig={themeConfig}
updateThemeConfig={updateThemeConfig}
activeColorScale={activeColorScale}
handleColorScaleChange={handleColorScaleChange}
className={className}
/>
))}
</section>
);
case "slider":
return (
<Slider
id={field.label}
key={field.label}
label={field.label}
value={configValue as number}
unit={field.unit}
onChange={handleChange}
min={field.min}
max={field.max}
step={field.step}
className={className}
/>
);
case "select":
return (
<Select
id={field.label}
key={field.label}
label={field.label}
value={configValue as string}
onChange={handleChange}
options={field.options}
className={className}
/>
);
case "colorPicker":
return (
<ColorPicker
id={field.label}
key={field.label}
label={field.label}
color={configValue as string}
onColorChange={handleChange}
className={className}
showColorName
/>
);
default:
return null;
}
};

const ConfigMapper = ({
themeConfig,
activeColorScale,
updateThemeConfig,
handleColorScaleChange,
}) => {
return (
<>
{optionsConfig.map((section, index) => (
Expand All @@ -29,62 +117,19 @@ const ConfigMapper = ({
id={section.title}
defaultOpen={index === 0}
>
{section.fields.map((field) => {
if (field.type === "colorScale") {
return (
<ColorScaleOptions
key={field.label}
activeColorScale={activeColorScale}
palette={themeConfig?.palette}
onColorChange={handleColorChange}
onColorScaleChange={handleColorScaleChange}
/>
);
}
const configValue = getConfigValue(themeConfig, field.path);
if (field.type === "slider") {
return (
<Slider
id={field.label}
key={field.label}
label={field.label}
value={configValue as number}
unit={field.unit}
onChange={(newValue) =>
updateThemeConfig(field.path, newValue)
}
/>
);
}
if (field.type === "select") {
return (
<Select
id={field.label}
key={field.label}
label={field.label}
value={configValue as string}
options={field.options}
onChange={(newValue) =>
updateThemeConfig(field.path, newValue)
}
/>
);
}
if (field.type === "colorPicker") {
return (
<ColorPicker
id={field.label}
key={field.label}
label={field.label}
color={configValue as string}
onColorChange={(newColor) =>
updateThemeConfig(field.path, newColor)
}
showColorName
/>
);
}
return null;
{section.fields.map((field, i) => {
return (
<ControlComponent
key={field.label + i}
type={field.type}
field={field}
themeConfig={themeConfig}
updateThemeConfig={updateThemeConfig}
activeColorScale={activeColorScale}
handleColorScaleChange={handleColorScaleChange}
className="mb-4"
/>
);
})}
</Accordion>
))}
Expand Down
19 changes: 17 additions & 2 deletions demo/ts/components/theme-builder/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const ThemeBuilder = () => {

return (
<div className="flex flex-row flex-wrap items-start justify-start w-full">
<aside className="relative flex flex-col h-lvh w-[350px] border-r border-gray-200">
<aside className="relative flex flex-col h-full w-[380px] border-r border-gray-200">
<div className="grow overflow-y-auto p-4 pb-[100px]">
<h2 className="mb-0 text-lg font-bold">Customize Your Theme</h2>
<p className="text-sm mb-4 text-gray-300">
Expand Down Expand Up @@ -147,7 +147,7 @@ const ThemeBuilder = () => {
</Button>
</footer>
</aside>
<main className="flex-1 flex flex-col items-center">
<main className="flex-1 flex flex-col items-center overflow-y-auto h-full">
{customThemeConfig && (
<div className="max-w-screen-xl w-full py-4 px-10">
<h2 className="text-xl font-bold mb-4">Example Charts</h2>
Expand Down Expand Up @@ -190,6 +190,21 @@ const ThemeBuilder = () => {
</VictoryStack>
</VictoryChart>
</div>
<div>
<h3 className="text-base font-bold mb-3">Area Chart</h3>
<VictoryChart
theme={customThemeConfig}
domainPadding={20}
style={chartStyle}
>
<VictoryAxis label="X Axis" />
<VictoryAxis dependentAxis label="Y Axis" />
<VictoryArea
data={sampleStackData}
labels={({ datum }) => datum.y}
/>
</VictoryChart>
</div>
</div>
</div>
)}
Expand Down
78 changes: 59 additions & 19 deletions demo/ts/components/theme-builder/options-config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
const getBaseLabelsConfig = (basePath: string) => [
{
type: "slider",
label: "Font Size",
min: 10,
max: 24,
unit: "px",
path: `${basePath}.fontSize`,
},
{
type: "slider",
label: "Padding",
min: 0,
max: 50,
unit: "px",
path: `${basePath}.padding`,
},
{
type: "colorPicker",
label: "Fill",
path: `${basePath}.fill`,
},
];

const optionsConfig = [
{
type: "section",
title: "Color Options",
title: "Palette",
fields: [
{
type: "colorScale",
Expand All @@ -11,28 +35,44 @@ const optionsConfig = [
},
{
type: "section",
title: "Axis Label Options",
title: "Axis Labels",
fields: getBaseLabelsConfig("axis.style.axisLabel"),
},
{
type: "section",
title: "Area Chart",
fields: [
{
type: "slider",
label: "Font Size",
min: 10,
max: 24,
unit: "px",
path: "axis.style.axisLabel.fontSize",
},
{
type: "slider",
label: "Padding",
min: 0,
max: 50,
unit: "px",
path: "axis.style.axisLabel.padding",
type: "section",
label: "Data",
fields: [
{
type: "slider",
label: "Fill Opacity",
min: 0,
max: 1,
step: 0.1,
path: "area.style.data.fillOpacity",
},
{
type: "slider",
label: "Stroke Width",
min: 0,
max: 5,
unit: "px",
path: "area.style.data.strokeWidth",
},
{
type: "colorPicker",
label: "Fill",
path: "area.style.data.fill",
},
],
},
{
type: "colorPicker",
label: "Fill",
path: "axis.style.axisLabel.fill",
type: "section",
label: "Labels",
fields: getBaseLabelsConfig("area.style.labels"),
},
],
},
Expand Down
9 changes: 7 additions & 2 deletions demo/ts/components/theme-builder/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ type SliderProps = {
onChange?: (value: number) => void;
min?: number;
max?: number;
step?: number;
className?: string;
};

const Slider = ({
label,
id,
value,
unit = "px",
unit,
onChange,
min,
max,
step = 1,
className,
}: SliderProps) => {
const handleChange = (event) => {
const newValue = event.target.value;
Expand All @@ -27,7 +31,7 @@ const Slider = ({
};

return (
<div className="my-4">
<div className={className}>
<label
htmlFor={id}
className="block mb-1 text-sm font-medium text-gray-900 dark:text-white"
Expand All @@ -43,6 +47,7 @@ const Slider = ({
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
min={min}
max={max}
step={step}
/>
</div>
);
Expand Down
Loading
Loading