fix: polish chart legends
All checks were successful
CI / Lint, test, typecheck and build (push) Successful in 9m58s

This commit is contained in:
zv
2026-06-14 21:03:13 +02:00
parent 169d5e5e59
commit b1cbc771f8

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { Bar, CartesianGrid, ComposedChart, Legend, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; import { Bar, CartesianGrid, ComposedChart, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
import { Card } from "@/components/ui/card"; import { Card } from "@/components/ui/card";
import { ChartTooltip } from "@/components/charts/chart-tooltip"; import { ChartTooltip } from "@/components/charts/chart-tooltip";
import { CHART_COLORS } from "@/lib/chart-theme"; import { CHART_COLORS } from "@/lib/chart-theme";
@@ -12,10 +12,37 @@ import type { HourlyForecast } from "@/types/forecast";
const INITIAL_CHART_DIMENSION = { width: 1, height: 1 }; const INITIAL_CHART_DIMENSION = { width: 1, height: 1 };
interface ChartLegendItem {
color: string;
label: string;
marker: "bar" | "line" | "dashed-line";
}
function formatHour(value: string) { function formatHour(value: string) {
return value.slice(11, 16); return value.slice(11, 16);
} }
function ChartLegend({ items }: { items: ChartLegendItem[] }) {
return (
<div className="mt-2 flex flex-wrap items-center gap-x-4 gap-y-2 text-[0.72rem] font-medium text-muted">
{items.map((item) => (
<span className="inline-flex items-center gap-1.5" key={item.label}>
{item.marker === "bar" ? (
<span className="h-2.5 w-3 rounded-t-[5px]" style={{ backgroundColor: item.color }} aria-hidden="true" />
) : (
<span
className={`h-0 w-5 border-t-2 ${item.marker === "dashed-line" ? "border-dashed" : "border-solid"}`}
style={{ borderColor: item.color }}
aria-hidden="true"
/>
)}
{item.label}
</span>
))}
</div>
);
}
export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) { export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) {
const { language, t } = useI18n(); const { language, t } = useI18n();
const temperatureUnit = useWeatherStore((state) => state.temperatureUnit); const temperatureUnit = useWeatherStore((state) => state.temperatureUnit);
@@ -27,6 +54,14 @@ export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) {
precipitationProbability: hour.precipitationProbability, precipitationProbability: hour.precipitationProbability,
})); }));
const temperatureUnitLabel = getTemperatureUnitLabel(temperatureUnit); const temperatureUnitLabel = getTemperatureUnitLabel(temperatureUnit);
const temperatureLegendItems: ChartLegendItem[] = [
{ color: CHART_COLORS.temperature, label: t("forecast.temperature"), marker: "line" },
{ color: CHART_COLORS.feelsLike, label: t("forecast.apparentTemperature"), marker: "dashed-line" },
];
const rainfallLegendItems: ChartLegendItem[] = [
{ color: CHART_COLORS.rainfall, label: t("forecast.precipitation"), marker: "bar" },
{ color: CHART_COLORS.probability, label: t("forecast.precipitationProbability"), marker: "line" },
];
return ( return (
<div className="grid gap-3 lg:grid-cols-2"> <div className="grid gap-3 lg:grid-cols-2">
@@ -68,7 +103,6 @@ export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) {
/> />
} }
/> />
<Legend wrapperStyle={{ fontSize: "0.72rem" }} />
<Line <Line
type="monotone" type="monotone"
dataKey="temperature" dataKey="temperature"
@@ -91,6 +125,7 @@ export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) {
</ComposedChart> </ComposedChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
<ChartLegend items={temperatureLegendItems} />
</Card> </Card>
<Card className="p-4 sm:p-5"> <Card className="p-4 sm:p-5">
@@ -141,7 +176,6 @@ export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) {
/> />
} }
/> />
<Legend wrapperStyle={{ fontSize: "0.72rem" }} />
<Bar <Bar
yAxisId="rainfall" yAxisId="rainfall"
dataKey="precipitation" dataKey="precipitation"
@@ -162,6 +196,7 @@ export function DayForecastCharts({ hours }: { hours: HourlyForecast[] }) {
</ComposedChart> </ComposedChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
<ChartLegend items={rainfallLegendItems} />
</Card> </Card>
</div> </div>
); );