TL/DR
- This is an example of how to implement a responsive vertical mosaic/masonry grid with drag-and-drop support in ReactJS.
- You can check the live demo here.
- Here is a "Google Keep like" example.
- Check the source code for comments and tests.
As a way to brush up my skills, I decided to experiment creating a simple "Google Keep"-like note-taking app in ReactJS. However, while building it, I couldn't find a grid library with the features I wanted and that would work well with ReactJS.
What I was looking for was:
- Vertical staggering. Like in Pinterest and Google Keep.
- Dynamic/auto height depending on the length of the content.
- Easy to integrate with ReactJS.
- Self-organising. No layout configuration required.
- Being able to add and remove items dynamically.
- With Drag-and-Drop support.
- Responsive
I decided to create this example for anyone who is looking for something similar. Feel free to fork it and change it as you see fit.
The grid/mosaic
For the grid part, I found this pure CSS/JS implementation that works just fine. It uses CSS Grid for the responsive layout and JavaScript for adjusting how many rows an item should occupy.
To see my ReactJS adapted grid implementation using hooks, check the grid folder in the source code.
Drag And Drop
For the Drag and Drop implementation, I use a library called react-dnd. It provides the foundation and utilities for implementing Drag and Drop. I adapted their sortable example to be used in a grid.
You can see my implementation in the dnd folder.
To keep it simple, I handle items' order as a list, instead of a matrix, as people usually do for grids. This makes sorting easier and allows the grid to be responsive, as items can change rows without having to be sorted again.
You can check the source code for tests and comments that explain a little bit more about the implementation.
Improvements
There are a few improvements that can be made in my example.
First of all, when dragging an element in a touch-enabled device there is no preview (ghost) element. This is due to the Touch Drag and Drop API not supporting it. There are ways to work around it by using the react-dnd-preview plugin, which allows you to define a custom ghost item while dragging.
Another possible improvement is to use react-dnd-test-backend in unit tests for testing drag and drop behaviour. As I decided to not eject from create-react-app, to keep this example as simple as possible, I was not able to wire the test backend to my application. In a real project, I suggest using this test backend, as it provides many utilities and simplifies testing those components.
That's all
If you want to learn more about CSS grids, I recommend this awesome guide by CSS Tricks.
Check the source code for more information.
Feel free to reach to me if you have any questions. See you!