Bar Chart with patterns from the theme

The fill of a theme entry can be a fill object, the same as the fill of a Bar. Here every entry of the active theme keeps its color and gets one of the built-in patterns, so the Bars tell their series apart without relying on color alone, and without setting any fill themselves.
import { useMemo } from 'react';
import {
  Bar,
  BarChart,
  CartesianGrid,
  Legend,
  RechartsTheme,
  RechartsThemeProvider,
  Tooltip,
  XAxis,
  YAxis,
  lightTheme,
  pattern,
  patterns,
  useRechartsTheme,
} from 'recharts';
import { RechartsDevtools } from '@recharts/devtools';

// #region Sample data
const data = [
  { name: 'Q1', north: 590, south: 800, east: 1400, west: 490 },
  { name: 'Q2', north: 868, south: 967, east: 1506, west: 590 },
  { name: 'Q3', north: 1397, south: 1098, east: 989, west: 350 },
];

// #endregion
const chartStyle = { width: '100%', maxWidth: '700px', maxHeight: '70vh', aspectRatio: 1.618 };
const chartMargin = { top: 20, right: 0, left: 0, bottom: 5 };

// One pattern per series. Create the definitions once, outside of components.
const seriesPatterns = [
  pattern(patterns.diagonal),
  pattern(patterns.star),
  pattern(patterns.crosshatch),
  pattern(patterns.diamond),
  pattern(patterns.triangle),
];

// Adds a pattern to each graphical item of a theme, and keeps its colors.
function withPatterns(theme: RechartsTheme): RechartsTheme {
  return {
    ...theme,
    graphicalItems: theme.graphicalItems.map((item, index) => {
      const definition = seriesPatterns[index % seriesPatterns.length];
      if (definition == null) {
        return item;
      }
      return { ...item, fill: { color: typeof item.fill === 'object' ? item.fill.color : item.fill, definition } };
    }),
  };
}

const BarChartWithThemePatterns = ({ isAnimationActive = true }: { isAnimationActive?: boolean }) => {
  // Build on the active theme, so the example follows light and dark mode.
  const theme = useRechartsTheme() ?? lightTheme;
  const patternedTheme = useMemo(() => withPatterns(theme), [theme]);
  return (
    <RechartsThemeProvider value={patternedTheme}>
      {/* The Bars set no fill: each one takes the color and the pattern of its theme entry */}
      <BarChart style={chartStyle} responsive data={data} margin={chartMargin}>
        <CartesianGrid />
        <XAxis dataKey="name" />
        <YAxis width="auto" />
        <Tooltip />
        <Legend iconSize={32} />
        <Bar dataKey="north" isAnimationActive={isAnimationActive} />
        <Bar dataKey="south" isAnimationActive={isAnimationActive} />
        <Bar dataKey="east" isAnimationActive={isAnimationActive} />
        <Bar dataKey="west" isAnimationActive={isAnimationActive} />
        <RechartsDevtools />
      </BarChart>
    </RechartsThemeProvider>
  );
};

export default BarChartWithThemePatterns;