matrix-grid
Two ordered axes as an N×M chart-family grid — each cell marks a position (filled / reachable / not applicable), colored by its row's category from the theme's chart palette.
Use for a rubric where BOTH axes are ordered categories (a depth ladder × a reach ladder, a maturity level × a scope) and a reader needs to see one position at a glance — not a status report. A chart-family member: renders inside the shared chart-frame skeleton and colors rows from the theme's chart categorical palette (--chart-cat1..8), never a hardcoded palette of its own. Cells carry a positional grammar ([x] this row's position, [-] reachable from here, [ ] not applicable). For regulation × obligation status tracking, use obligation-matrix; for phases × workstreams delivery status, use roadmap; for two free axes and four cells, use matrix-2x2.
When to use
- Both axes are ordered categories. A depth ladder (skill, seniority, maturity) crossed with a reach or scope ladder (self, team, org, field). If either axis is a free, unordered label, reach for
matrix-2x2(two axes, four cells) instead. - One position, not a status report. The grid exists to show where a single subject sits — a role, a maturity level, a capability — not to track many items' pass/fail state. For that,
obligation-matrix(regulation × obligation) orroadmap(phase × workstream) fit better. - The key's words are a DEFAULT, not a fixed vocabulary. 'reachable' and 'not applicable' suit a capability rubric; a coverage or eligibility grid wants other words. Write a label set —
[{[-], within reach}, {[ ], out of band}]— and those shapes are renamed. Only[-]and[ ]are keyable: a filled cell's own trailing text is its label, so[x]has no general name to give it. - Row category carries the color. Each row is colored by its own hue from the chart family's categorical palette, not a status palette — there's no universal 'good' or 'bad' cell here, only which row and how far it reaches.
When not to use
- Pass/fail or delivery status. If cells mean shipped/at-risk/blocked, use
obligation-matrixorroadmap— their semantic state palette (pass/warn/fail) is built for exactly that read, and matrix-grid's categorical row colors would mislead. - More than one filled cell per row. Each row names one position — one
[x]. Multiple filled cells in a row breaks the "this is where you are" read; use[-]for the cells the row can still reach. - Unordered axes. The grid earns its shape when both axes have a real order (shallow to deep, narrow to wide). Two free categorical labels belong in
matrix-2x2.
Common mistakes
- Authoring
[x]with no trailing label, e.g.| [x] |alone. A filled cell's text IS the row's title at that reach —[x] Senior, not a bare marker. An unlabeled filled cell renders as an empty colored box. - Keying
[x]in a label set.[x]is deliberately not keyable: a filled cell's own trailing text IS its label ([x] Senior), so the shape has no general name and a key row reading 'filled' would repeat on every slide what the cell already says better. Key[-]and[ ], the two shapes a reader genuinely cannot infer.lint:decksays this back to you, quoting the manifest's own reason. - Writing the label set ABOVE the table, where the axis lives. The axis and the key are the SAME shape — a bracketed list — so position is the only thing that tells them apart. A list ABOVE the table names the axes; a list BELOW it renames the key. Put it above and your key becomes an axis label reading 'within reach ▶'.
Authoring
<!-- _class: matrix-grid -->
## Where each level sits on two axes.
Your position is the diagonal — depth and reach meet at one cell.
`[Wider reach, Deeper cognition]`
| Depth | Self | Team | Org |
| ---------- | :--: | :--: | :-: |
| Advanced | [ ] | [-] | [x] Lead |
| Proficient | [-] | [x] Senior | [-] |
| Beginner | [x] Junior | [-] | [ ] |Slots
| Slot | Selector | Required | Description |
|---|---|---|---|
heading | h2 | yes | Slide heading naming the rubric. |
eyebrow | p > code | no | OPTIONAL axis labels: ONE bracketed list in its own paragraph ABOVE the table — ` [Wider reach, Deeper cognition] . The first member names the column (reach) axis and renders centered above the grid; the second names the row (depth) axis and renders rotated along its left edge. Double quotes are optional and protect a comma inside a name — ["Reach, net", Depth] is two axes, and a stray ] right after a quoted name closes the list early (lint:deck warns, bracket-list-closed-early`). Direction arrows are GENERATED — write only the names. Omit the paragraph entirely and the grid renders with no axis labels. A paragraph that is not a bracketed list is an ordinary eyebrow/subtitle and is left alone. |
subtitle | h2 + p | no | One supporting sentence under the heading, framing how to read the grid. |
matrix | table | yes | Markdown table — the header row is the reach/scope axis, the first column of each body row is the category axis. Cells use the positional grammar ([x] / [-] / [ ]); a filled cell's trailing text is its label. |
key | p > code:only-child | no | OPTIONAL label set renaming the cell key: [{[-], within reach}, {[ ], out of band}], one bracketed list in its own paragraph BELOW the table. POSITION is what distinguishes it from the axis — the two are the same shape, so a list above the table names the axes and a list below it renames the key. TWO shapes are keyable — [-] and [ ]. [x] is deliberately NOT: a filled cell's own trailing text IS its label ([x] Senior), so the shape has no general name and a row reading 'filled' would repeat on every slide what the cell already says better. Naming a subset is the normal case; the rest keep the defaults declared in this manifest's labelSet. |
legend | p:last-of-type | no | Optional single trailing paragraph, doubling as the chart caption. It no longer has to say what the cell shapes mean — the key under the grid names them — so use it for the caveat the key cannot carry (how the placements were derived, what they are illustrative of). A leading **bold** run still renders as a filled swatch + label and a leading *italic* run as an outlined swatch + label, for a caption that wants to point at a specific cell; keep both in this ONE paragraph (a second trailing paragraph is not lifted into the caption). |
Data shape
- The header row's first cell is conventionally blank or names the category axis; the remaining header cells are the reach/scope axis labels in ascending order.
- Body rows go deepest/highest category first — the row order IS the depth axis, so declare rows in the same descending order you'd want read top-to-bottom.
- Up to eight rows are colored from the chart family's categorical palette before hues repeat; past eight, split into two grids.
- On a wide deck every column is the same width, so a filled cell's label has to fit that share rather than widening its own column. Keep labels to a word or two —
Senior,Principal,VP.Distinguishedat five columns is the longest the shipped gallery carries and it clears its cell by 75.9px; a much longer one does not get cut, it paints straight through the pill's border, so treat the pill as the budget.
Anatomy
┌─────────────────────────────────────────┐
│ header │
│ Verb × reach heading. │
│ │
│ ┌───────────┬───────────┬───────────┐ │
│ │ │ Self │ Team │ │
│ ├───────────┼───────────┼───────────┤ │
│ │ Create │ · │ ◇ │ │
│ │ Apply │ ◇ │ ■ │ │
│ │ Remember │ ■ │ ◇ │ │
│ └───────────┴───────────┴───────────┘ │
│ footer 1/19 │
└─────────────────────────────────────────┘Guides
- Marks in layoutswhy
[x][-][ ]mean a POSITION here, not an answer
Related
- obligation-matrixrows × columns of pass/partial/exempt status, not a single position
- roadmapphases × workstreams delivery status
- matrix-2x2two free axes, four cells, qualitative placement
- verdict-gridoptions scored against shared criteria, one card per option