diff --git a/webapp/src/features/charts/soil/config.ts b/webapp/src/features/charts/soil/config.ts index b2f3672a..573d4034 100644 --- a/webapp/src/features/charts/soil/config.ts +++ b/webapp/src/features/charts/soil/config.ts @@ -1,7 +1,8 @@ export const SUNBURST_LAYOUT = { - height: 360, + // Let Plotly fill its container (see chart-taxon-abundance) instead of a + // fixed width/height, so the chart expands with the popup like the base charts. + autosize: true, margin: { b: 20, l: 20, r: 20, t: 20 }, paper_bgcolor: "rgba(0,0,0,0)", plot_bgcolor: "rgba(0,0,0,0)", - width: 360, }; diff --git a/webapp/src/features/charts/soil/ui/chart-taxon-abundance.tsx b/webapp/src/features/charts/soil/ui/chart-taxon-abundance.tsx index 091e0daa..5442ca62 100644 --- a/webapp/src/features/charts/soil/ui/chart-taxon-abundance.tsx +++ b/webapp/src/features/charts/soil/ui/chart-taxon-abundance.tsx @@ -1,4 +1,5 @@ import type { Data as PlotlyData } from "plotly.js"; +import { useEffect, useRef } from "react"; import Plot from "react-plotly.js"; import { @@ -18,10 +19,12 @@ export const ChartTaxonAbundance: ChartComponentType = ({ dataType, }) => { const { t } = useTranslation(["common", "all4trees"]); + const dataEntries = Object.entries(data); const hasTaxonData = dataEntries.some(([key]) => key.trim() !== ""); let sunburstData: PlotlyData[] = []; const cardHeight = hasTaxonData ? "min-h-105" : "min-h-40"; + if (hasTaxonData) { // Remove taxon entries with "Aucun" value const filteredDataEntries = dataEntries.filter( @@ -45,6 +48,25 @@ export const ChartTaxonAbundance: ChartComponentType = ({ } as SunburstTrace, ] as unknown as PlotlyData[]; } + + // Plotly (via react-plotly's `useResizeHandler`) only refits on window + // resize, so it misses container-only changes such as toggling the popup + // size. Observe the wrapper and forward those changes as a resize event so + // the sunburst adapts like the recharts base charts. + const wrapperRef = useRef(null); + + useEffect(() => { + if (!hasTaxonData) return; + const wrapper = wrapperRef.current; + if (!wrapper) return; + // Use react-plotly's own resize handler (which refits to the container) + const observer = new ResizeObserver(() => { + window.dispatchEvent(new Event("resize")); + }); + observer.observe(wrapper); + return () => observer.disconnect(); + }, [hasTaxonData]); + return ( = ({ >
{hasTaxonData && ( - + // Style - Extend the width to the container, keep a square aspect and + // stay centered. Limit width to 600px to avoid an oversized chart. +
+ +
)} {!hasTaxonData && (
= ({ {chartIndicators.length > 0 && (
{chartIndicators.map((child, index) => ( + // `w-0 min-w-full` makes each chart fill the available width without + // contributing to the popup's intrinsic (max-content) width. Charts + // are `w-full` and would otherwise pin the shrink-to-fit popup to + // their widest rendered size, so it could never shrink back after + // being maximized. This keeps the popup width driven by its textual + // content only, so toggling the size returns to the fit-content width.
key={`chart-indicator-${index}`} >