Realtime
Cell flashing
Flash a cell green or red when its value moves, show how far it moved, flash cells on demand, and keep a busy board's flashes cheap.
A tick flash tells the eye which values just moved. Set flash: 'auto' on a column and the grid does the rest: it remembers each cell’s last value and flashes green on a rise, red on a fall. There is nothing to keep in app code; write the new value and the cell flashes.
Bid and ask below flash on their own, often in opposite directions in the same row. Status flashes amber whenever it changes. The buttons flash cells whose values did not change, and Motion switches between a fading and a held flash.
Flash modes
const columns: ColumnDef[] = [
{ type: 'price', key: 'bid', header: 'Bid', flash: 'auto' },
{ type: 'text', key: 'status', header: 'Status', flash: 'change', flashMs: 900 },
];
row.bid = next; // the bid cell flashes, in the direction it moved flash | What flashes |
|---|---|
'auto' (alias 'up-down') | Each cell on its own: green when the number rose, red when it fell. For prices and other numbers. |
'change' | Each cell on its own, in a neutral amber, on any change: status, quantity, text. |
true | Legacy row-driven mode: every flash: true column in the row flashes together, following the row’s own flashSeq and flashDir, which you bump yourself. |
The derived modes are per cell: bid can flash green while ask flashes red in the same row on the same frame. Flash state is keyed on the row id and the column, so a cell stays quiet on first paint and when it scrolls back into view; only a real change flashes.
flashMs sets the duration (300 ms by default). Raise it for a slow feed, lower it for a fast one so flashes don’t smear together. A column that colours its own text (price-limit tones, for example) should set flashColor: false, so the flash lights only the background.
Under prefers-reduced-motion: reduce the grid plays no flash at all.
Showing the change
showChange: true shows how far a value moved, not only which way: ▲0.15 beside the price in the up colour (▼ down), held, then faded over a second.
{ type: 'price', key: 'last', header: 'Last', flash: 'auto', showChange: true }
{ type: 'price', key: 'last', header: 'Last', showChange: { format: (d) => (d > 0 ? '+' : '') + d.toFixed(2), ms: 1500 } } - The delta is written in the column’s own format;
format(delta, row)receives the signed change, andmssets how long it shows (1,000 by default). - In a narrow column the delta gives way first, so the value is never cut for it.
- It fades by animating the text colour, so it adds no compositor layers.
Use it on the one or two columns that matter, such as the match price. Each change runs a short animation, so a busy board with it on every column pays real frame time.
Flash on demand
Some events don’t change a value on screen: a block trade, your order filling, an alert level crossed. api.flashCells plays the tick flash on the cells you name, changed or not:
api.flashCells({ rows: [fill.symbol] }); // the whole row, amber
api.flashCells({ rows: ids, columns: ['symbol'], ms: 1200 }); // just the symbol, longer
api.flashCells({ rows: [id], columns: ['last'], dir: 'up' }); // tinted like a rise rowsare row ids (every rendered row when omitted), andcolumnsare column keys (every column when omitted).dir: 'up' | 'down'tints like a rise or a fall;msoverrides each column’sflashMs.- Only rows on screen flash, as with a tick. The call returns how many rows it flashed.
- Value cells flash (numbers and text). Cells that draw their own content (badges, sparklines, components) don’t.
- A tick that lands during the flash takes over with its own direction, and a repeat call replays it.
Busy boards
By default a flash fades out. A CSS fade is restyled and repainted on every frame it runs, and on a busy board most visible cells are always mid-fade, which becomes most of the frame. flashMotion="hold" shows a static tint for the flash window instead: repainted when it starts and when the grid’s clock drops it, while a repeat tick during the hold changes nothing.
<Grid {rows} {columns} flashMotion="hold" onReady={(a) => (api = a)} height={480} /> Measured on the Price board with motion allowed, held flashes cut the main thread’s work per frame from about 30 to about 9.4 ms at 10,000 events/s, and from about 40 to about 12.3 ms at 30,000, with no dropped frames. That is within about 1 ms of no flash at all (BENCHMARKS.md).
For a grid that is sometimes quiet and sometimes busy, flashMotion="auto" decides per flash as it starts. It fades while few cells flash at once and holds once more than about 120 overlap. A taller board reaches that sooner, which is the point: the cost grows with the fading cells on screen. A flash that lights whole rows (flashNewRows, api.flashCells) counts every cell it lights, so a burst of new orders on a blotter holds too.
The trading desk board below flashes prices, changes and volume across 1,000 rows, with sparklines and heat cells:
Reference
flash boolean | 'auto' | 'up-down' | 'change' Default falseFlash the cell when its value changes. - 'auto' (alias 'up-down') — the grid derives it: green on a rise, red on a fall, per cell. Nothing to maintain in app code; just stream new values in. This is what you want for a live price board. - 'change' — a neutral flash on any change, numeric or not (status, qty). - true — legacy row-driven mode: the flash follows the row's own flashSeq/flashDir, so every flash: true column in a row flashes together, in one direction, and you bump the counter yourself. Derived modes never flash on first paint or when a row scrolls into view.
flashMs number Default 300Flash duration in ms — derived modes only ('auto'/'up-down'/ 'change'); has no effect on legacy flash: true, which flashes for the CSS animation's fixed duration regardless. Raise it for a slow feed, lower it for a fast one so flashes don't smear together.
flashColor boolean Default trueTint the text in the tick's direction while flashing. Set false when the column colours its own text — e.g. price-limit tones on a VN board (ceiling / floor / reference) — so the flash only lights the background.
showChange boolean | ShowChangeOptions Default falseShow the size of each change beside the value for a moment — ▲0.15 in the up colour, ▼ down — held, then faded. The delta is the last change, written in the column's own format. Numeric values only; first paint and rows scrolling into view show nothing. { format, ms } sets the text (format(delta, row) gets the signed change) and how long it shows (1000 ms unless set). In a narrow column the delta gives way first: the value itself is never cut for it. Meant for one or two key columns (the match price): each change runs a short animation, so a busy board with it on every column pays real frame time.
Example
{ type: 'price', key: 'last', header: 'Last', flash: 'auto', showChange: { ms: 1500, format: (d) => `${d > 0 ? '+' : ''}${d.toFixed(2)}` } }flashMotion 'fade' | 'hold' | 'auto' Default 'fade'How a flash plays. 'fade': the tint fades out. 'hold': the tint holds for the flash window, then drops — no CSS animation, so a busy board restyles and repaints a flashing cell twice instead of every frame. 'auto': fade while few cells flash at once, hold when many do. A flash that lights whole rows (flashNewRows, api.flashCells) counts each cell it lights.
flashNewRows boolean | number Default falseFlash a row once when it arrives in rows (a new order, a new fill): every cell, in the neutral flash colour, for this many ms (true: 600). A row arrives when its id is new; a copy of a row already there does not flash, nor do the rows an empty grid gets (a load or a reload), nor a wholesale replacement (more than 64 rows, and more than an eighth of them, at once). Rows on screen only, as with every flash.
Example
<Grid {rows} {columns} height={480} flashNewRows={900} />flashCells (opts?: FlashCellsOptions): number Flash cells on demand — a fill, an alert, a row to notice — with the tick animation, whether or not their values changed. Only rows on screen flash. Value cells flash (numbers, text); cells that draw their own content (badges, sparklines, components) do not. Returns how many rows it flashed.
Example
api.flashCells({ rows: [fill.orderId], dir: fill.side === 'buy' ? 'up' : 'down', ms: 800 });