{"spec_id":"errorbar-basic","library":"muix","language":"javascript","code":"// anyplot.ai\n// errorbar-basic: Basic Error Bar Plot\n// Library: muix 7.29.1 | JavaScript 22.23.0\n// Quality: 88/100 | Created: 2026-06-30\n//# anyplot-orientation: landscape\n// anyplot.ai\n// errorbar-basic: Basic Error Bar Plot\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-06-30\n\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { BarPlot } from \"@mui/x-charts/BarChart\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { ChartsGrid } from \"@mui/x-charts/ChartsGrid\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport { useXScale, useYScale } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Plant stress experiment: mean stem elongation (cm/week) ± 1 SD across 7 growth conditions\nconst CONDITIONS = [\"Control\", \"Low Temp\", \"High Temp\", \"Low pH\", \"High pH\", \"Drought\", \"Flood\"];\nconst MEANS      = [4.2,       2.8,         3.1,         2.4,      3.6,       1.9,       2.2];\nconst ERRORS     = [0.5,       0.7,         0.6,         0.8,      0.5,       0.6,       0.9];\n\n// Visual hierarchy: Control=full brand green (benchmark), Drought=amber (stress/caution),\n// intermediate conditions=muted brand green to draw the eye to the key contrast\nconst BAR_COLORS = CONDITIONS.map((c) => {\n  if (c === \"Control\") return t.palette[0];   // #009E73 — optimal/reference\n  if (c === \"Drought\") return t.amber;         // #DDCC77 — peak stress (caution anchor)\n  return t.palette[0] + \"99\";                 // ~60% opacity — intermediate conditions\n});\n\n// ErrorBars renders ±1 SD whiskers using the CartesianContext scale functions\nfunction ErrorBars() {\n  const xScale = useXScale(\"x\");\n  const yScale = useYScale(\"y\");\n  if (!xScale || !yScale) return null;\n\n  const bw  = (xScale as any).bandwidth();\n  const cap = Math.round(bw * 0.19);  // 19% of bandwidth for readable caps\n\n  return (\n    <g>\n      {CONDITIONS.map((cond, i) => {\n        const cx   = (xScale as any)(cond) + bw / 2;\n        const yTop = (yScale as any)(MEANS[i] + ERRORS[i]);\n        const yBot = (yScale as any)(MEANS[i] - ERRORS[i]);\n        return (\n          <g key={cond}>\n            {/* Vertical whisker */}\n            <line x1={cx} y1={yTop} x2={cx} y2={yBot}\n                  stroke={t.ink} strokeWidth={3} strokeOpacity={0.7} strokeLinecap=\"round\" />\n            {/* Top cap */}\n            <line x1={cx - cap} y1={yTop} x2={cx + cap} y2={yTop}\n                  stroke={t.ink} strokeWidth={3} strokeOpacity={0.7} strokeLinecap=\"round\" />\n            {/* Bottom cap */}\n            <line x1={cx - cap} y1={yBot} x2={cx + cap} y2={yBot}\n                  stroke={t.ink} strokeWidth={3} strokeOpacity={0.7} strokeLinecap=\"round\" />\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;\n  const H = window.ANYPLOT_SIZE.height;\n\n  const title = \"Seedling Growth Under Stress · errorbar-basic · javascript · muix · anyplot.ai\";\n  const titleSize = title.length > 67 ? Math.round(22 * 67 / title.length) : 22;\n\n  return (\n    <ChartContainer\n      width={W}\n      height={H}\n      series={[{\n        type: \"bar\",\n        data: MEANS,\n        id: \"growth\",\n        label: \"Mean Stem Elongation (cm/week)\",\n        xAxisId: \"x\",\n        yAxisId: \"y\",\n      }]}\n      xAxis={[{\n        id: \"x\",\n        scaleType: \"band\",\n        data: CONDITIONS,\n        colorMap: {\n          type: \"ordinal\",\n          values: CONDITIONS,\n          colors: BAR_COLORS,\n        },\n      }]}\n      yAxis={[{\n        id: \"y\",\n        min: 0,\n        max: 6,\n      }]}\n      margin={{ top: 72, bottom: 92, left: 100, right: 100 }}\n    >\n      <ChartsGrid horizontal />\n      <BarPlot skipAnimation borderRadius={4} />\n      <ErrorBars />\n      <ChartsReferenceLine\n        y={MEANS[0]}\n        axisId=\"y\"\n        label=\"Control baseline\"\n        labelAlign=\"end\"\n        lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"6 4\", strokeWidth: 1.5 }}\n        labelStyle={{ fontSize: 13, fill: t.inkSoft, fontStyle: \"italic\" }}\n      />\n      <ChartsXAxis\n        axisId=\"x\"\n        label=\"Growth Condition\"\n        labelStyle={{ fontSize: 16 }}\n        tickLabelStyle={{ fontSize: 14 }}\n      />\n      <ChartsYAxis\n        axisId=\"y\"\n        label=\"Mean Stem Elongation (cm / week)\"\n        labelStyle={{ fontSize: 16 }}\n        tickLabelStyle={{ fontSize: 14 }}\n      />\n      <text\n        x={W / 2}\n        y={36}\n        textAnchor=\"middle\"\n        dominantBaseline=\"middle\"\n        fontSize={titleSize}\n        fontWeight={600}\n        fill={t.ink}\n        fontFamily=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n      >\n        {title}\n      </text>\n    </ChartContainer>\n  );\n}\n"}