import { XYCustomChart } from "semiotic/xy" import { diagnoseTokenEncoding, generateTokens, suggestTokenEncoding, tokenLayer, } from "semiotic/recipes" // 1 · Say what a repeated mark MEANS before anything is drawn. const encoding = { tokenType: "glyph", icon: "bus", // the built-in ISOTYPE bus sign tokenSemantics: "possible-outcome", countStrategy: "quantile", // Kay/Hullman: equally likely arrivals tokenCount: 50, layout: "dotplot", // Wilkinson-stacked quantile dotplot } // 2 · The records carry the ledger and a live design critique. const tokenSet = generateTokens(arrivalSamples, encoding) tokenSet.diagnostics // e.g. TOO_MANY_VISIBLE_TOKENS if you ask for 800 // 3 · Any custom layout stamps them as real scene nodes — canvas + SVG, // hover, keyboard nav, transitions, accessible rows, for free. function busDotplotLayout(ctx) { const { height } = ctx.dimensions.plot const layer = tokenLayer({ input: tokenSet, options: { tokenSize: 17, cellHeight: -19, // negative step: stack up from the axis y: height - 32, valueToX: (arrival) => ctx.scales.x(arrival), color: (t) => (t.sample <= threshold ? "#236d99" : "#c93d3d"), datum: (t) => ({ arrival: t.sample, quantile: t.quantile }), pointId: (t) => `outcome-${t.index}`, }, }) return { nodes: layer.nodes, overlays: <ThresholdLine /> } } <XYCustomChart data={arrivalData} layout={busDotplotLayout} xExtent={[0, 22]} /> // 4 · Or ask for the encoding first — task in, semantics out. suggestTokenEncoding({ taskIntent: "estimate probability", dataType: "distribution" }) // → { recommendedEncoding: "quantile-dotplot", tokenEncoding, rationale, … }