Convert Figma logo to code with AI

dantrain logoreact-stonecutter

Animated grid layout component for React

1,215
72
1,215
19

Top Related Projects

A lightweight magic-move library for configurable layout transitions

Effortless animation between DOM changes (eg. list reordering) using the FLIP technique.

🎊 A collection of animations for inline style libraries

An easy way to perform animations when a React component enters or leaves the DOM

✌️ A spring physics based React animation library

23,338

Open source, production-ready animation and gesture library for React

Quick Overview

React-stonecutter is a React component library for creating animated grid layouts. It provides a flexible and performant way to create masonry-style layouts with smooth transitions when items are added, removed, or reordered.

Pros

  • Easy to implement responsive grid layouts with minimal code
  • Smooth animations for adding, removing, and reordering grid items
  • Supports both CSS transitions and spring animations
  • Customizable with various layout options and animation settings

Cons

  • Limited documentation and examples
  • Not actively maintained (last update was in 2018)
  • May have compatibility issues with newer React versions
  • Performance might degrade with a large number of grid items

Code Examples

  1. Basic Grid Layout:
import { CSSGrid, layout } from 'react-stonecutter';

const Grid = ({ items }) => (
  <CSSGrid
    component="ul"
    columns={5}
    columnWidth={150}
    gutterWidth={5}
    gutterHeight={5}
    layout={layout.pinterest}
    duration={800}
    easing="ease-out"
  >
    {items.map(item => (
      <li key={item.id}>{item.content}</li>
    ))}
  </CSSGrid>
);
  1. Spring Animation Grid:
import { SpringGrid, makeResponsive } from 'react-stonecutter';

const Grid = makeResponsive(SpringGrid, {
  maxWidth: 1920,
  minPadding: 100
});

const MyGrid = ({ items }) => (
  <Grid
    component="ul"
    columns={3}
    columnWidth={250}
    gutterWidth={10}
    gutterHeight={10}
    itemHeight={200}
    springConfig={{ stiffness: 170, damping: 26 }}
  >
    {items.map(item => (
      <li key={item.id}>{item.content}</li>
    ))}
  </Grid>
);
  1. Custom Layout Function:
import { CSSGrid, enterExitStyle } from 'react-stonecutter';

const customLayout = (itemProps, gridProps) => {
  // Custom layout logic here
  return { ...itemProps, left: x, top: y };
};

const Grid = ({ items }) => (
  <CSSGrid
    component="ul"
    columns={4}
    columnWidth={200}
    layout={customLayout}
    enter={enterExitStyle.fromTop}
    entered={enterExitStyle.scale}
    exit={enterExitStyle.toBottom}
  >
    {items.map(item => (
      <li key={item.id}>{item.content}</li>
    ))}
  </CSSGrid>
);

Getting Started

  1. Install the package:

    npm install react-stonecutter
    
  2. Import and use in your React component:

    import React from 'react';
    import { CSSGrid, layout } from 'react-stonecutter';
    
    const MyGrid = ({ items }) => (
      <CSSGrid
        component="ul"
        columns={3}
        columnWidth={200}
        gutterWidth={10}
        gutterHeight={10}
        layout={layout.simple}
        duration={400}
      >
        {items.map(item => (
          <li key={item.id}>{item.content}</li>
        ))}
      </CSSGrid>
    );
    
    export default MyGrid;
    
  3. Customize the grid properties and layout as needed for your specific use case.

Competitor Comparisons

A lightweight magic-move library for configurable layout transitions

Pros of react-flip-toolkit

  • More flexible animation system, allowing for complex transitions and staggered animations
  • Better performance for large lists and complex layouts
  • Active maintenance and regular updates

Cons of react-flip-toolkit

  • Steeper learning curve due to more advanced API
  • Requires more setup and configuration for basic use cases

Code Comparison

react-flip-toolkit:

<Flipper flipKey={listData}>
  {listData.map(item => (
    <Flipped key={item.id} flipId={item.id}>
      <div>{item.content}</div>
    </Flipped>
  ))}
</Flipper>

react-stonecutter:

<SpringGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
>
  {items.map(item => <li key={item.id}>{item.content}</li>)}
</SpringGrid>

react-flip-toolkit offers more granular control over animations and transitions, while react-stonecutter provides a simpler API for grid-based layouts. react-flip-toolkit is better suited for complex, custom animations, whereas react-stonecutter excels in quickly creating responsive grid layouts with basic transitions.

Effortless animation between DOM changes (eg. list reordering) using the FLIP technique.

Pros of react-flip-move

  • More focused on animating list changes, providing smoother transitions
  • Supports both DOM and React Native environments
  • Actively maintained with recent updates and bug fixes

Cons of react-flip-move

  • Limited to list animations, less versatile for complex grid layouts
  • Requires more manual configuration for advanced use cases
  • May have a steeper learning curve for beginners

Code Comparison

react-flip-move:

<FlipMove enterAnimation="fade" leaveAnimation="fade">
  {items.map(item => (
    <div key={item.id}>{item.content}</div>
  ))}
</FlipMove>

react-stonecutter:

<SpringGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
>
  {items.map(item => (
    <li key={item.id}>{item.content}</li>
  ))}
</SpringGrid>

react-stonecutter offers more built-in layout options and grid-specific features, while react-flip-move focuses on smooth list transitions. react-stonecutter may be better suited for complex grid layouts, while react-flip-move excels in simple list animations across different platforms.

🎊 A collection of animations for inline style libraries

Pros of react-animations

  • Provides a wide range of pre-defined animations, making it easy to implement common animation effects
  • Integrates well with popular CSS-in-JS libraries like styled-components and Emotion
  • Lightweight and focused solely on animation keyframes

Cons of react-animations

  • Lacks built-in layout management capabilities for grid-like structures
  • Doesn't provide automatic animation of elements entering or leaving the DOM
  • Requires additional setup to handle responsive layouts

Code Comparison

react-animations:

import { fadeIn } from 'react-animations';
import styled, { keyframes } from 'styled-components';

const fadeInAnimation = keyframes`${fadeIn}`;
const FadeInDiv = styled.div`animation: 1s ${fadeInAnimation};`;

react-stonecutter:

import { SpringGrid, makeResponsive } from 'react-stonecutter';

const Grid = makeResponsive(SpringGrid, {
  maxWidth: 1920,
  minPadding: 100
});

<Grid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
  springConfig={{ stiffness: 170, damping: 26 }}
>
  {items}
</Grid>

react-stonecutter focuses on creating animated grid layouts with responsive capabilities, while react-animations provides a set of predefined animation keyframes that can be applied to any element. react-stonecutter offers more comprehensive layout management, whereas react-animations is more flexible for applying animations to individual elements.

An easy way to perform animations when a React component enters or leaves the DOM

Pros of react-transition-group

  • More widely adopted and maintained by the React core team
  • Offers a broader range of transition components (CSSTransition, SwitchTransition, TransitionGroup)
  • Better documentation and community support

Cons of react-transition-group

  • Requires more manual setup for complex grid layouts
  • Less specialized for masonry or grid-specific animations

Code Comparison

react-transition-group:

<CSSTransition
  in={inProp}
  timeout={200}
  classNames="fade"
  unmountOnExit
>
  <div>Transitioning content</div>
</CSSTransition>

react-stonecutter:

<SpringGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
>
  {items.map(item => <li key={item.id}>{item.content}</li>)}
</SpringGrid>

Summary

react-transition-group is a more versatile and widely-supported library for general transitions in React applications. It offers a range of components for different transition needs but requires more setup for complex layouts. react-stonecutter, on the other hand, is specifically designed for grid and masonry layouts with built-in animation capabilities, making it easier to implement animated grid layouts but with a narrower focus.

✌️ A spring physics based React animation library

Pros of react-spring

  • More comprehensive animation library with a wider range of features
  • Better performance for complex animations due to its spring-physics based approach
  • Larger community and more frequent updates

Cons of react-spring

  • Steeper learning curve due to its more complex API
  • Potentially overkill for simple layout animations

