# Flashing Cells
URL: https://pro.rv-grid.com/guides/cells/cell-flash/
Source: src/content/docs/guides/cells/cell-flash.mdx
Description: Highlight edited or programmatically updated cells and rows in RevoGrid.
Cell flashing makes recent changes visible in editable grids, live dashboards, and audit workflows. The Pro `CellFlashPlugin` can react to edits from `EventManagerPlugin`, undo/redo changes from `HistoryPlugin`, manual `flashcell` events, or direct plugin method calls.

The demo below updates market-style rows, supports burst/live updates, row flashing, custom duration, manual row flash, and undo/redo.

## Enable Cell Flash

Add `CellFlashPlugin` and mark columns with `flash`. Existing boolean predicates still work, and `EventManagerPlugin` keeps edit events connected to the source update flow.

```ts
import { CellFlashPlugin, EventManagerPlugin } from '@revolist/revogrid-pro';

grid.plugins = [EventManagerPlugin, CellFlashPlugin];
grid.eventManager = { applyEventsToSource: true };
grid.columns = [
  {
    name: 'Price',
    prop: 'price',
    flash: () => true,
  },
];
```

## Context-Aware Flashing

The `flash` callback receives the new value and a context object with the previous value, row model, row index, column, row type, and edit metadata. Return a boolean for simple behavior or a decision object to customize the flash.

```ts
grid.columns = [
  {
    name: 'Price',
    prop: 'price',
    flash: (value, context) => ({
      flash: true,
      rowFlash: Math.abs(Number(value) - Number(context.previousValue)) > 2,
      direction: Number(value) > Number(context.previousValue) ? 'up' : 'down',
      duration: 800,
      rowDuration: 1200,
      className: 'price-flash',
      rowClassName: 'large-move-row',
    }),
	    cellTemplate: cellFlashArrowTemplate({
	      symbols: { up: '+', down: '-', changed: '~' },
	      className: 'price-flash-arrow',
	      arrowClassName: 'price-flash-symbol',
	      directionClassNames: { up: 'positive', down: 'negative', changed: 'neutral' },
	    }),
  },
];
```

## Configure Timing And Queueing

Use `grid.cellFlash` or `additionalData.cellFlash` to tune behavior. Defaults preserve legacy behavior: enabled, cell-only, 1000ms duration, replace active flashes on each flash event, and clear on source reset.

```ts
grid.cellFlash = {
  duration: 700,
  rowDuration: 1000,
  mode: 'cell-and-row',
  queue: 'merge',
  maxActive: 300,
  clearOnSourceChange: true,
  respectReducedMotion: true,
	  aria: {
	    enabled: true,
	    live: 'polite',
	    atomic: true,
	    liveRegionClassName: 'rv-cell-flash-live-region',
	  },
  labels: {
    cellUpdated: state => `Updated ${String(state.prop)} in row ${state.rowIndex + 1}`,
    rowUpdated: state => `Updated row ${state.rowIndex + 1}`,
  },
  className: 'cell-flash-active',
  rowClassName: 'row-flash-active',
};
```

Queue modes:

- `replace` clears current flash state before applying the next batch.
- `merge` keeps existing flashes active until their own timers expire.

Announcement priority is: per-change `ariaLabel`, `aria.label`, `labels.cellUpdated` or `labels.rowUpdated`, then the built-in defaults. Use `labels` for normal localization and `aria.label` when one callback should fully own every announcement. The live-region politeness, atomic flag, and live-region class are also configurable through `aria`.

## Manual Flash API

Manual methods are available from the plugin instance. This is useful when updates come from a websocket, polling loop, or external calculation.

```ts
const plugins = await grid.getPlugins();
const cellFlash = plugins.find(plugin => plugin.constructor.name === 'CellFlashPlugin');

cellFlash.flashCell({
  rowIndex: 0,
  prop: 'price',
  previousValue: 100,
  value: 104,
  direction: 'up',
});

cellFlash.flashRows({
  rowIndex: 0,
  rowClassName: 'manual-row-flash',
});

cellFlash.clearFlash({ rowIndex: 0, prop: 'price' });
```

The existing event API is still supported:

```ts
grid.dispatchEvent(new CustomEvent('flashcell', {
  detail: {
    data: { 0: { price: 104 } },
    previousData: { 0: { price: 100 } },
    type: 'rgRow',
  },
}));
```

## Styling

The plugin sets `flash`, `flash-direction`, `data-flash-direction`, and duration CSS variables on active cells. Row flashes receive `flash-row` and the configured row class.

```css
revo-grid {
  --rv-change-highlight: rgba(255, 238, 0, 0.6);
  --rv-row-change-highlight: rgba(255, 238, 0, 0.22);
  --rv-cell-flash-up-color: #15803d;
  --rv-cell-flash-down-color: #dc2626;
  --rv-cell-flash-arrow-transition-duration: 0.3s;
  --rv-cell-flash-arrow-transition-timing: ease-in-out;
}

revo-grid[theme^='dark'] {
  --rv-change-highlight: rgba(250, 204, 21, 0.34);
  --rv-row-change-highlight: rgba(250, 204, 21, 0.16);
  --rv-cell-flash-up-color: #4ade80;
  --rv-cell-flash-down-color: #f87171;
}

revo-grid .rgCell[flash][flash-direction="up"] {
  color: var(--rv-cell-flash-up-color);
}

revo-grid .rgRow[flash-row].large-move-row {
  font-weight: 600;
}
```

When `respectReducedMotion` is enabled, users with reduced-motion preferences keep the flash attributes and final highlight state without the animation.
