Declarative React Canvas Grid primitive for Data table, Pivot table, Excel Worksheets

Usage no npm install needed!

<script type="module">
  import reactKonvaGrid from '';


Declarative Canvas Grid with React Konva

Canvas table grid to render large set of tabular data. Uses virtualization similar to react-window and React-Konva for primitives such as Rect, Text, Shape etc

MIT license Build Status

Demo | Usage | Wiki

Screen capture


  • :electron: React powered declarative library
  • :100: Virtualized: Only visible cells are rendered
  • :bulb: Performant: Canvas implementation - 55-60fps (re-render) and 40-60fps (scroll)
  • :scroll: Supports scrolling using native scrollbars
  • :computer: Supports both Fixed and Variable sized grids
  • :fire: Freeze rows and columns
  • :white_square_button: Merge rows and columns
  • :hand: Resizable headers
  • :deciduous_tree: Create Tree tables
  • :musical_keyboard: Keyboard accessible
  • :page_with_curl: Pagination sync/async
  • :hammer_and_wrench: Fully typed API written in TypeScript
  • :rainbow: Full Theming and Context Support
  • :anchor: Fill handle support
  • :feet: Customizable undo/redo support
  • :iphone: Mobile/Touch device support
  • :muscle: Highly customizable using react-konva

Why another canvas grid library

Born out of frustration, having to deal with complicated imperative canvas libraries, I wanted to create something easy to understand and declarative in nature. This Grid primitive is built on top of React Konva making it easy to customize and extend. Take a look at the storybook to learn more.



yarn add react-konva-grid


npm install react-konva-grid --save


Konva grid will work in any browser that supports react, konva and canvas element.


Konva Grid is a pure renderer, that will work with many third-party table plugins

1. React-table

Uses react-table to create grouped headings and rows, and display on Konva Grid

2. Excel worksheet

3. Zustand - More control over cell level re-rendering

More examples coming soon.


import { Grid, Cell } from 'react-konva-grid'
import { Group, Text, Rect } from 'react-konva'

const App = () => {
  const data = {
    [[1, 2]]: 'Hello world'

  return (
      rowHeight={(rowIndex) => 20}
      columnWidth={(columnIndex) => 100}
      itemRenderer={(props) => (
            data[[props.rowIndex, props.columnIndex]]


This is the list of props that are meant to be used to customise the konva-grid behavior.

Name Required Type Description Default
width true number Width of the grid container 800
height true number Height of the grid container 800
columnCount true number No of columns in the grid 200
rowCount true number No of rows in the grid 200
rowHeight true function Function that returns height of the row based on rowIndex (rowIndex) => 20
columnWidth true function Function that returns width of the column based on columnIndex (columnIndex) => 100
itemRenderer true Function React component to render the cell null
selectionRenderer true Function React component to render selected cell null
scrollbarSize false number Size of the scrollbar 17
showScrollbar false boolean Always show scrollbar true
selectionBackgroundColor false string Background color of selected cells rgba(66, 133, 244, 0.3)
selectionBorderColor false string Border color of bounding box of selected cells rgba(66, 133, 244, 1)
selectionStrokeWidth false number Border width of selection 1
activeCellStrokeWidth false number Border width of activeCell 2
activeCell false { rowIndex, columnIndex } Recently active cell that user has clicked null
selections false Array Array of selected cell areas []
mergedCells false Array Array of merged cell areas []
cellAreas false Array Increase the range of certain cells []
snap false boolean Snaps to the next row or column as you scroll false
frozenRows false number No of frozen rows 0
frozenColumns false number No of frozen columns 0
showFrozenShadow false boolean Show shadow in frozen columns/rows true
shadowSettings false object Customize shadow of frozen columns/rows true
onBeforeRenderRow false Function Called right before a row is rendered, useful for react-table null
stageProps false Object Konva stage props null
children false Function Inject React Konva shapes using children null
wrapper false Function Inject custom context using a wrapper (children) => children
showFillHandle false boolean Show fill handle at bottom right corner true
onFillHandleMouseDown false Function Callback fired user selects fill handle null
fillSelection false SelectionProp Area of selected fill null
overscanCount false number Number of items outside the visible viewport should be renderer at all times 1


scrollTo({ scrollLeft, scrollTop }

Scrolls the grid to a specified x,y position relative to the container

resetAfterIndices({ rowIndex, columnIndex })

Imperatively trigger re-render of the grid after specified rowIndex or columnIndex


Get the current scroll position of the grid.

const gridRef = useRef()
const { scrollLeft, scrollTop } = gridRef.current.getScrollPosition()

isMergedCell({ rowIndex, columnIndex })

Check if a cell at a coordinate is a merged cell

getCellBounds({ rowIndex, columnIndex })

Returns a selection IArea for a particular cell. Useful to get selection area of a merged cell

getCellCoordsFromOffsets(x , y)

Returns exact rowIndex and columnIndex from a x and y cordinate. Useful if you want to get cell coords based on mouse position

getCellOffsetFromCoords({ rowIndex, columnIndex })

Returns offset position { x, y, width, height } of a cell


Access Konva stage instance

const gridRef = useRef()


const stage = gridRef.current.stage

Passing Contexts

React Konva uses react-reconciler to create a custom React renderer. Which means Top Level Context is not available inside the canvas. We provide a simple wrapper prop to pass Context to the Grid

const ThemeContext = React.createContext({})
const theme = { color: 'yellow' }
  wrapper={(children) => {
    return (
      <ThemeContext.Provider value={theme}>

This will let you use ThemeContext in any of the React Konva components. To access theme inside Cell, you could do

const Cell = ({ x, y, width, height }) => {
  const theme = useContext(ThemeContext)

  return (


Examples can be found in stories directory. To run storybook, enter the following commands

yarn run storybook


Feel free to fork and submit pull requests

git clone
cd konva-grid
// Run storybook
yarn storybook