{"spec_id":"lollipop-basic","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// lollipop-basic: Basic Lollipop Chart\n// Library: chartjs 4.4.7 | JavaScript 22.23.0\n// Quality: 89/100 | Created: 2026-07-01\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (website traffic by marketing channel, sorted descending) --------\nconst channels = [\n  \"Paid Search\", \"Organic\", \"Social Media\", \"Blog\",\n  \"Direct\", \"Email\", \"Influencer\", \"Referral\",\n  \"Video Ads\", \"Podcast\"\n];\nconst visitors = [312, 285, 198, 176, 165, 142, 118, 89, 67, 43];\n\n// Emphasize top performer with a larger dot\nconst dotRadii = visitors.map((_, i) => i === 0 ? 20 : 14);\n\n// --- Mount -----------------------------------------------------------------\nconst canvas = document.createElement(\"canvas\");\ndocument.getElementById(\"container\").appendChild(canvas);\n\n// --- Inline plugin: value label above the top performer -------------------\nconst topLabelPlugin = {\n  id: \"topLabel\",\n  afterDraw(chart) {\n    const ctx = chart.ctx;\n    const meta = chart.getDatasetMeta(1); // line dataset (dots)\n    const topPoint = meta.data[0];\n    ctx.save();\n    ctx.font = \"bold 15px sans-serif\";\n    ctx.fillStyle = t.ink;\n    ctx.textAlign = \"center\";\n    ctx.textBaseline = \"bottom\";\n    ctx.fillText(\"312K\", topPoint.x, topPoint.y - dotRadii[0] - 6);\n    ctx.restore();\n  },\n};\n\n// --- Chart (lollipop: thin bars as stems + line points as dots) -----------\nnew Chart(canvas, {\n  type: \"bar\",\n  data: {\n    labels: channels,\n    datasets: [\n      {\n        // Stems: very thin bars from baseline to value\n        type: \"bar\",\n        label: \"Visitors (K)\",\n        data: visitors,\n        backgroundColor: t.palette[0],\n        barThickness: 3,\n        order: 1,\n      },\n      {\n        // Dots: large circular points at each value; top performer is larger\n        type: \"line\",\n        label: \"Visitors (K)\",\n        data: visitors,\n        backgroundColor: t.palette[0],\n        borderColor: t.pageBg,\n        borderWidth: 2,\n        pointRadius: dotRadii,\n        pointHoverRadius: dotRadii.map(r => r + 2),\n        showLine: false,\n        order: 2,\n      },\n    ],\n  },\n  options: {\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    plugins: {\n      title: {\n        display: true,\n        text: \"lollipop-basic · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 22, weight: \"bold\" },\n        padding: { top: 20, bottom: 30 },\n      },\n      legend: {\n        display: false,\n      },\n    },\n    scales: {\n      x: {\n        ticks: {\n          color: t.inkSoft,\n          font: { size: 14 },\n        },\n        grid: { display: false },\n        title: {\n          display: true,\n          text: \"Marketing Channel\",\n          color: t.ink,\n          font: { size: 16 },\n          padding: { top: 12 },\n        },\n      },\n      y: {\n        ticks: {\n          color: t.inkSoft,\n          font: { size: 14 },\n        },\n        grid: { color: t.grid },\n        beginAtZero: true,\n        title: {\n          display: true,\n          text: \"Monthly Visitors (thousands)\",\n          color: t.ink,\n          font: { size: 16 },\n          padding: { bottom: 12 },\n        },\n      },\n    },\n    layout: {\n      padding: { top: 40, bottom: 20, left: 30, right: 30 },\n    },\n  },\n  plugins: [topLabelPlugin],\n});\n"}