quadrant — Lattice component

quadrant

EvidenceScatterSeries

Native 2×2 scatter chart — items plotted on two continuous axes.

Open in Playground
Variant

Use to position items by two numeric attributes (cost × value, effort × impact). Data-driven; for static categorical 2×2 grids, use matrix-2x2.

two-by-twopositioningprioritizerisk

When to use

  • Two numeric axes carry the analysis. Effort × impact, cost × value, probability × severity, reach × confidence. Both axes are continuous and the position on each genuinely matters — that's the argument quadrant is built to make.
  • Categorical grouping clusters the dots. Items grouped under list headings (Strategic Bets, Quick Wins, Defer, Time Sinks) share a color, so the eye can read the cluster before the individual point. The grouping is editorial, not derived from coordinates.
  • Six to twelve items. Below six the chart wastes the canvas — write it as prose. Past twelve the labels overlap and the quadrant becomes a constellation. Trim the long tail or break it across two slides.

When not to use

  • Static categorical 2×2. If the quadrants are fixed labels (Important × Urgent, Build × Buy × Partner × Defer) and items are placed by category not coordinate, use matrix-2x2. quadrant is data-driven; matrix-2x2 is conceptual.
  • Single axis matters. If one axis is decorative and only the other carries meaning, you have a ranking, not a scatter. Use progress for percent-complete or kpi for ranked metrics with status.
  • Coordinates without an audience-shared scale. If {8, 80} requires a footnote to interpret, the slide doesn't pay off. Either give each axis its domain in the axis list — the [{Effort, 0..10}, {Reach, 0..100}] line above every slide here — or normalize to a familiar scale before authoring.

Common mistakes

  • Under magic, expecting the group heading text to move an item into that quadrant. Placement is driven entirely by the item's {x, y} point — the group heading is an editorial label only; an item whose coordinates don't fall in the region a heading like 'Leaders' implies still renders wherever its numbers place it.
  • Reading a name as belonging to the dot nearest it. Follow the hairline where there is one. A crowded corner pushes names one or two rings out from their own dot, and a leader is drawn for exactly that case — a name with no line is sitting against the dot it names.

Authoring

<!-- _class: quadrant -->

`[{Effort, 0..10}, {Reach, 0..100}]`

## Where to put the next dollar, having spent the last one on a workshop.

Effort estimated in story-points; reach as percent of addressable teams.

- Strategic Bets
  - Scoring model v2 `{3, 70}`
  - Per-team calibration `{5, 85}`
- Quick Wins
  - Weekly signal brief `{8, 80}`
  - Snapshot exports `{9, 55}`
- Defer
  - Vendor scoping `{2, 30}`
  - Manual recalibration `{1, 22}`
- Time Sinks
  - Custom audit log UI `{7, 18}`
  - Bespoke board export `{9, 28}`

Slots

