Life Grid

Conway's Game of Life runs on a seeded grid, newborn cells flashing in the accent and dying cells shrinking away

Installation
$ pnpm dlx shadcn@latest add @remocn/life-grid

Usage

LifeGrid plays Conway's Game of Life. A seeded first generation fills a density share of the cells, and every next generation follows the standard rules: a live cell with two or three live neighbors survives, and an empty cell with exactly three is born. The board wraps at the edges, so patterns leave one side and come back on the other, and the border never runs dry.

The step between generations is animated. A newborn cell pops in as an accent tile with a small overshoot, then a tile in color grows from its center and covers it. A dying cell shrinks to nothing in the first 60% of the step. Surviving cells hold still. A faint lattice marks the empty cells.

tsx
import { LifeGrid } from "@/components/remocn/life-grid";
 
export const Simulation = () => <LifeGrid />;

The component fills its parent and paints its own background. cols sets the number of columns, the row count follows the composition aspect ratio, and the square board is centered. Generations are computed once per seed, grid size and density and cached for the render, so every frame is deterministic and cheap after the first.

Timing

At 30 fps, speed={1} and framesPerGeneration={5}:

FramesMotion
0–5The seeded first generation holds still
5Generation 1 begins: newborns pop in as accent tiles, dying cells start to shrink
5–8Dying cells shrink away
7–10The core of each newborn grows over its accent tile
every 5 framesThe next generation starts

The simulation runs for as long as the composition: it precomputes durationInFrames × speed / framesPerGeneration generations. It has no loop point. Over a long run the board can settle into still lifes and blinkers; try another seed or a higher density if a seed calms down too early.

Variations

Fewer cols gives big, readable cells; more gives a fine texture. framesPerGeneration slows the simulation for a calmer bed; at 1 the board churns every frame. showGrid={false} removes the lattice, and gap={0} merges neighboring cells into solid shapes.

tsx
<LifeGrid
  cols={24}
  density={0.3}
  framesPerGeneration={8}
  gap={0.08}
  showGrid={false}
  background="#f6f5f1"
  color="#171717"
  accent="#2f6bff"
/>

Props10

PropTypeDefault
cols
number48

Columns, rounded, minimum 4; rows follow the frame aspect ratio

density
number0.24

Share of cells alive in the seeded first generation, 0 to 1

framesPerGeneration
number5

Frames each generation is held, minimum 1

gap
number0.16

Gap between tiles as a fraction of the cell

showGrid
booleantrue

Draws the faint lattice of empty cells

seed
number7

Seeds the first generation

background
string"#111111"

Background fill

color
string"#FFFFFF"

Living cells and the lattice

accent
string"#E5322D"

Flash color of newborn cells

speed
number1

Playback multiplier; 0 holds the first generation

  • colsnumber

    Columns, rounded, minimum 4; rows follow the frame aspect ratio

    Default48

  • densitynumber

    Share of cells alive in the seeded first generation, 0 to 1

    Default0.24

  • framesPerGenerationnumber

    Frames each generation is held, minimum 1

    Default5

  • gapnumber

    Gap between tiles as a fraction of the cell

    Default0.16

  • showGridboolean

    Draws the faint lattice of empty cells

    Defaulttrue

  • seednumber

    Seeds the first generation

    Default7

  • backgroundstring

    Background fill

    Default"#111111"

  • colorstring

    Living cells and the lattice

    Default"#FFFFFF"

  • accentstring

    Flash color of newborn cells

    Default"#E5322D"

  • speednumber

    Playback multiplier; 0 holds the first generation

    Default1