# XWUISpecTable

A reference table of stated facts. The header is quiet and monospaced and paints on
whatever surface the table sits on. Rows are separated by a hairline and carry no fill
of their own: there is no zebra and there is no hover. Typography is chosen per column,
so identifiers read as identifiers and prose reads as prose.

`new XWUISpecTable(container, data, config?)`, positional. Implements `setupDOM()`, and
`destroy()` calls `super.destroy()`.

## Data

| Key | Default | Meaning |
| --- | --- | --- |
| `caption` | `''` | What the table is. Names the table for assistive technology and is not painted. |
| `columns` | `[]` | Column descriptors, in painting order. |
| `rows` | `[]` | Rows keyed by column key. A cell is text or an element. |

## Column descriptor

Every field but `key` is optional and every default is the resting state, so a column
written as `{ key: 'x' }` is a plain secondary-toned data column.

| Key | Default | Meaning |
| --- | --- | --- |
| `key` | required | Key this column reads out of each row. |
| `title` | `''` | Header text. |
| `mono` | `false` | Paint the cells in the monospaced family. |
| `fill` | `false` | This column absorbs the leftover width. |
| `rowHeader` | `false` | Emit the cells as `th scope="row"` rather than `td`. |
| `tone` | `'default'` | Colour for every cell in the column. |
| `toneByValue` | none | Colour by exact cell text. Wins over `tone`. |

Tones are `default`, `strong`, `success`, `warning`, `running` and `error`. `default` is
`--text-secondary` and `strong` is `--text-primary`. There is no third neutral step: on a
true-black ground `--text-tertiary` measures 4.06:1 and AA wants 4.5:1, so the tertiary
step is not offered for text here.

## Config

| Key | Default | Meaning |
| --- | --- | --- |
| `selectedRow` | `-1` | Index of the one row drawn with a lifted background. |
| `className` | none | Extra class on the table element. |

## Semantics

A real `<table>`. Column headers are `th scope="col"`; a column marked `rowHeader` emits
`th scope="row"`, which is how a screen reader names the row it is reading. The `caption`
is a real `<caption>`, taken out of flow with `clip-path: inset(50%)` rather than the
framework's `.sr-only`, so the component does not depend on a global utility sheet.

The table sits inside a wrapper that scrolls sideways. When a caption is given, the
wrapper becomes a `region` labelled by that caption and takes `tabindex="0"`, because a
scrollable box is keyboard reachable by browser rule on Chrome and Firefox and not on
Safari. With no caption there is no name to announce, so there is no region and no tab
stop.

Nothing here is interactive. No row is clickable, no header sorts, and `selectedRow` is
a drawn state the host sets, not a state the table enters on its own.

`toneByValue` never carries meaning alone: the value it colours is the cell's own text,
so removing colour removes nothing.

## Row height

Derived from padding plus the line box, the way the rest of the library derives it, not
declared. `--spacing-md` above and below a `--font-size-xs` line at
`--line-height-normal` plus the hairline. A declared row height would stop a cell
wrapping, and these tables carry sentences, not only short tokens.

## Style dependencies

- Base: `reset.css`, `typography.css`
- Brand: `brand/xwui/brand.css`
- Style: `style/modern/spacing.css`
- Theme: `theme/colors/{selected}.css`, `theme/accents/{selected}.css`,
  `theme/lines/{selected}.css`, `theme/typography/{selected}.css`

`--status-running` is read as `var(--status-running, var(--text-secondary))`: it is
declared for the `noir` colour theme only, and on any other theme the `running` tone
degrades to the neutral colour rather than to `transparent`.
