{"spec_id":"bar-horizontal","library":"muix","language":"javascript","code":"// anyplot.ai\n// bar-horizontal: Horizontal Bar Chart\n// Library: muix 7.29.1 | JavaScript 22.23.1\n// Quality: 93/100 | Created: 2026-08-05\nimport { BarChart } from \"@mui/x-charts/BarChart\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// \"muted\" semantic anchor (other / rest) — not in ANYPLOT_TOKENS, so it's\n// derived the same way the style guide defines it: theme-adaptive gray.\nconst MUTED = t.theme === \"light\" ? \"#6B6A63\" : \"#A8A79F\";\n\n// Fixed (theme-independent) label colors — the bar fills below don't flip\n// with theme, so label contrast is chosen per fill, not via t.ink/t.inkSoft.\nconst LABEL_ON_BRAND = \"#1A1A17\"; // dark ink — reads on the brand-green bar\nconst LABEL_ON_MUTED = t.pageBg; // page background — reads on the muted-gray bars (adapts per theme)\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Product roadmap survey: feature requests ranked by customer votes, most\n// requested first. Long descriptive labels are exactly why this ranking is\n// horizontal rather than vertical — they'd collide or need rotation otherwise.\nconst FEATURES = [\n  \"Dark mode support\",\n  \"Offline data sync\",\n  \"Advanced search filters\",\n  \"Bulk CSV export\",\n  \"Customizable dashboards\",\n  \"Real-time collaboration\",\n  \"Mobile app redesign\",\n  \"API rate limit increase\",\n];\nconst VOTES = [842, 715, 693, 588, 511, 467, 398, 312];\n\n// Chart renders category index 0 at the top of the y-axis, so the array\n// above (already sorted highest → lowest) reads as a top-to-bottom ranking.\n// Only the top request is highlighted brand green; the rest use the \"muted\"\n// semantic anchor (other / rest) so the eye lands on the leading request.\nconst BAR_COLORS = FEATURES.map((_, i) => (i === 0 ? t.palette[0] : MUTED));\nconst LABEL_COLORS = FEATURES.map((_, i) => (i === 0 ? LABEL_ON_BRAND : LABEL_ON_MUTED));\n\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width; // 1600 CSS px (landscape mount)\n  const H = window.ANYPLOT_SIZE.height; // 900 CSS px\n  const CHART_TOP = 84;\n\n  const title = \"Feature Requests by Customer Votes · bar-horizontal · javascript · muix · anyplot.ai\";\n  const titleSize = title.length > 67 ? Math.round(22 * 67 / title.length) : 22;\n\n  return (\n    <Box sx={{ position: \"relative\", width: W, height: H, bgcolor: t.pageBg }}>\n      {/* Title + subtitle */}\n      <Box sx={{ position: \"absolute\", top: 24, left: 56, right: 56 }}>\n        <Typography sx={{ color: t.ink, fontSize: titleSize, fontWeight: 500 }}>{title}</Typography>\n        <Typography sx={{ color: t.inkSoft, fontSize: 14, mt: 0.5 }}>\n          Dark mode leads a 2026 product roadmap survey of 1,842 respondents\n        </Typography>\n      </Box>\n\n      {/* Bar chart */}\n      <Box sx={{ position: \"absolute\", top: CHART_TOP, left: 0, right: 0, bottom: 0 }}>\n        <BarChart\n          width={W}\n          height={H - CHART_TOP}\n          layout=\"horizontal\"\n          skipAnimation\n          borderRadius={4}\n          xAxis={[\n            {\n              label: \"Customer Votes\",\n              labelStyle: { fontSize: 15, fill: t.ink },\n              tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n              disableTicks: true,\n              max: 950,\n            },\n          ]}\n          yAxis={[\n            {\n              scaleType: \"band\",\n              data: FEATURES,\n              colorMap: { type: \"ordinal\", values: FEATURES, colors: BAR_COLORS },\n              tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n              disableTicks: true,\n              categoryGapRatio: 0.35,\n            },\n          ]}\n          series={[\n            {\n              id: \"votes\",\n              label: \"Votes\",\n              data: VOTES,\n              valueFormatter: (v) => `${v} votes`,\n            },\n          ]}\n          barLabel=\"value\"\n          slotProps={{\n            barLabel: (ownerState) => ({\n              style: {\n                fontSize: 13,\n                fontWeight: 600,\n                fill: LABEL_COLORS[ownerState.dataIndex],\n              },\n            }),\n            legend: { hidden: true },\n          }}\n          margin={{ top: 14, right: 60, bottom: 60, left: 230 }}\n          sx={{\n            \"& .MuiChartsAxis-line\": { stroke: t.inkSoft },\n            \"& .MuiChartsGrid-line\": { stroke: t.grid },\n          }}\n        />\n      </Box>\n    </Box>\n  );\n}\n"}