Theming Override tokens
Override tokens
Override individual --pretable-* tokens with plain CSS cascade — no preprocessor required.
The override story is plain CSS cascade. Pick a theme, redefine any of its 50 tokens in your own stylesheet, and your values win because they load after the theme.
Two buttons redefine --pretable-accent and --pretable-radius on a wrapper div at runtime, the same cascade a :root override in your own stylesheet produces after the theme import.
Toggle either button above and watch the grid change with no re-render logic of its own — the surface never re-mounts, because nothing about its React tree changed. Only the CSS custom properties it reads changed, and the grid was already reading them live.
Token overrides are the simplest path, but you can also override any rendered style with plain CSS — the grid's defaults are zero-specificity and layered, so your selectors win without
!important. See Cascade & overrides.
The basic pattern
@import "@pretable/ui/themes/pretable.css";
@import "@pretable/ui/grid.css";
:root {
--pretable-accent: #ff5722;
--pretable-rule: #cccccc;
}Both your :root block and the theme's :root block declare CSS variables at the same specificity. Source order wins: your stylesheet imports after the theme's, so your values override. The same holds for any of the three themes — this page uses pretable.css, the default, in its examples. The demo above overrides via an inline style on a wrapper div instead — a stronger override than a stylesheet rule (inline style beats any selector, tie or not), used there only because it's the easiest way to flip a token from a button click. Your own app can do the same with a scoped selector, as shown below, or with inline style wherever the value is computed at render time rather than fixed in a stylesheet.
Worked examples
Tweak the accent color
Most apps want the grid's accent to match their brand. Override one token:
@import "@pretable/ui/themes/pretable.css";
@import "@pretable/ui/grid.css";
:root {
--pretable-accent: var(--brand-primary);
}The accent marks interactive state: an active filter funnel, the filter menu's Clear button, the date picker's navigation on hover. How far one override reaches depends on the theme. Excel and Material write their control tokens as var(--pretable-accent), so recoloring the accent also recolors the checked checkbox, the resize handle on hover, the column drop indicator, and the range-selection tint. Only the hover state of the handle moves: --pretable-resize-handle, the idle one, is transparent in every theme and has no color to keep in step. The pretable theme writes those as literals instead, so that its dark block can move an affordance independently — override the grid-control tokens alongside the accent if you want the same reach there.
Swap the entire color palette
Pretable ships three concrete themes, but the token contract works for any palette. Once you're overriding the surface/text/line/state/accent groups together rather than one or two tokens, you're effectively building your own theme on top of a shipped one — at that point, write it as a real theme file instead of a growing :root block. Custom themes has the cleaner pattern, and includes a live, complete brand.css — every token, a dark block, and density tiers — that you can copy wholesale rather than reassembling from a partial snippet.
One consequence worth knowing when the base theme ships a dark block, as
pretableand Material do.:rootand[data-theme="dark"]carry the same specificity — a pseudo-class and an attribute selector weigh the same — so your later-loading:rootbeats the theme's dark block too. A palette written at:roottherefore applies in both modes, and for the tokens you overrode the theme's dark values stop having any effect. That is usually what you want for a single brand accent. If you want different values per mode, write your dark ones in your own[data-theme="dark"]block, after the theme's import.
Change the corner radius
The pretable theme ships --pretable-radius: 10px; Excel ships 0 for sharp spreadsheet corners. To move either without writing a new theme:
@import "@pretable/ui/themes/pretable.css";
@import "@pretable/ui/grid.css";
:root {
--pretable-radius: 4px;
}The grid container's outer border radius now reflects your value. Cells stay square — the radius applies only to the outermost wrapper. Small affordances (menu items, the funnel and ⋮ buttons, the chip remove target) take --pretable-radius-control instead, because the container radius applied to a 14–18px control rounds it into a circle.
Change density values
Density tokens follow the same rule. Override them at :root to tweak the dimensions a theme ships:
@import "@pretable/ui/themes/pretable.css";
@import "@pretable/ui/grid.css";
:root {
/* The default theme's standard density is a 48px row; tighten to 36px globally */
--pretable-row-height: 36px;
--pretable-header-height: 40px;
--pretable-cell-padding-x: 12px;
--pretable-cell-padding-y: 6px;
}The engine reads --pretable-row-height, --pretable-header-height, and --pretable-group-panel-height directly from CSS, so the virtualizer respects your values without you passing props. One constraint: it parses only <number>px, so a height written as 2rem or a calc() falls back to the built-in default rather than the value you meant.
Token groups
The 50 tokens group by purpose. When overriding, think in groups:
- Surfaces drive cell, pinned-cell, group-row, header, toolbar, and popover backgrounds.
- Text drives readable content color.
- Lines and radii drive gridlines, container borders, and corner rounding. The horizontal and vertical rules are separate tokens, so a theme can drop the column cage without losing row separation.
- State drives hover, selection, and focus interaction.
- Editing skins the inline cell editor and its invalid-input state.
- Accent is the interactive hue.
- Semantic ramp is the four state colors — positive, negative, warning, info — that the delta, status, and badge cell presentations read.
- Elevation drives popover shadows, the container's card shadow, and the frozen-column seam.
- Density drives row heights, padding, font sizes, and the per-level indent of a grouped row.
- Icons is the single draw size shared by every built-in glyph.
- Typography drives font family stacks (sans for chrome, mono for numeric cells).
- Grid controls drive the checkbox, the range-selection overlay, the resize handle, and the column-reorder indicators.
See Token reference for the full list with descriptions, types, and each theme's values.
Specificity tips
- Override at
:root— matches the theme's specificity, source order decides. - Don't use
!importantunless something else is fighting you. Cascade order should win cleanly. - Scope overrides if needed — to override per-section of your app, scope to a class or attribute:
.dashboard { --pretable-accent: red; } .reports { --pretable-accent: blue; }. The grid inside each scope reads the locally scoped value.
Where to go next
- Token reference — the canonical 50-token table.
- Light / dark switching — runtime variant toggle.
- Density switching — runtime density toggle.
- Custom themes — when overrides grow into a full theme, switch to authoring one.