Skip to content

Commit

Permalink
Merge pull request #1230 from visualize-admin/feat/combo-chart-improv…
Browse files Browse the repository at this point in the history
…ements

feat: Combo charts improvements
  • Loading branch information
bprusinowski authored Oct 24, 2023
2 parents fff1c84 + 561e7e8 commit 127646d
Show file tree
Hide file tree
Showing 36 changed files with 1,125 additions and 398 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ You can also check the [release page](https://github.com/visualize-admin/visuali

## Unreleased

- Features
- It's now possible to adjust Combo charts colors 🧑‍🎨
- Fixes
- Color picker in now in sync with selected color palette
- Performance
- Improved the performance of data download
- (min|max)Inclusive values stored in `sh:or` are now also retrieved
- Style
- Color picker's design has been adjusted to be more user-friendly
- Map now outlines shapes on hover, instead of changing their colors
- Maintenance
- Added retrieval of dimension units via `qudt:hasUnit` (but kept `qudt:unit` for backward compatibility)
Expand Down
3 changes: 2 additions & 1 deletion app/charts/area/areas-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
scaleOrdinal,
ScaleTime,
scaleTime,
schemeCategory10,
stack,
stackOrderAscending,
stackOrderDescending,
Expand Down Expand Up @@ -251,7 +252,7 @@ const useAreasState = (

return {
label: segment,
color: fields.segment?.colorMapping![dvIri] ?? "#006699",
color: fields.segment?.colorMapping![dvIri] ?? schemeCategory10[0],
};
});

Expand Down
27 changes: 27 additions & 0 deletions app/charts/chart-config-ui-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ type EncodingOption<T extends ChartConfig = ChartConfig> =
}
| {
field: "useAbbreviations";
}
| {
field: "lineAxisOrientation";
onChange: OnEncodingOptionChange<"left" | "right", ComboLineColumnConfig>;
};

const onColorComponentScaleTypeChange: OnEncodingOptionChange<
Expand Down Expand Up @@ -928,6 +932,27 @@ const chartConfigOptionsUISpec: ChartSpecs = {
customComponent: true,
componentTypes: ["NumericalMeasure"],
filters: false,
options: {
lineAxisOrientation: {
onChange: (_, options) => {
const { chartConfig } = options;
// Need the correct order to not enable "Reset color palette" button.
const firstIri =
chartConfig.fields.y.lineAxisOrientation === "left"
? chartConfig.fields.y.columnComponentIri
: chartConfig.fields.y.lineComponentIri;
const secondIri =
chartConfig.fields.y.lineAxisOrientation === "left"
? chartConfig.fields.y.lineComponentIri
: chartConfig.fields.y.columnComponentIri;

chartConfig.fields.y.colorMapping = {
[firstIri]: chartConfig.fields.y.colorMapping[secondIri],
[secondIri]: chartConfig.fields.y.colorMapping[firstIri],
};
},
},
},
},
{
field: "x",
Expand Down Expand Up @@ -967,5 +992,7 @@ export const getChartFieldOptionChangeSideEffect = (
case "areaLayer.color.scaleType":
case "symbolLayer.color.scaleType":
return get(encoding, "options.colorComponent.onScaleTypeChange");
case "y.lineAxisOrientation":
return get(encoding, "options.lineAxisOrientation.onChange");
}
};
3 changes: 2 additions & 1 deletion app/charts/column/columns-grouped-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ScaleOrdinal,
scaleOrdinal,
scaleTime,
schemeCategory10,
sum,
} from "d3";
import orderBy from "lodash/orderBy";
Expand Down Expand Up @@ -196,7 +197,7 @@ const useColumnsGroupedState = (

return {
label: segment,
color: fields.segment?.colorMapping![dvIri] || "#006699",
color: fields.segment?.colorMapping![dvIri] ?? schemeCategory10[0],
};
});

Expand Down
3 changes: 2 additions & 1 deletion app/charts/column/columns-stacked-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ScaleOrdinal,
scaleOrdinal,
scaleTime,
schemeCategory10,
stack,
stackOffsetDiverging,
stackOrderAscending,
Expand Down Expand Up @@ -236,7 +237,7 @@ const useColumnsStackedState = (

return {
label: segment,
color: fields.segment?.colorMapping![dvIri] || "#006699",
color: fields.segment?.colorMapping![dvIri] ?? schemeCategory10[0],
};
});