Code Comparison

react-spring:

import { useSpring, animated } from 'react-spring'

function AnimatedComponent() {
  const props = useSpring({ opacity: 1, from: { opacity: 0 } })
  return <animated.div style={props}>I will fade in</animated.div>
}

react-stonecutter:

import { SpringGrid } from 'react-stonecutter'

function GridComponent() {
  return (
    <SpringGrid
      component="ul"
      columns={5}
      columnWidth={150}
      gutterWidth={5}
      gutterHeight={5}
      itemHeight={200}
    >
      {items.map(item => <li key={item.id}>{item.content}</li>)}
    </SpringGrid>
  )
}

react-spring offers more flexibility for general animations, while react-stonecutter is specifically designed for grid layouts. react-spring's API is more verbose but allows for more customization, whereas react-stonecutter provides a simpler API for its specific use case.

23,338

Open source, production-ready animation and gesture library for React

Pros of Motion

  • More comprehensive animation library with a wider range of features
  • Active development and larger community support
  • Better performance optimization for complex animations

Cons of Motion

  • Steeper learning curve due to more extensive API
  • Larger bundle size, which may impact load times for smaller projects

Code Comparison

Motion:

import { motion } from "framer-motion"

<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  transition={{ duration: 0.5 }}
>
  Hello World
</motion.div>

React-Stonecutter:

import { SpringGrid } from 'react-stonecutter';

<SpringGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
  springConfig={{ stiffness: 170, damping: 26 }}
>
  {items}
</SpringGrid>

Motion offers a more flexible approach to animations, allowing for complex transitions and gestures. React-Stonecutter focuses specifically on grid layouts with built-in animations, providing a simpler API for this specific use case. While Motion is more versatile, React-Stonecutter may be easier to implement for grid-based layouts.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

react-stonecutter npm version

Animated grid layout component for React, inspired by Masonry.
Choose between CSS Transitions or React-Motion for animation.

Demo

Installation

With npm:

npm install --save react-stonecutter

Usage

A simple layout with items of equal height:

import { SpringGrid } from 'react-stonecutter';
<SpringGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
  springConfig={{ stiffness: 170, damping: 26 }}
>
  <li key="A">A</li>
  <li key="B">B</li>
  <li key="C">C</li>
</SpringGrid>

A Pinterest-style layout with varying item heights, this time using CSS transitions:

import { CSSGrid, layout } from 'react-stonecutter';
<CSSGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  layout={layout.pinterest}
  duration={800}
  easing="ease-out"
>
  <li key="A" itemHeight={150}>A</li>
  <li key="B" itemHeight={120}>B</li>
  <li key="C" itemHeight={170}>C</li>
</CSSGrid>

To render React components as children, wrap them in simple elements. This gives you full control of your markup:

<SpringGrid
  component="ul"
  // ...etc.
>
  {data.map((datum) => (
    <li key={datum.id}>
      <MyComponent datum={datum} />
    </li>
  ))}
</SpringGrid>

If you don't know the heights of your items ahead of time, use the measureItems higher-order component to measure them in the browser before layout:

import { SpringGrid, measureItems } from 'react-stonecutter';

const Grid = measureItems(SpringGrid);
<Grid
  // ...etc.
>
  <li key="A">Who controls the British crown?</li>
  <li key="B">Who keeps the metric system down?</li>
  <li key="C">We do!</li>
  <li key="D">We do!</li>
</Grid>

If your grid spans the page and you want to vary the number of columns based on the viewport width, use the makeResponsive higher-order component which makes use of enquire.js:

import { CSSGrid, measureItems, makeResponsive } from 'react-stonecutter';

const Grid = makeResponsive(measureItems(CSSGrid), {
  maxWidth: 1920,
  minPadding: 100
});

API Reference

Exports:

  • SpringGrid
  • CSSGrid
  • measureItems
  • makeResponsive
  • layout
  • enterExitStyle
  • easings

SpringGrid and CSSGrid props

columns={Number}
Number of columns. Required.
You can wrap the Grid component in the makeResponsive higher-order component to set this dynamically.