SlotSelectorRequiredDescription
titleh2yesSlide heading framing the analysis.
axesp > codenoOptional axes, as ONE bracketed list in its own paragraph ABOVE the chart list — x first, then y: [{Effort, 0..10}, {Reach, 0..100}]. Each member is {name, min..max, threshold}; the domain and threshold are optional and derive from the data when absent. The paragraph is consumed and painted on the axes, so it never prints twice. Double quotes are optional and protect a comma inside a name; a stray ] right after a quoted name closes the list early, and lint:deck warns (bracket-list-closed-early). A paragraph that is not a bracketed list is the ordinary chart eyebrow and is left alone. Same idiom as scatter and matrix-grid.
itemsli > ul > liyesOne li per item, nested under the group it belongs to (- Quick Wins / - Weekly digest {2, 82}`): its label, then one point record, {x, y} or {x, y, size=n}. The group is a top-level li that holds items and draws no mark of its own, so a > under it describes nothing (lint chart-row-quote-unread); a >` under an item is that point's description.
detailli > ul > li > ulnoOptional 3rd-level nested sublist under an item (the point is an inline record, so this level is free). Drives two surfaces from one source (shared with pie/funnel/map via the chart-family mark-detail substrate): (1) Present/Practice — the kernel tags the item's <circle>/bubble with data-mark (a stable global index across all variants) and emits the sublist as an inert <template class="chart-detail"> the reveal layer reads; (2) the static PDF — the same detail is folded into the slide's speaker note (Label: item · item) as a Marp-faithful comment that notes-core lifts into the per-slide note channel. The note rides the existing channel, so the chart pixels stay byte-identical. A quadrant with no sublists emits no note and is unchanged.

Data shape

  • An item is ONE inline-code point — Label — {x, y} as ` {3, 70} , or {3, 70, size=2.4} under bubble — EXCEPT trail, which needs TWO points ( {5, 60} {3, 78} , from-position then to-position); splitting a non-trail` item's coordinates into two chips silently zeroes the second axis instead of erroring.
  • The axis list is not just a label — a member's domain SETS the scale ({Effort, 0..10} fixes it instead of deriving it from the data), and its optional third part is that axis's threshold, which threshold draws as a cutoff line ([{Effort, 0..10, 5}, {Reach, 0..100, 50}]); omit either and the chart falls back to a data-derived scale / a midpoint threshold. The retired arrow eyebrow (Effort 0–10 → Reach 0–100) now renders as a plain eyebrow — lint:deck flags it and rewrites it.

Anatomy

┌─────────────────────────────────────────┐
│  header                                 │
│         Quadrant chart heading          │
│                                         │
│    high ▲    ◆       ◆                  │
│         │ ◆    ●                        │
│         │       ●  ◆                    │
│         │  ●         ●                  │
│     low └──────────────►                │
│           low        high               │
│  footer                           1/19  │
└─────────────────────────────────────────┘

Variant decision rule

  • default (no modifier) — Each item is a single, current position on the two axes — the plain scatter.
  • bubble — A third numeric dimension (size, cost, headcount) should scale each point's radius, not just its x/y position.
  • trail — Items have moved — the story is the delta from a prior position to now, shown as a dashed connector line between a faded before-dot and a solid after-dot.
  • cohort — The categorical grouping itself, not the axes, is what the audience should color-scan first.
  • threshold — Specific numeric cutoffs on each axis are the point — draws the actual threshold lines instead of leaving the quadrant split purely visual.
  • magic — The four quadrants have established, named archetypes (Leaders/Challengers/Visionaries/Niche Players) worth labeling explicitly, Gartner-style.
  • minimal — The quadrant tint fields, bubble fills, and cohort hull shading would distract — strips them to outlined points, while axis labels and threshold lines stay visible.

Variants

bubble — bubble

A third value sizes each point.

<!-- _class: quadrant bubble -->

`[{Effort, 0..10}, {Reach, 0..100}]`

## bubble sizes each point by a third value.

- Strategic Bets
  - Scoring model v2 `{3, 70, size=2.4}`
  - Per-team calibration `{5, 85, size=4.1}`
- Quick Wins
  - Weekly signal brief `{8, 80, size=0.9}`
  - Snapshot exports `{9, 55, size=0.6}`
- Defer
  - Vendor scoping `{2, 30, size=0.4}`
- Time Sinks
  - Custom audit log UI `{7, 18, size=1.3}`

trail — trail

Arrows show where points moved from.

<!-- _class: quadrant trail -->

`[{Effort, 0..10}, {Reach, 0..100}]`

## trail shows where each point moved from.

- Strategic Bets
  - Scoring model v2 `{5, 60}` `{3, 78}`
  - Per-team calibration `{7, 70}` `{5, 88}`
- Quick Wins
  - Snapshot exports `{9, 45}` `{8, 62}`
- Time Sinks
  - Custom audit log UI `{6, 25}` `{7, 16}`

cohort — cohort

Points color by group.

<!-- _class: quadrant cohort -->

`[{Effort, 0..10}, {Reach, 0..100}]`

## cohort colors the points by group.

- Strategic Bets
  - Scoring model v2 `{3, 70}`
  - Per-team calibration `{5, 85}`
- Quick Wins
  - Weekly signal brief `{8, 80}`
  - Snapshot exports `{9, 55}`
- Defer
  - Vendor scoping `{2, 30}`
  - Manual recalibration `{1, 22}`
- Time Sinks
  - Custom audit log UI `{7, 18}`
  - Bespoke board export `{9, 28}`

threshold — threshold

The lines that matter, drawn.

<!-- _class: quadrant threshold -->

`[{Effort, 0..10, 5}, {Reach, 0..100, 50}]`

## threshold draws the lines that matter.

- Strategic Bets
  - Scoring model v2 `{3, 70}`
  - Per-team calibration `{5, 85}`
- Quick Wins
  - Weekly signal brief `{8, 80}`
- Defer
  - Vendor scoping `{2, 30}`
- Time Sinks
  - Custom audit log UI `{7, 18}`

magic — magic

All four quadrants named.

<!-- _class: quadrant magic -->

`[{Completeness of vision, 0..100}, {Ability to execute, 0..100}]`

## magic names all four quadrants.

- Challengers
  - Productboard `{30, 82}`
- Leaders
  - Sprig + Log `{85, 88}`
  - Chorus `{72, 76}`
- Niche Players
  - Notion build-out `{25, 28}`
- Visionaries
  - Spreadsheet `{82, 34}`

minimal — minimal

Just the points.

<!-- _class: quadrant minimal -->

`[{Effort, 0..10}, {Reach, 0..100}]`

## minimal strips the chart to its points.

- Strategic Bets
  - Scoring model v2 `{3, 70}`
  - Per-team calibration `{5, 85}`
- Quick Wins
  - Weekly signal brief `{8, 80}`
  - Snapshot exports `{9, 55}`
- Defer
  - Vendor scoping `{2, 30}`
- Time Sinks
  - Custom audit log UI `{7, 18}`

Related

  • matrix-2x2the 2×2 is categorical, not coordinate-based
  • radaritems rated across more than two criteria
  • progresspercent-complete on a single axis
  • piechartpart-to-whole, not bivariate position
  • verdict-gridcomparing options against shared categorical criteria