react-broken-layouter
Version:
Layouter is a lightweight React utility for creating responsive masonry-style layouts.
261 lines (194 loc) β’ 8.8 kB
Markdown
# React Broken Layouter
A lightweight React utility for creating responsive masonry-style layouts with automatic height estimation and column distribution.
## Table of Contents
- [Features](#features)
- [Environment Compatibility](#environment-compatibility)
- [Recommended Usage](#recommended-usage)
- [Server Component Usage](#server-component-usage)
- [Not Recommended](#not-recommended)
- [Considerations](#considerations)
- [Installation](#installation)
- [Usage](#usage)
- [Basic Example](#basic-example)
- [Custom Render](#custom-render)
- [Responsive Layout with `breakpoints`](#responsive-layout-with-breakpoints)
- [Props](#props)
- [Utility Functions](#utility-functions)
- [Experimental Features](#experimental-features)
- [How It Works](#how-it-works)
- [Development](#development)
- [License](#license)
- [Contributing](#contributing)
## Features
- π― Simple and intuitive API
- π± Responsive column-based layout
- π Automatic height estimation
- π¨ Customizable gap between items
- π Support for dynamic content
- π Zero dependencies (except React)
- π¦ TypeScript support
- π οΈ Utility functions for common tasks
## Environment Compatibility
This component is primarily designed for client-side use in React applications. While it doesn't use React hooks, it relies on client-side calculations for optimal layout and height estimation.
### Recommended Usage
- β
Client-side React applications
- β
Browser environments
- β
React 17+ and React 18+
- β
Next.js client components (with 'use client' directive)
- β
Client-side rendered pages
### Server Component Usage
To use this component with server components in frameworks like Next.js, follow these guidelines:
- Use the `'use client'` directive at the top of the file where you import and use the Layouter:
```tsx
"use client";
import Layouter from "react-broken-layouter";
```
- Provide explicit heights via `getHeight` or `estimateHeight` props to ensure consistent layout:
```tsx
<Layouter
cols={3}
items={items}
render={Item}
getHeight={(item) => item.height} // Provide explicit heights
/>
```
### Not Recommended
- β Server Components without 'use client' directive
- β Server-side rendering without proper client-side hydration
- β Static site generation without client-side JavaScript
### Considerations
- β οΈ Height estimation is most accurate in client environments
- β οΈ For server-side rendering, consider providing explicit heights via `getHeight` or `estimateHeight` props
- β οΈ Dynamic content may require client-side re-rendering for optimal layout
## Installation
```bash
npm install react-broken-layouter
# or
yarn add react-broken-layouter
```
## Usage
### Basic Example
A simple setup with a fixed number of columns:
```tsx
import Layouter from "react-broken-layouter";
const items = [
{ id: 1, content: "Item 1" },
{ id: 2, content: "Item 2" },
// ...
];
const Item = ({ item }) => (
<div style={{ padding: "1rem", background: "#f0f0f0" }}>{item.content}</div>
);
export default function App() {
return (
<Layouter
cols={3} // Fixed column count
items={items}
render={Item} // Render component
gap={16} // Space between items
getId={(item) => item.id} // Unique key for each item
/>
);
}
```
### Custom Render
You can provide a custom render function that returns a component to display each item. The function receives an `item` prop, which you can pass to your component:
```tsx
const YourComponent = ({ item }) => (
<div style={{ padding: "1rem", background: "#e0e0e0" }}>{item.content}</div>
);
<Layouter
cols={3} // Fixed column count
items={items}
render={(props) => <YourComponent {...props} />} // Custom render function
gap={16} // Space between items
getId={(item) => item.id} // Unique key for each item
/>;
```
> **Note**: The `render` prop expects a component that accepts an `item` prop. Using a function allows dynamic rendering while maintaining compatibility.
## Responsive Layout with `breakpoints`
Use the `breakpoints` prop to override the default `cols` value based on screen width, ideal for responsive layouts:
```tsx
<Layouter
cols={1} // Default to 1 column (e.g., for mobile)
items={items}
render={Item}
gap={16}
getId={(item) => item.id}
breakpoints={{
768: { cols: 2 },
1024: { cols: 3 },
1440: { cols: 4 },
}}
/>
```
This dynamically sets:
- 1 column below 768px (using `cols`)
- 2 columns from 768px to 1023px
- 3 columns from 1024px to 1439px
- 4 columns at 1440px and above
## Props
| Prop | Type | Required | Default | Description |
| ---------------- | ------------------------------------- | :------: | :-----: | ----------------------------------------------------------------------- |
| `cols` | number | β
| - | Default number of columns (overridden by `breakpoints` if provided) |
| `breakpoints` | { [width: number]: { cols: number } } | β | - | Map of viewport widths to column counts for responsive behavior |
| `items` | any[] | β
| - | List of items to display |
| `render` | React.FC<{ item: any }> | β
| - | Component to render each item (can be a function returning a component) |
| `gap` | number | β | 16 | Gap between items (px) |
| `getId` | (item: any) => string \| number | β | - | Optional function to get unique ID for each item |
| `getHeight` | (item: any) => number | β | - | Exact item height (for layout optimization) |
| `estimateHeight` | (item: any) => number | β | - | Estimate item height if exact value isn't available |
| `mediaHeight` | number | β | - | Additional height buffer (e.g., for images or media content) |
## Utility Functions
These utility functions simplify common tasks like height estimation and ID generation:
- **`heightEstimator`**
Estimates the total height based on an array of strings or numbers. Useful for calculating content heights.
```tsx
import { heightEstimator } from "react-broken-layouter";
// Example usage
const content = ["Hello", "World", 100];
const estimatedHeight = heightEstimator(content);
// Returns: (5 * 0.35) + (5 * 0.35) + 100 = 103.5
```
- **`getRandomId`**
Generates a random string ID. Useful for creating unique keys when none are provided.
```tsx
import { getRandomId } from "react-broken-layouter";
// Example usage
const uniqueId = getRandomId();
// Returns something like: "x7f9k2m"
```
- **`isObject`**
Checks if a value is a plain object (not an array or null).
```tsx
import { isObject } from "react-broken-layouter";
// Example usage
isObject({}); // true
isObject([]); // false
isObject(null); // false
isObject("string"); // false
```
## Experimental Features
> **Note**: These features are experimental and may not work perfectly in all scenarios. Test thoroughly with your use case.
### Height Estimation
The height estimation features (**`getHeight`** and **`estimateHeight`**) are currently experimental and may be subject to change in future versions. These features provide ways to control the height of items in the layout:
- **`getHeight`**: Allows you to provide exact heights for items
- **`estimateHeight`**: Lets you implement custom height estimation logic
## How It Works
The Layouter component:
1. Estimates the height of each item based on content length
2. Distributes items across columns to maintain balanced heights
3. Renders items in a responsive grid layout
## Development
```bash
# Install dependencies
npm install
# Run development build
npm run dev
# Build for production
npm run build
```
## License
MIT Β© [Hassan Mohamed](https://github.com/HassanMostafa)
## Contributing
Weβd love to improve React Broken Layouter with your help! Contributions are welcomeβplease feel free to submit a Pull Request or open an issue to discuss your ideas.