{"spec_id":"bar-basic","library":"d3","language":"javascript","code":"// anyplot.ai\n// bar-basic: Basic Bar Chart\n// Library: d3 7.9.0 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-02\n\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\nconst { width, height } = window.ANYPLOT_SIZE;\nconst margin = { top: 90, right: 60, bottom: 100, left: 130 };\nconst iw = width - margin.left - margin.right;\nconst ih = height - margin.top - margin.bottom;\n\n// Data — quarterly revenue (USD millions) for a fictional consumer-products company\nconst data = [\n  { category: \"Beverages\", value: 184.2 },\n  { category: \"Snacks\", value: 152.7 },\n  { category: \"Dairy\", value: 138.4 },\n  { category: \"Bakery\", value: 121.9 },\n  { category: \"Frozen\", value: 97.3 },\n  { category: \"Produce\", value: 86.1 },\n  { category: \"Pantry\", value: 74.5 },\n  { category: \"Household\", value: 58.8 },\n];\n\n// SVG mount\nconst svg = d3\n  .select(\"#container\")\n  .append(\"svg\")\n  .attr(\"width\", width)\n  .attr(\"height\", height);\nconst g = svg\n  .append(\"g\")\n  .attr(\"transform\", `translate(${margin.left},${margin.top})`);\n\n// Scales\nconst x = d3\n  .scaleBand()\n  .domain(data.map((d) => d.category))\n  .range([0, iw])\n  .padding(0.28);\nconst y = d3\n  .scaleLinear()\n  .domain([0, d3.max(data, (d) => d.value) * 1.1])\n  .nice()\n  .range([ih, 0]);\n\n// Y-axis gridlines (drawn behind the bars, no domain line)\ng.append(\"g\")\n  .attr(\"class\", \"y-grid\")\n  .call(d3.axisLeft(y).ticks(6).tickSize(-iw).tickFormat(\"\"))\n  .call((sel) => sel.select(\".domain\").remove())\n  .call((sel) =>\n    sel.selectAll(\"line\").attr(\"stroke\", t.ink).attr(\"stroke-opacity\", 0.15),\n  );\n\n// Bars — Imprint palette position 1 (brand green) for the single series\ng.selectAll(\"rect.bar\")\n  .data(data)\n  .join(\"rect\")\n  .attr(\"class\", \"bar\")\n  .attr(\"x\", (d) => x(d.category))\n  .attr(\"y\", (d) => y(d.value))\n  .attr(\"width\", x.bandwidth())\n  .attr(\"height\", (d) => ih - y(d.value))\n  .attr(\"fill\", t.palette[0]);\n\n// Value labels above each bar\ng.selectAll(\"text.value-label\")\n  .data(data)\n  .join(\"text\")\n  .attr(\"class\", \"value-label\")\n  .attr(\"x\", (d) => x(d.category) + x.bandwidth() / 2)\n  .attr(\"y\", (d) => y(d.value) - 12)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"20px\")\n  .style(\"font-weight\", \"500\")\n  .text((d) => `$${d.value.toFixed(0)}M`);\n\n// X-axis (floating — domain line kept as a subtle baseline)\nconst xAxis = g\n  .append(\"g\")\n  .attr(\"transform\", `translate(0,${ih})`)\n  .call(d3.axisBottom(x).tickSize(0).tickPadding(12));\nxAxis.select(\".domain\").attr(\"stroke\", t.inkSoft);\nxAxis.selectAll(\"text\").attr(\"fill\", t.inkSoft).style(\"font-size\", \"22px\");\n\n// Y-axis (floating — no domain line; values formatted as $N M)\nconst yAxis = g\n  .append(\"g\")\n  .call(\n    d3\n      .axisLeft(y)\n      .ticks(6)\n      .tickSize(0)\n      .tickPadding(14)\n      .tickFormat((d) => `$${d}M`),\n  );\nyAxis.select(\".domain\").remove();\nyAxis.selectAll(\"text\").attr(\"fill\", t.inkSoft).style(\"font-size\", \"20px\");\n\n// Axis labels\nsvg\n  .append(\"text\")\n  .attr(\"x\", margin.left + iw / 2)\n  .attr(\"y\", height - 24)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"24px\")\n  .text(\"Product Category\");\n\nsvg\n  .append(\"text\")\n  .attr(\"transform\", `translate(36, ${margin.top + ih / 2}) rotate(-90)`)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"24px\")\n  .text(\"Quarterly Revenue (USD millions)\");\n\n// Title — descriptive prefix included; ~72 chars at 28px fits comfortably\nsvg\n  .append(\"text\")\n  .attr(\"x\", width / 2)\n  .attr(\"y\", 52)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"28px\")\n  .style(\"font-weight\", \"600\")\n  .text(\"Quarterly Revenue by Category · bar-basic · javascript · d3 · anyplot.ai\");\n"}