Expand Down
4 changes: 2 additions & 2 deletions app/charts/column/columns.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { schemeCategory10 } from "d3";
import React from "react";

import { ColumnsState } from "@/charts/column/columns-state";
Expand Down Expand Up @@ -79,7 +80,7 @@ export const Columns = () => {
const y0 = yScale(0);
const renderData: RenderColumnDatum[] = React.useMemo(() => {
const getColor = (d: number) => {
return d <= 0 ? theme.palette.secondary.main : theme.palette.primary.main;
return d <= 0 ? theme.palette.secondary.main : schemeCategory10[0];
};

return chartData.map((d) => {
Expand Down Expand Up @@ -108,7 +109,6 @@ export const Columns = () => {
xScale,
yScale,
y0,
theme.palette.primary.main,
theme.palette.secondary.main,
getRenderingKey,
]);
Expand Down
38 changes: 27 additions & 11 deletions app/charts/combo/axis-height-linear-dual.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { alpha } from "@mui/material";
import React from "react";

import { ComboLineColumnState } from "@/charts/combo/combo-line-column-state";
Expand All @@ -10,16 +9,20 @@ import {
import { useChartState } from "@/charts/shared/chart-state";
import { useChartTheme } from "@/charts/shared/use-chart-theme";
import { OpenMetadataPanelWrapper } from "@/components/metadata-panel";
import { theme } from "@/themes/federal";
import { getTextWidth } from "@/utils/get-text-width";

const TITLE_HPADDING = 8;
const TITLE_VPADDING = 4;

type AxisHeightLinearDualProps = {
orientation?: "left" | "right";
};

export const AxisHeightLinearDual = (props: AxisHeightLinearDualProps) => {
const { orientation = "left" } = props;
const leftAligned = orientation === "left";
const { axisLabelFontSize } = useChartTheme();
const { gridColor, labelColor, axisLabelFontSize } = useChartTheme();
const [ref, setRef] = React.useState<SVGGElement | null>(null);
const { y, yOrientationScales, colors, bounds, maxRightTickWidth } =
useChartState() as ComboLineDualState | ComboLineColumnState;
Expand All @@ -32,13 +35,13 @@ export const AxisHeightLinearDual = (props: AxisHeightLinearDualProps) => {

useRenderAxisHeightLinear(ref, {
id: `axis-height-linear-${orientation}`,
orientation: orientation,
orientation,
scale: yScale,
width: bounds.chartWidth,
height: bounds.chartHeight,
margins: bounds.margins,
lineColor: alpha(color, 0.1),
textColor: color,
margins,
lineColor: gridColor,
textColor: labelColor,
});

return (
Expand All @@ -52,14 +55,27 @@ export const AxisHeightLinearDual = (props: AxisHeightLinearDualProps) => {
axisTitleWidth +
// Align the title with the rightmost tick.
maxRightTickWidth +
TICK_PADDING
TICK_PADDING -
TITLE_HPADDING * 2
}
width={axisTitleWidth}
height={axisLabelFontSize * 2}
color={color}
width={axisTitleWidth + TITLE_HPADDING * 2}
height={(axisLabelFontSize + TITLE_VPADDING) * 2}
color={theme.palette.getContrastText(color)}
>
<OpenMetadataPanelWrapper dim={y[orientation].dimension}>
<span style={{ fontSize: axisLabelFontSize }}>{axisTitle}</span>
<span
style={{
fontSize: axisLabelFontSize,
backgroundColor: color,
paddingTop: TITLE_VPADDING,
paddingBottom: TITLE_VPADDING,
paddingLeft: TITLE_HPADDING,
paddingRight: TITLE_HPADDING,
borderRadius: 4,
}}
>
{axisTitle}
</span>
</OpenMetadataPanelWrapper>
</foreignObject>
<g ref={(newRef) => setRef(newRef)} />
Expand Down
2 changes: 2 additions & 0 deletions app/charts/combo/combo-line-column-state-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const useComboLineColumnStateVariables = (
dimension: measuresByIri[lineIri],
iri: lineIri,
label: getLabelWithUnit(measuresByIri[lineIri]),
color: fields.y.colorMapping[lineIri],
getY: (d) => {
return d[lineIri] !== null ? Number(d[lineIri]) : null;
},
Expand All @@ -75,6 +76,7 @@ export const useComboLineColumnStateVariables = (
dimension: measuresByIri[columnIri],
iri: columnIri,
label: getLabelWithUnit(measuresByIri[columnIri]),
color: fields.y.colorMapping[columnIri],
getY: (d) => {
return d[columnIri] !== null ? Number(d[columnIri]) : null;
},
Expand Down
2 changes: 1 addition & 1 deletion app/charts/combo/combo-line-column-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ const useComboLineColumnState = (
const xScaled = (xScale(x) as number) + xScale.bandwidth() * 0.5;

return {
datum: { label: "", value: "0", color: "#006699" },
datum: { label: "", value: "0", color: d3.schemeCategory10[0] },
xAnchor: xScaled,
yAnchor:
[variables.y.left, variables.y.right]
Expand Down
2 changes: 2 additions & 0 deletions app/charts/combo/combo-line-dual-state-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const useComboLineDualStateVariables = (
dimension: measuresByIri[leftIri],
iri: leftIri,
label: getLabelWithUnit(measuresByIri[leftIri]),
color: fields.y.colorMapping[leftIri],
getY: (d) => {
return d[leftIri] !== null ? Number(d[leftIri]) : null;
},
Expand All @@ -58,6 +59,7 @@ export const useComboLineDualStateVariables = (
dimension: measuresByIri[rightIri],
iri: rightIri,
label: getLabelWithUnit(measuresByIri[rightIri]),
color: fields.y.colorMapping[rightIri],
getY: (d) => {
return d[rightIri] !== null ? Number(d[rightIri]) : null;
},
Expand Down
2 changes: 1 addition & 1 deletion app/charts/combo/combo-line-dual-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const useComboLineDualState = (
const xScaled = xScale(x);

return {
datum: { label: "", value: "0", color: "#006699" },
datum: { label: "", value: "0", color: d3.schemeCategory10[0] },
xAnchor: xScaled,
yAnchor:
[variables.y.left, variables.y.right]
Expand Down
1 change: 1 addition & 0 deletions app/charts/combo/combo-line-single-state-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const useComboLineSingleStateVariables = (
dimension: measuresByIri[iri],
iri,
label: measuresByIri[iri].label,
color: fields.y.colorMapping[iri],
getY: (d) => {
return d[iri] !== null ? Number(d[iri]) : null;
},
Expand Down
2 changes: 1 addition & 1 deletion app/charts/combo/combo-line-single-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const useComboLineSingleState = (
const xScaled = xScale(x);

return {
datum: { label: "", value: "0", color: "#006699" },
datum: { label: "", value: "0", color: d3.schemeCategory10[0] },
xAnchor: xScaled,
yAnchor: yScale(
variables.y.lines
Expand Down
1 change: 1 addition & 0 deletions app/charts/combo/combo-state-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type BaseYGetter = {
dimension: DimensionMetadataFragment;
iri: string;
label: string;
color: string;
getY: (d: Observation) => number | null;
};

Expand Down
4 changes: 2 additions & 2 deletions app/charts/combo/combo-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import React from "react";
import { useWidth } from "@/charts/shared/use-width";
import { Observation } from "@/domain/data";
import { useFormatNumber, useTimeFormatUnit } from "@/formatters";
import { getPalette } from "@/palettes";

type UseCommonComboStateOptions = {
chartData: Observation[];
Expand All @@ -15,6 +14,7 @@ type UseCommonComboStateOptions = {
yGetters: {
label: string;
getY: (d: Observation) => number | null;
color: string;
}[];
computeTotal: boolean;
};
Expand Down Expand Up @@ -74,7 +74,7 @@ export const useCommonComboState = (options: UseCommonComboStateOptions) => {

const colors = React.useMemo(() => {
const domain = yGetters.map((d) => d.label);
const range = getPalette();
const range = yGetters.map((d) => d.color);

return d3.scaleOrdinal<string, string>().domain(domain).range(range);
}, [yGetters]);
Expand Down
Loading

1 comment on commit 127646d

@vercel
Copy link

@vercel vercel bot commented on 127646d Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visualization-tool – ./

visualization-tool-git-main-ixt1.vercel.app
visualization-tool-alpha.vercel.app
visualization-tool-ixt1.vercel.app

Please sign in to comment.