{"spec_id":"burndown-sprint","library":"muix","language":"javascript","code":"// anyplot.ai\n// burndown-sprint: Agile Sprint Burndown Chart\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 91/100 | Created: 2026-06-14\n\nimport { LineChart } from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts\";\nimport { useXScale, useDrawingArea } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Sprint: start state + 10 working days (2 weeks Mon–Fri)\n// Scope change: +8 story points added by stakeholder on Thu of Week 1 (Day 4)\nconst days = [\n  \"Start\",\n  \"Mon 1\", \"Tue 2\", \"Wed 3\", \"Thu 4\", \"Fri 5\",\n  \"Mon 8\", \"Tue 9\", \"Wed 10\", \"Thu 11\", \"Fri 12\",\n];\n\n// Remaining story points recorded at end of each day.\n// Thu 4: team completed 2 pts but +8 scope added → jump from 32 to 38\nconst actual = [40, 37, 34, 32, 38, 34, 28, 21, 14, 7, 2];\n\n// Ideal burndown: straight line from 40 → 0 across 10 working days (4 pts/day)\nconst ideal = [40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0];\n\nconst TITLE_H = 60;\n\n// SVG overlay: shades the Fri→Mon gap to represent the weekend break\nfunction WeekendBand() {\n  const xScale = useXScale();\n  const { top, height } = useDrawingArea();\n\n  if (typeof xScale.bandwidth !== \"function\") return null;\n\n  const bw = xScale.bandwidth();\n  const x1 = xScale(\"Fri 5\");\n  const x2 = xScale(\"Mon 8\");\n\n  if (x1 == null || x2 == null) return null;\n\n  // Shade from the mid-point of Fri 5 to mid-point of Mon 8 (one bandwidth wide)\n  // — visually straddles the weekend discontinuity between the two adjacent bands\n  const rectX = x1 + bw * 0.5;\n  const rectW = x2 + bw * 0.5 - rectX;\n\n  return (\n    <rect\n      x={rectX}\n      y={top}\n      width={rectW}\n      height={height}\n      fill={t.inkSoft}\n      fillOpacity={0.12}\n    />\n  );\n}\n\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n\n  return (\n    <div\n      style={{\n        width,\n        height,\n        background: t.pageBg,\n        overflow: \"hidden\",\n        boxSizing: \"border-box\",\n        fontFamily: \"'Roboto', 'Helvetica Neue', Arial, sans-serif\",\n      }}\n    >\n      <div\n        style={{\n          height: TITLE_H,\n          display: \"flex\",\n          alignItems: \"center\",\n          paddingLeft: 28,\n          paddingRight: 28,\n        }}\n      >\n        <span\n          style={{\n            color: t.ink,\n            fontSize: 22,\n            fontWeight: 500,\n            letterSpacing: 0.3,\n          }}\n        >\n          burndown-sprint · javascript · muix · anyplot.ai\n        </span>\n      </div>\n\n      <LineChart\n        width={width}\n        height={height - TITLE_H}\n        skipAnimation\n        xAxis={[{\n          scaleType: \"band\",\n          data: days,\n          tickLabelStyle: { fontSize: 13, fill: t.inkSoft },\n        }]}\n        yAxis={[{\n          label: \"Story Points Remaining\",\n          min: 0,\n          max: 48,\n          tickLabelStyle: { fontSize: 13, fill: t.inkSoft },\n          labelStyle: { fontSize: 15, fill: t.ink },\n        }]}\n        series={[\n          {\n            id: \"actual\",\n            data: actual,\n            label: \"Actual Remaining\",\n            curve: \"step\",\n            showMark: true,\n            color: t.palette[0],\n          },\n          {\n            id: \"ideal\",\n            data: ideal,\n            label: \"Ideal Burndown\",\n            curve: \"linear\",\n            showMark: false,\n            color: t.inkSoft,\n            area: true,\n          },\n        ]}\n        sx={{\n          \"& .MuiLineElement-series-ideal\": {\n            strokeDasharray: \"10 6\",\n            strokeOpacity: 0.6,\n          },\n          \"& .MuiAreaElement-series-ideal\": {\n            fill: t.palette[0],\n            fillOpacity: 0.07,\n          },\n          \"& .MuiLineElement-series-actual\": {\n            strokeWidth: 3,\n          },\n          \"& .MuiMarkElement-series-actual\": {\n            strokeWidth: 2,\n          },\n        }}\n        slotProps={{\n          legend: {\n            itemMarkWidth: 20,\n            itemMarkHeight: 3,\n            markGap: 8,\n            itemGap: 24,\n            labelStyle: { fontSize: 14, fill: t.ink },\n          },\n        }}\n      >\n        {/* Weekend shading: straddled rect at Fri→Mon discontinuity */}\n        <WeekendBand />\n\n        <ChartsReferenceLine\n          x=\"Thu 4\"\n          label=\"Scope +8 pts\"\n          labelAlign=\"start\"\n          lineStyle={{\n            stroke: t.palette[3],\n            strokeWidth: 2,\n            strokeDasharray: \"5 4\",\n          }}\n          labelStyle={{\n            fill: t.palette[3],\n            fontSize: 13,\n            fontWeight: 500,\n          }}\n        />\n      </LineChart>\n    </div>\n  );\n}\n"}