{"spec_id":"bar-error","library":"muix","language":"javascript","code":"// anyplot.ai\n// bar-error: Bar Chart with Error Bars\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 90/100 | Created: 2026-09-02\n//# anyplot-orientation: landscape\n// anyplot.ai\n// bar-error: Bar Chart with Error Bars\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-09-02\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 { useXScale, useYScale } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Customer-support survey: mean satisfaction score (0-10) ± 1 SD across ~150\n// respondents per channel. Horizontal layout keeps the longer channel labels\n// (\"Self-Service\", \"Social Media\") on a single, unrotated line.\nconst CHANNELS = [\n  \"Email\",\n  \"Live Chat\",\n  \"Phone\",\n  \"Self-Service\",\n  \"Social Media\",\n];\nconst SCORES = [7.2, 8.4, 7.8, 6.5, 6.9];\nconst ERRORS = [0.9, 0.6, 0.7, 1.1, 0.95];\n\n// ErrorBars draws ±1 SD whiskers from the chart's own scale functions —\n// horizontal layout means the whisker runs along x, its caps run along y.\nfunction ErrorBars() {\n  const xScale = useXScale(\"x\");\n  const yScale = useYScale(\"y\");\n  if (!xScale || !yScale) return null;\n\n  const bw = (yScale as any).bandwidth();\n  const cap = bw * 0.22;\n\n  return (\n    <g>\n      {CHANNELS.map((channel, i) => {\n        const cy = (yScale as any)(channel) + bw / 2;\n        const xLow = (xScale as any)(SCORES[i] - ERRORS[i]);\n        const xHigh = (xScale as any)(SCORES[i] + ERRORS[i]);\n        return (\n          <g key={channel}>\n            <line\n              x1={xLow}\n              y1={cy}\n              x2={xHigh}\n              y2={cy}\n              stroke={t.ink}\n              strokeWidth={3}\n              strokeOpacity={0.75}\n              strokeLinecap=\"round\"\n            />\n            <line\n              x1={xLow}\n              y1={cy - cap / 2}\n              x2={xLow}\n              y2={cy + cap / 2}\n              stroke={t.ink}\n              strokeWidth={3}\n              strokeOpacity={0.75}\n              strokeLinecap=\"round\"\n            />\n            <line\n              x1={xHigh}\n              y1={cy - cap / 2}\n              x2={xHigh}\n              y2={cy + cap / 2}\n              stroke={t.ink}\n              strokeWidth={3}\n              strokeOpacity={0.75}\n              strokeLinecap=\"round\"\n            />\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 =\n    \"Customer Satisfaction by Support Channel · bar-error · javascript · muix · anyplot.ai\";\n  const titleSize =\n    title.length > 67 ? Math.round(22 * (67 / title.length)) : 22;\n  const subtitle = \"Error bars show ±1 SD across ~150 respondents per channel\";\n\n  return (\n    <ChartContainer\n      width={W}\n      height={H}\n      series={[\n        {\n          type: \"bar\",\n          data: SCORES,\n          id: \"satisfaction\",\n          label: \"Mean satisfaction score (0–10)\",\n          layout: \"horizontal\",\n          color: t.palette[0],\n          xAxisId: \"x\",\n          yAxisId: \"y\",\n        },\n      ]}\n      xAxis={[\n        {\n          id: \"x\",\n          scaleType: \"linear\",\n          min: 0,\n          max: 10,\n          label: \"Mean Satisfaction Score (0–10)\",\n          labelStyle: { fontSize: 16, fill: t.inkSoft },\n          tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n        },\n      ]}\n      yAxis={[\n        {\n          id: \"y\",\n          scaleType: \"band\",\n          data: CHANNELS,\n          tickLabelStyle: { fontSize: 15, fill: t.inkSoft },\n        },\n      ]}\n      margin={{ top: 110, bottom: 90, left: 190, right: 90 }}\n    >\n      <ChartsGrid vertical />\n      <BarPlot borderRadius={4} skipAnimation />\n      <ErrorBars />\n      <ChartsXAxis axisId=\"x\" />\n      <ChartsYAxis axisId=\"y\" />\n      <text\n        x={W / 2}\n        y={44}\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      <text\n        x={W / 2}\n        y={78}\n        textAnchor=\"middle\"\n        dominantBaseline=\"middle\"\n        fontSize={16}\n        fontStyle=\"italic\"\n        fill={t.inkSoft}\n        fontFamily=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n      >\n        {subtitle}\n      </text>\n    </ChartContainer>\n  );\n}\n"}