Name the data's job, let it pick the chart type, then choose colors.
From dataviz, references/choosing-a-form.md.
Pick a job; the same data redraws to answer it.
// 1. Is it even a chart?
function pickForm(data, job) {
if (data.values === 1) return "stat tile";
if (data.isRatioToLimit) return "meter";
if (data.classes > 7) return "table + chart";
return FORM_BY_JOB[job]; // 2. The job picks the form
}
// 3. The form's job picks the color, last.
const FORM_BY_JOB = {
magnitude: { form: "bar, sorted", color: "sequential, one hue" },
trend: { form: "line (area if single)", color: "one hue" },
identity: { form: "multi-line / grouped bar", color: "categorical, fixed order" },
emphasis: { form: "one line + gray context", color: "1 hue + gray" },
polarity: { form: "diverging bar", color: "diverging, gray midpoint" },
partToWhole: { form: "stacked bar, horizontal", color: "categorical" },
likert: { form: "diverging stacked bar", color: "diverging" },
beforeAfter: { form: "dumbbell", color: "1 hue, 2 shades" },
};
Drag past $5.0M, or past 100% of quota.
Revenue, Q3
$4.2M
+12% vs Q2
value + delta + sparklineQuota attained, Q3
62%
$3.1M of $5.0M
role="meter"<!-- one value: a stat tile, not a one-bar bar chart -->
<div class="tile">
<p class="label">Revenue, Q3</p>
<p class="value">$4.2M</p>
<p class="delta" data-dir="up"><span aria-hidden="true">▲</span> +12% vs Q2</p>
</div>
<!-- ratio to a limit: a meter, not a 2-slice pie. Track runs past 100%. -->
<div class="meter" role="meter" aria-valuemin="0" aria-valuemax="125" aria-valuenow="62">
<div class="fill"></div> <!-- transform: scaleX(0.496); origin left -->
<div class="limit"></div> <!-- left: 80% (100 of 125) -->
</div>
Slide past 7 categories.
const MAX_COLORED = 7;
function partToWhole(classes) {
if (classes.length <= MAX_COLORED) return { bar: classes, table: null };
const sorted = [...classes].sort((a, b) => b.share - a.share);
const top = sorted.slice(0, MAX_COLORED - 1);
const rest = sorted.slice(top.length);
const other = { name: `Other (${rest.length})`, share: sum(rest), color: "gray" };
return { bar: [...top, other], table: sorted };
}
The question narrows the form to one or two options. Color then serves that form, not a mood.