Skip to content

Commit ebc5cf8

Browse files
authored
feat(chart): add BubbleMap chart component (#602)
1 parent a74bd9c commit ebc5cf8

14 files changed

Lines changed: 1284 additions & 18 deletions

File tree

.changeset/spicy-maps-glow.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@cloudflare/kumo": minor
3+
---
4+
5+
feat(chart): add `BubbleMap` chart component
6+
7+
New `BubbleMap` component renders proportional bubbles over a registered
8+
geographic map using ECharts' scatter series. Includes value-based radius
9+
scaling, a `mapColors` palette addition to `ChartPalette`, and supporting
10+
types. Also extracts `escapeHtml` / `defaultValueFormat` tooltip helpers into a
11+
shared `tooltip-utils` module reused by `SankeyChart`.

packages/kumo-docs-astro/src/components/SidebarNav.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ const chartItems: NavItem[] = [
8686
{ label: "Charts", href: "/charts" },
8787
{ label: "Colors", href: "/charts/colors" },
8888
{ label: "Timeseries", href: "/charts/timeseries" },
89+
{ label: "Maps", href: "/charts/maps" },
8990
{ label: "Sankey", href: "/charts/sankey" },
9091
{ label: "Custom Chart", href: "/charts/custom" },
9192
];

packages/kumo-docs-astro/src/components/ThemeToggle.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,43 @@ export function ThemeToggle() {
77
const [mounted, setMounted] = useState(false);
88

99
useEffect(() => {
10+
const getCurrentTheme = () => {
11+
const mode = document.documentElement.getAttribute("data-mode");
12+
if (mode === "dark" || mode === "light") return mode;
13+
14+
const stored = localStorage.getItem("theme");
15+
if (stored === "dark" || stored === "light") return stored;
16+
17+
return window.matchMedia("(prefers-color-scheme: dark)").matches
18+
? "dark"
19+
: "light";
20+
};
21+
22+
const handleThemeChange = (event: Event) => {
23+
const nextTheme = (event as CustomEvent<{ theme?: "light" | "dark" }>)
24+
.detail?.theme;
25+
if (nextTheme === "dark" || nextTheme === "light") {
26+
setTheme(nextTheme);
27+
}
28+
};
29+
1030
setMounted(true);
11-
const stored = localStorage.getItem("theme");
12-
if (stored === "dark" || stored === "light") {
13-
setTheme(stored);
14-
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
15-
setTheme("dark");
16-
}
31+
setTheme(getCurrentTheme());
32+
window.addEventListener("kumo:theme-change", handleThemeChange);
33+
34+
return () => {
35+
window.removeEventListener("kumo:theme-change", handleThemeChange);
36+
};
1737
}, []);
1838

1939
const toggleTheme = () => {
2040
const newTheme = theme === "light" ? "dark" : "light";
2141
setTheme(newTheme);
2242
localStorage.setItem("theme", newTheme);
2343
document.documentElement.setAttribute("data-mode", newTheme);
44+
window.dispatchEvent(
45+
new CustomEvent("kumo:theme-change", { detail: { theme: newTheme } }),
46+
);
2447
};
2548

2649
// Prevent hydration mismatch
@@ -37,6 +60,7 @@ export function ThemeToggle() {
3760
variant="ghost"
3861
shape="square"
3962
aria-label={`Switch to ${theme === "light" ? "dark" : "light"} mode`}
63+
title="Toggle theme (D)"
4064
onClick={toggleTheme}
4165
>
4266
{theme === "light" ? <MoonIcon size={20} /> : <SunIcon size={20} />}

0 commit comments

Comments
 (0)