columnWidth={Number}
Width of a single column, by default in px units. Required.

gutterWidth={Number}
Width of space between columns. Default: 0.

gutterHeight={Number}
Height of vertical space between items. Default: 0.

component={String}
Change the HTML tagName of the Grid element, for example to 'ul' or 'ol' for a list. Default: 'div'.

layout={Function}
Use one of the included layouts, or create your own. Defaults to a 'simple' layout with items of fixed height.
Included layouts:

import { layout } from 'react-stonecutter';

const { simple, pinterest } = layout;

The function is passed two parameters; an Array of the props of each item, and the props of the Grid itself. It must return an object with this shape:

{
  positions: // an Array of [x, y] coordinate pairs like this: [[0, 0], [20, 0], [0, 30]]
  gridWidth: // width of the entire grid (Number)
  gridHeight: // height of the entire grid (Number)
}

Have a look at the code for the included layouts to get a feel for creating your own.

enter={Function}
entered={Function}
exit={Function}
These allow you to change how items animate as they appear and disappear from the grid. Supply functions that return objects with the opacity and transform values for an item's start and end states. By default the item's scale and opacity go from 0 to 1 and back to 0 on exit, like this:

enter={() => ({ scale: 0, opacity: 0 })}
entered={() => ({ scale: 1, opacity: 1 })}
exit={() => ({ scale: 0, opacity: 0 })}

The functions are passed three parameters, the item props, grid props and grid state which includes the current height and width of the grid. For example to have disappearing items fall off the bottom of the grid:

exit={(itemProps, gridProps, gridState) => ({ translateY: gridState.gridHeight + 500 })}

CSS transform-functions are split up so they can be easily animated individually. Supported functions:

  • translateX
  • translateY
  • translateZ
  • skew
  • skewX
  • skewY
  • scale
  • scaleX
  • scaleY
  • rotate
  • rotateX
  • rotateY

Some example functions are included:

import { enterExitStyle } from 'react-stonecutter';

const { enter, entered, exit } = enterExitStyle.foldUp;

Check out the demo to see them in action.

perspective={Number}
The perspective distance used for 3D transforms. If you are using a transform function like rotateX, use this to strengthen the effect. Default is no perspective applied.

lengthUnit={String}
The length unit used throughout. Default: 'px'. Experimental. You could try using 'em' or 'rem' and then adjust the font-size for a fluid layout, but it may not work well with the measureItems and makeResponsive higher-order components. % does not work well due to the way CSS transforms work.

angleUnit={String}
The angle unit. Affects transform-functions such as rotate. Default: 'deg'.

SpringGrid only props

springConfig={Object}
Configuration of the React-Motion spring. See the React-Motion docs for more info. Default: { stiffness: 60, damping: 14, precision: 0.1 }.

CSSGrid only props

duration={Number}
Animation duration in ms. Required.

easing={String}
Animation easing function in CSS transition-timing-function format. Some Penner easings are included for convenience:

import { easings } from 'react-stonecutter';

const { quadIn, quadOut, /* ..etc. */  } = easings;

Default: easings.cubicOut.

measureItems options

Pass like this:

const Grid = measureItems(SpringGrid, { measureImages: true })

measureImages: Boolean
If set to true, waits for images to load before measuring items and adding them to the Grid. This may be necessary if you don't know the height of your images ahead of time. Powered by imagesLoaded.

background: Boolean|String
This option is passed through to the imagesLoaded library. It allows you to wait for background images to load, in addition to <img> tags.

makeResponsive options

Pass like this:

const Grid = makeResponsive(SpringGrid, { maxWidth: 1920 })

maxWidth: Number
Maximum width for the Grid in px.

minPadding: Number
Minimum horizontal length between the edge of the Grid and the edge of the viewport in px. Default: 0.

defaultColumns: Number
Default number of columns before the breakpoints kick in. May be useful when rendering server-side in a universal app. Default: 4.

Alternatives

If you have a list already nicely laid out by the browser, check out React Flip Move which uses the very cool FLIP technique.

License

MIT

NPM DownloadsLast 30 Days