README
react-listitem-grid
Utilities and components for responsive grid layout of list items. See example use cases.
Table of Contents
- Installation
- Should I Use This Library?
- What's in This Library?
- How Do I Use This Library?
- Want to Help?
- Contributors
- License
Installation
npm install react-listitem-grid
This library has minimal peer depencency on @babel/runtime
, which is probably
already present in your React project.
If you use the React hook and components from this library, you'll also need the
react
peer dependency.
Should I Use This Library?
This library currently satisfies some very narrow use cases.
List Item Width
â Use This Library
Your list item has a width range constraint. A good example is a result card design that works well with a minimum width of 150px and a maximum width of 350px.
đĢ Don't Use This Library
- Your list item has a fixed width.
- Your list item only has minimum width, but can freely grow to any size.
There are much simpler ways (CSS-only if you're using grid) to solve the problem.
List Item Alignment
â Use This Library
Your list items must always left-align within the grid.
đĢ Don't Use This Library
If your list items need to do anything else.
Items Per Row
â Use This Library
You want to maximize either by item width or by number of items per row.
đĢ Don't Use This Library
If you just need to maximize by number of items. There are simpler solutions.
Maximum Number of Rows
â Use This Library
You need to know how many items the grid container will be rendering, based on the optionally specified maximum number of rows. This is useful, for example, to know how many records to request from the back-end API.
What's in This Library?
Utils
There are some JavaScript utilities which can be used in any project.
calculateLayoutSpec()
This function does all the calculations and returns an object with:
itemWidth
: The exact pixel width of each list item.rowCount
: Number of items per row.desiredItemCount
: How many items should be rendered if themaxRows
constraint is given. This value isundefined
ifmaxRows
is0
orundefined
.containerWidth
: only useful for flexbox-based layout, where the actual container size is larger than what appears visually in order to accommodate column gaps.
â ī¸ If you decide to use CSS flexbox to render the grid, be sure to pass
isFlex: true
.
calculateItemWidthWithCount()
This is used to recalculate the itemWidth
once the number of results are
known. For example, the container width may be able to fit 5 items across at
300px each. However, there are only 4 items to be displayed, we'll want to
display them at their maximum width of 350px instead of at 300px.
flexCompensate
flexCompensate.container()
which returns the CSSmargin
andwidth
values to be applied to the flex container.flexCompensate.item()
which returns the CSSmargin
value to be applied to the flex item.
Hook useCalculateLayout
A convenience hook which uses ResizeObserver to measure the width of the
grid container. It returns all the values from utils.calculateLayoutSpec()
plus a containerRef
, which you attach as a ref
to a grid container in your
JSX. E.g.:
import { useCalculateLayout } from "react-listitem-grid";
function MyComponent() {
const { containerRef, ...calculatedValues } = useCalculateLayout(calParams);
return <ul ref={containerRef}>...</ul>;
}
This will ensure calculatedValues
is updated if <ul>
is resized.
You don't need to use this hook if you want to handle things differently, in
that case, just use calculateLayoutSpec()
directly.
âšī¸ For browsers that do not support ResizeObserver, the library will
automatically ponyfill with @juggle/resize-observer
via dynamic import.
â ī¸ If you decide to use CSS flexbox to render the grid, be sure to pass
isFlex: true
.
React Components
These components are supplied simply as styling conveniences, you don't have to
use them. These components do not use the useCalculateLayout
hook, so it's up
to you to wire things up. Refer to the source code or the example app to see
what props are required.
Each compound component has Container
and Item
. Container
is marked up as
<ul>
and Item
is marked up as <li>
.
Each component also comes with its own CSS which must be imported if you want the default layout behavior.
Example:
import { Grid, useCalculateLayout } from "react-listitem-grid";
import "react-listitem-grid/Grid/styles.css";
function MyComponent() {
const { containerRef, itemWidth } = useCalculateLayout(calParams);
return (
<Grid.Container itemWidth={itemWidth} columnGap={16} rowGap={16}>
{items.map((item) => (
<Grid.Item key={item.id}>{item.name}</Grid.Item>
))}
</Grid.Container>
);
}
The components should be flexible enough that you can apply additional styling however you want: regular CSS, CSS modules, CSS-with-JS.
Grid
If you work with modern browsers that support CSS grid.
Flex
If you need to support older browsers with iffy or no grid support, e.g. Internet Explorer. This has been tested to work with IE 11.
How Do I Use This Library?
Example App
This repo contains an example app, which shows the effects of
making adjustments calculateLayoutSpec()
's params. You can clone this repo and
run it locally:
npm run init-dev
npm start
You can also play with the deployed example app.
Typical Workflow
The example app demonstrates a typical workflow of how to use this library.
Get the calculated values based on container width. The easiest way is to use
useCalculateLayout
by supplying some initial layout specs.Recalculate the item width if needed. This is necessary if the total number of items is less then
rowCount
(number of items per row).
The following files specifically use this library:
Want to Help?
Check out the task board and how to contribute.
Contributors
Thanks goes to these people (emoji key):
George Song đģ đ đĄ đ¤ đ đ§ đ |
Hanna đģ đ đĄ đ¤ |
This project follows the all-contributors specification. Contributions of any kind welcome!