Background color scheme

This commit is contained in:
2026-01-29 20:59:22 +01:00
parent 27e7b59b1a
commit 1fb07409f8
+91 -13
View File
@@ -14,6 +14,41 @@ type Row = Record<string, number>;
type PlotType = "scatter" | "surface";
type ThemeScheme = "light" | "dark" | "transparent";
const THEME_SCHEMES: Record<
ThemeScheme,
{
paperBg: string;
plotBg: string;
fontColor: string;
gridColor: string;
mainClass: string;
}
> = {
dark: {
paperBg: "#0b0d12",
plotBg: "#0b0d12",
fontColor: "#cfd3ff",
gridColor: "rgba(148, 163, 184, 0.25)",
mainClass: "bg-[#0b0d12]",
},
light: {
paperBg: "#f8fafc",
plotBg: "#f8fafc",
fontColor: "#1e293b",
gridColor: "rgba(148, 163, 184, 0.5)",
mainClass: "bg-slate-100",
},
transparent: {
paperBg: "rgba(0,0,0,0)",
plotBg: "rgba(0,0,0,0)",
fontColor: "#475569",
gridColor: "rgba(100, 116, 139, 0.4)",
mainClass: "bg-transparent",
},
};
const COLORSCALES = [
"Viridis",
"Plasma",
@@ -41,6 +76,7 @@ export default function Home() {
const [z, setZ] = useState("");
const [plotType, setPlotType] = useState<PlotType>("scatter");
const [colorscale, setColorscale] = useState<string>(COLORSCALES[0]);
const [themeScheme, setThemeScheme] = useState<ThemeScheme>("dark");
// First row after header = axis sizes (X max, Y max, Z max); rest = plot data.
const plotData = rows.length > 1 ? rows.slice(1) : rows;
@@ -118,14 +154,44 @@ export default function Home() {
},
};
const theme = THEME_SCHEMES[themeScheme];
const sceneLayout: {
xaxis: { title: { text: string }; range?: [number, number] };
yaxis: { title: { text: string }; range?: [number, number] };
zaxis: { title: { text: string }; range?: [number, number] };
bgcolor?: string;
xaxis: {
title: { text: string };
range?: [number, number];
gridcolor?: string;
tickfont?: { color: string };
};
yaxis: {
title: { text: string };
range?: [number, number];
gridcolor?: string;
tickfont?: { color: string };
};
zaxis: {
title: { text: string };
range?: [number, number];
gridcolor?: string;
tickfont?: { color: string };
};
} = {
xaxis: { title: { text: x } },
yaxis: { title: { text: y } },
zaxis: { title: { text: z } },
bgcolor: theme.plotBg,
xaxis: {
title: { text: x },
gridcolor: theme.gridColor,
tickfont: { color: theme.fontColor },
},
yaxis: {
title: { text: y },
gridcolor: theme.gridColor,
tickfont: { color: theme.fontColor },
},
zaxis: {
title: { text: z },
gridcolor: theme.gridColor,
tickfont: { color: theme.fontColor },
},
};
if (axisSizes) {
sceneLayout.xaxis.range = [0, axisSizes.x];
@@ -137,9 +203,9 @@ export default function Home() {
plotRef.current!,
[trace],
{
paper_bgcolor: "#0b0d12",
plot_bgcolor: "#0b0d12",
font: { color: "#cfd3ff" },
paper_bgcolor: theme.paperBg,
plot_bgcolor: theme.plotBg,
font: { color: theme.fontColor },
scene: sceneLayout,
margin: { l: 0, r: 0, t: 0, b: 0 },
},
@@ -150,7 +216,7 @@ export default function Home() {
return () => {
cancelled = true;
};
}, [rows, x, y, z, plotType, colorscale]);
}, [rows, x, y, z, plotType, colorscale, themeScheme]);
function onFile(file: File) {
@@ -204,9 +270,9 @@ export default function Home() {
}
return (
<div className="h-screen grid grid-cols-[280px_1fr]">
<div className="h-screen grid grid-cols-[280px_1fr] overflow-y-hidden">
{/* Sidebar */}
<aside className="bg-panel p-4 space-y-4">
<aside className="bg-panel p-4 space-y-4 overflow-y-scroll">
<div className="text-lg font-semibold">
3dplot-gen
<div className="text-xs text-muted">CSV → 3D Plot</div>
@@ -300,6 +366,18 @@ export default function Home() {
</select>
</Control>
<Control label="Background">
<select
className="w-full bg-neutral-900 border border-slate-700 rounded px-2 py-1"
value={themeScheme}
onChange={(e) => setThemeScheme(e.target.value as ThemeScheme)}
>
<option value="dark">Dark</option>
<option value="light">Light</option>
<option value="transparent">Transparent</option>
</select>
</Control>
{plotType === "surface" &&
plotData.length > 0 &&
buildSurfaceGrid() === null && (
@@ -317,7 +395,7 @@ export default function Home() {
</aside>
{/* Plot */}
<main className="bg-plot">
<main className={THEME_SCHEMES[themeScheme].mainClass}>
<div ref={plotRef} className="w-full h-full" />
</main>
</div>