LyteNyte Grid logo for light mode. Links back to the documentation home page.
Cells

Cell Diff Flashing

Highlight frequent data updates by momentarily flashing modified cells. This visual cue helps users track real-time changes in high-frequency data streams.

Note

Implement cell flashing using a custom renderer that triggers a CSS animation when the cell value updates. This guide covers several approaches for cell flashing. Review the Cell Renderers guide before you start.

Flashing Cells On Change

To flash a cell when its value changes, compare the current and previous values. If the values differ, apply a CSS flash animation. Click Update Data to randomly change cell values.

Flash Updated Cells

Fork code on stack blitzFork code on code sandbox

The cell flashing logic lives in the NumberCell component. NumberCell is a custom cell renderer that the grid columns use. The component tracks the previous value and applies the "flash" animation in an effect whenever the value changes.

export function NumberCell({ api, column, row }: Grid.T.CellRendererParams<GridSpec>) {
const field = api.columnField(column, row) as number;
const prevRef = useRef(field);
const prev = prevRef.current;
const value = typeof field === "number" ? formatter.format(field) : "-";
const diff = field - (prev ?? field);
if (prev !== field) prevRef.current = field;
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!ref.current) return;
ref.current.style.animation = "none";
requestAnimationFrame(() => {
ref.current!.style.animation = "flash 1s ease-out forwards";
});
}, [diff]);
return (
<div ref={ref} className="flex h-full items-center justify-end gap-2 tabular-nums tracking-tighter">
{value}
</div>
);
}

Enhanced Flash

Flashing the cell background indicates a value changed but doesn’t show the change’s direction or magnitude. To provide context, flash the value itself, as shown in the demo below.

Flash Value Changes

Fork code on stack blitzFork code on code sandbox

This demo reuses the change-detection logic from the previous example but alters the rendering. Instead of flashing the background, the cell renderer highlights the value change and then fades out the effect. See the code below.

export function NumberCell({ api, column, row }: Grid.T.CellRendererParams<GridSpec>) {
20 collapsed lines
const field = api.columnField(column, row) as number;
const prevRef = useRef(field);
const prev = prevRef.current;
const value = typeof field === "number" ? formatter.format(field) : "-";
const diff = field - (prev ?? field);
if (prev !== field) prevRef.current = field;
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!ref.current) return;
ref.current.style.animation = "none";
requestAnimationFrame(() => {
ref.current!.style.animation = "fadeOut 3s ease-out forwards";
});
}, [diff]);
return (
<div className="flex h-full items-center justify-end gap-2 tabular-nums tracking-tighter">
{diff !== 0 && (
<div
ref={ref}
className={clsx(
"flex items-center rounded px-1 text-[10px]",
diff < 0 && "bg-red-800/20 text-red-500",
diff > 0 && "bg-green-500/20 text-green-500",
)}
>
{diff < 0 && <ArrowDownIcon width={12} height={12} />}
{diff > 0 && <ArrowUpIcon width={12} height={12} />}
<span>{diff.toFixed(2)}</span>
</div>
)}
{value}
</div>
);
}

Next Steps