Add dark mode support with persisted OS-aware theme selection
This commit is contained in:
@@ -25,6 +25,7 @@ import {
|
||||
CHART_PALETTE,
|
||||
resolveFluentToken,
|
||||
} from "../utils/chartTheme";
|
||||
import { useThemeMode } from "../providers/ThemeProvider";
|
||||
import { ChartStateWrapper } from "./ChartStateWrapper";
|
||||
import { useBanTrend } from "../hooks/useBanTrend";
|
||||
import type { BanOriginFilter, TimeRange } from "../types/ban";
|
||||
@@ -200,29 +201,36 @@ export const BanTrendChart = memo(function BanTrendChart({
|
||||
source = "fail2ban",
|
||||
}: BanTrendChartProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { colorMode } = useThemeMode();
|
||||
const { buckets, loading, error, reload } = useBanTrend(timeRange, origin, source);
|
||||
|
||||
const isEmpty = buckets.every((b) => b.count === 0);
|
||||
const entries = buildEntries(buckets, timeRange);
|
||||
const { primaryColour, axisColour, gridColour } = useMemo(
|
||||
() => ({
|
||||
primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
|
||||
axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
|
||||
gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
|
||||
}),
|
||||
[],
|
||||
() => {
|
||||
void colorMode;
|
||||
return {
|
||||
primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
|
||||
axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
|
||||
gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
|
||||
};
|
||||
},
|
||||
[colorMode],
|
||||
);
|
||||
const tickInterval = TICK_INTERVAL[timeRange];
|
||||
|
||||
const tooltipContent = useMemo(
|
||||
() => (
|
||||
<TrendTooltip
|
||||
backgroundColor={resolveFluentToken(tokens.colorNeutralBackground1)}
|
||||
borderColor={resolveFluentToken(tokens.colorNeutralStroke2)}
|
||||
textColor={resolveFluentToken(tokens.colorNeutralForeground1)}
|
||||
/>
|
||||
),
|
||||
[],
|
||||
() => {
|
||||
void colorMode;
|
||||
return (
|
||||
<TrendTooltip
|
||||
backgroundColor={resolveFluentToken(tokens.colorNeutralBackground1)}
|
||||
borderColor={resolveFluentToken(tokens.colorNeutralStroke2)}
|
||||
textColor={resolveFluentToken(tokens.colorNeutralForeground1)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[colorMode],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
CHART_PALETTE,
|
||||
resolveFluentToken,
|
||||
} from "../utils/chartTheme";
|
||||
import { useThemeMode } from "../providers/ThemeProvider";
|
||||
import { ChartStateWrapper } from "./ChartStateWrapper";
|
||||
import { ChartTooltip } from "./ChartTooltip";
|
||||
import { useJailDistribution } from "../hooks/useJailDistribution";
|
||||
@@ -134,17 +135,21 @@ export const JailDistributionChart = memo(function JailDistributionChart({
|
||||
origin,
|
||||
}: JailDistributionChartProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { colorMode } = useThemeMode();
|
||||
const { jails, loading, error, reload } = useJailDistribution(timeRange, origin);
|
||||
|
||||
const entries = buildEntries(jails);
|
||||
const chartHeight = Math.max(entries.length * BAR_HEIGHT_PX, MIN_CHART_HEIGHT);
|
||||
const { primaryColour, axisColour, gridColour } = useMemo(
|
||||
() => ({
|
||||
primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
|
||||
axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
|
||||
gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
|
||||
}),
|
||||
[],
|
||||
() => {
|
||||
void colorMode;
|
||||
return {
|
||||
primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
|
||||
axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
|
||||
gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
|
||||
};
|
||||
},
|
||||
[colorMode],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
CHART_GRID_LINE_TOKEN,
|
||||
resolveFluentToken,
|
||||
} from "../utils/chartTheme";
|
||||
import { useThemeMode } from "../providers/ThemeProvider";
|
||||
import { ChartTooltip } from "./ChartTooltip";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -142,16 +143,20 @@ export const TopCountriesBarChart = memo(function TopCountriesBarChart({
|
||||
countryNames,
|
||||
}: TopCountriesBarChartProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { colorMode } = useThemeMode();
|
||||
|
||||
const entries = buildEntries(countries, countryNames);
|
||||
|
||||
const { primaryColour, axisColour, gridColour } = useMemo(
|
||||
() => ({
|
||||
primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
|
||||
axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
|
||||
gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
|
||||
}),
|
||||
[],
|
||||
() => {
|
||||
void colorMode;
|
||||
return {
|
||||
primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
|
||||
axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
|
||||
gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
|
||||
};
|
||||
},
|
||||
[colorMode],
|
||||
);
|
||||
|
||||
if (entries.length === 0) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { LegendPayload } from "recharts/types/component/DefaultLegendConten
|
||||
import type { TooltipContentProps } from "recharts/types/component/Tooltip";
|
||||
import { tokens, makeStyles, Text } from "@fluentui/react-components";
|
||||
import { CHART_PALETTE, resolveFluentToken } from "../utils/chartTheme";
|
||||
import { useThemeMode } from "../providers/ThemeProvider";
|
||||
import { ChartTooltip } from "./ChartTooltip";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -134,10 +135,14 @@ export const TopCountriesPieChart = memo(function TopCountriesPieChart({
|
||||
countryNames,
|
||||
}: TopCountriesPieChartProps): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { colorMode } = useThemeMode();
|
||||
|
||||
const resolvedPalette = useMemo(
|
||||
() => CHART_PALETTE.map(resolveFluentToken),
|
||||
[],
|
||||
() => {
|
||||
void colorMode;
|
||||
return CHART_PALETTE.map(resolveFluentToken);
|
||||
},
|
||||
[colorMode],
|
||||
);
|
||||
const slices = buildSlices(countries, countryNames, resolvedPalette);
|
||||
const total = slices.reduce((sum, s) => sum + s.value, 0);
|
||||
|
||||
Reference in New Issue
Block a user