├── src ├── components │ └── bento-grid │ │ ├── index.ts │ │ └── bento-grid.tsx ├── styles │ └── globals.css ├── index.ts ├── lib │ └── index.ts └── types.ts ├── .husky └── pre-commit ├── public ├── example.png └── react_bento.png ├── postcss.config.js ├── global.d.ts ├── tailwind.config.cjs ├── _gitignore ├── .gitignore ├── tsconfig.json ├── .eslintrc.json ├── rollup.config.js ├── package.json └── README.md /src/components/bento-grid/index.ts: -------------------------------------------------------------------------------- 1 | export {BentoGrid} from "./bento-grid" -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /public/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anbrela/react-bento/HEAD/public/example.png -------------------------------------------------------------------------------- /src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /public/react_bento.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anbrela/react-bento/HEAD/public/react_bento.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import "./styles/globals.css"; 2 | 3 | export * from "./components/bento-grid"; 4 | export * from "./types"; 5 | -------------------------------------------------------------------------------- /global.d.ts: -------------------------------------------------------------------------------- 1 | // global.d.ts 2 | declare module "*.css" { 3 | const content: { [className: string]: string }; 4 | export default content; 5 | } 6 | -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...args: ClassValue[]) { 5 | return twMerge(clsx(args)); 6 | } -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], 3 | content: ["./src/**/*.{html,js, ts, tsx}"], 4 | darkMode: false, 5 | theme: { 6 | extend: {}, 7 | }, 8 | variants: { 9 | extend: {}, 10 | }, 11 | plugins: [], 12 | }; 13 | -------------------------------------------------------------------------------- /_gitignore: -------------------------------------------------------------------------------- 1 | # Node modules 2 | node_modules/ 3 | 4 | # Build output 5 | dist/ 6 | 7 | # Logs 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Dependency directories 13 | jspm_packages/ 14 | 15 | # TypeScript cache 16 | *.tsbuildinfo 17 | 18 | # Optional eslint cache 19 | .eslintcache 20 | 21 | # Mac system files 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node modules 2 | node_modules/ 3 | 4 | # Build output 5 | dist/ 6 | 7 | # Logs 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Dependency directories 13 | jspm_packages/ 14 | 15 | # TypeScript cache 16 | *.tsbuildinfo 17 | 18 | # Optional eslint cache 19 | .eslintcache 20 | 21 | # Mac system files 22 | .DS_Store 23 | 24 | /example -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "jsx": "react-jsx", 6 | "strict": true, 7 | "moduleResolution": "node", 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "declaration": true, 12 | "declarationDir": "./dist/types", 13 | "outDir": "./dist" 14 | }, 15 | "include": ["src"] 16 | } 17 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export type BentoItem = { 4 | id: number; 5 | title: string; 6 | element: React.ReactNode; 7 | width: number; 8 | color?: string; 9 | height: number; 10 | }; 11 | 12 | export type BentoItems = BentoItem[]; 13 | 14 | export type ClassNames = { 15 | container?: string; 16 | elementContainer?: string; 17 | }; 18 | 19 | export type BentoGridProps = { 20 | items: BentoItems; 21 | gridCols?: number; 22 | rowHeight?: number; 23 | classNames: ClassNames; 24 | }; 25 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:react/recommended", 9 | "plugin:@typescript-eslint/recommended" 10 | ], 11 | "parser": "@typescript-eslint/parser", 12 | "parserOptions": { 13 | "ecmaFeatures": { 14 | "jsx": true 15 | }, 16 | "ecmaVersion": 12, 17 | "sourceType": "module" 18 | }, 19 | "plugins": ["react", "@typescript-eslint"], 20 | "rules": { 21 | "react/react-in-jsx-scope": "off" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import external from "rollup-plugin-peer-deps-external"; 2 | import resolve from "@rollup/plugin-node-resolve"; 3 | import commonjs from "@rollup/plugin-commonjs"; 4 | import typescript from "@rollup/plugin-typescript"; 5 | import postcss from "rollup-plugin-postcss"; 6 | import tailwindcss from "tailwindcss"; 7 | import autoprefixer from "autoprefixer"; 8 | 9 | export default { 10 | input: "src/index.ts", 11 | output: [ 12 | { 13 | file: "dist/index.cjs.js", 14 | format: "cjs", 15 | sourcemap: true, 16 | exports: "auto", 17 | }, 18 | { 19 | file: "dist/index.esm.js", 20 | format: "esm", 21 | sourcemap: true, 22 | }, 23 | ], 24 | plugins: [ 25 | external(), 26 | resolve(), 27 | commonjs(), 28 | typescript({ 29 | tsconfig: "./tsconfig.json", 30 | declaration: true, 31 | declarationDir: "./dist/types", 32 | rootDir: "src", 33 | }), 34 | postcss({ 35 | plugins: [tailwindcss(), autoprefixer()], 36 | extensions: [".css"], 37 | minimize: true, 38 | inject: { 39 | insertAt: "top", 40 | }, 41 | }), 42 | ], 43 | external: ["react", "react-dom"], 44 | }; 45 | -------------------------------------------------------------------------------- /src/components/bento-grid/bento-grid.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "../../styles/globals.css"; 3 | import { cn } from "../../lib/index"; 4 | import { BentoGridProps, BentoItem } from "../../types"; 5 | 6 | export const BentoGrid = ({ 7 | items, 8 | gridCols, 9 | rowHeight = 100, 10 | classNames, 11 | }: BentoGridProps): React.ReactNode => { 12 | return ( 13 |
23 | {items.map((item: BentoItem) => ( 24 |
38 | {item.element} 39 |
40 | ))} 41 |
42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-bento", 3 | "version": "1.0.8", 4 | "main": "dist/index.cjs.js", 5 | "module": "dist/index.esm.js", 6 | "types": "dist/types/index.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/anbrela/react-bento" 10 | }, 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "rollup -c && npx tsc --declaration --declarationDir dist/types --outDir dist", 16 | "lint": "eslint src/**/*.ts{,x}", 17 | "prepare": "husky install" 18 | }, 19 | "dependencies": { 20 | "clsx": "^2.1.1", 21 | "react": "^17.0.2", 22 | "react-dom": "^17.0.2", 23 | "tailwind-merge": "^2.3.0" 24 | }, 25 | "devDependencies": { 26 | "@rollup/plugin-commonjs": "^21.0.1", 27 | "@rollup/plugin-node-resolve": "^13.0.6", 28 | "@rollup/plugin-typescript": "^8.3.0", 29 | "@types/node": "^16.18.101", 30 | "@types/react": "^17.0.80", 31 | "@types/react-dom": "^17.0.25", 32 | "@typescript-eslint/eslint-plugin": "^4.33.0", 33 | "@typescript-eslint/parser": "^4.33.0", 34 | "autoprefixer": "^10.3.7", 35 | "eslint": "^7.32.0", 36 | "eslint-plugin-import": "^2.22.1", 37 | "eslint-plugin-jsx-a11y": "^6.4.1", 38 | "eslint-plugin-react": "^7.24.0", 39 | "eslint-plugin-react-hooks": "^4.2.0", 40 | "eslint-plugin-react-refresh": "^0.3.4", 41 | "husky": "^7.0.4", 42 | "lint-staged": "^11.2.6", 43 | "postcss": "^8.3.11", 44 | "rollup": "^2.58.0", 45 | "rollup-plugin-peer-deps-external": "^2.2.4", 46 | "rollup-plugin-postcss": "^4.0.0", 47 | "tailwindcss": "^2.2.19", 48 | "typescript": "^4.9.5" 49 | }, 50 | "peerDependencies": { 51 | "react": "^17.0.2", 52 | "react-dom": "^17.0.2" 53 | }, 54 | "lint-staged": { 55 | "*.ts": [ 56 | "eslint --fix", 57 | "git add" 58 | ] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![React bento](public/react_bento.png) 2 | 3 | `react-bento` is a component library for creating dynamic and flexible layouts inspired by Bento box design. It allows you to organize items in a grid with support for custom dimensions, colors, and more. 4 | 5 | # Real example 6 | 7 | ![Example](public/example.png) 8 | 9 | You can see the real example [here](https://www.pablonaveira.dev) 10 | 11 | # Getting started 12 | 13 | Install the library using npm or yarn: 14 | 15 | ```bash 16 | npm install react-bento 17 | ``` 18 | 19 | or 20 | 21 | ```bash 22 | yarn add react-bento 23 | ``` 24 | 25 | ## Usage 26 | 27 | Here is an example of how to use `react-bento`: 28 | 29 | ### Import the Library 30 | 31 | ```javascript 32 | import { BentoGrid } from "react-bento"; 33 | ``` 34 | 35 | ### Define Your Items 36 | 37 | ```javascript 38 | import React from "react"; 39 | 40 | const bentoItems = [ 41 | { 42 | id: 3, 43 | title: "Item 3", 44 | color: "bg-state-yellow", 45 | element: ( 46 |
47 |

48 | In 2015 I founded a theatre company that is still running. 49 |

50 |

51 | In 2017 I created an Escape Room which is still running. 52 |

53 |

54 | I love the responsibility of new projects. 55 |

56 | 61 |
62 | ), 63 | width: 1, 64 | height: 2, 65 | }, 66 | { 67 | id: 4, 68 | color: "bg-state-green", 69 | title: "Item 4", 70 | element: ( 71 | 79 |
  • Code reviews ensuring good practices.
  • 80 |
  • 81 | Mentoring and onboarding of new frontend profiles. 82 |
  • 83 |
  • CI / CD with Github Actions.
  • 84 |
  • Releases preparation.
  • 85 |
  • New projects approach.
  • 86 |
  • 2 week sprints in Agile methodology.
  • 87 | 88 | } 89 | /> 90 | ), 91 | width: 2, 92 | height: 1, 93 | }, 94 | { 95 | id: 5, 96 | title: "Item 5", 97 | element: ( 98 |
    99 | My best virtue is the day-to-day dealings. A fool in the team makes all 100 | flows better. 101 |
    102 | ), 103 | width: 1, 104 | height: 1, 105 | }, 106 | ]; 107 | ``` 108 | 109 | ### Render the Bento Grid 110 | 111 | ```javascript 112 | const MyBentoGrid = () => { 113 | return ( 114 | 123 | ); 124 | }; 125 | 126 | export default MyBentoGrid; 127 | ``` 128 | 129 | ## Types 130 | 131 | The following types are used in `react-bento`: 132 | 133 | ```typescript 134 | import React from "react"; 135 | 136 | export type BentoItem = { 137 | id: number; 138 | title: string; 139 | element: React.ReactNode; 140 | width: number; 141 | color?: string; 142 | height: number; 143 | }; 144 | 145 | export type BentoItems = BentoItem[]; 146 | 147 | export type ClassNames = { 148 | container?: string; 149 | elementContainer?: string; 150 | }; 151 | 152 | export type BentoGridProps = { 153 | items: BentoItems; 154 | gridCols?: number; 155 | rowHeight?: number; 156 | classNames: ClassNames; 157 | }; 158 | ``` 159 | 160 | ## License 161 | 162 | This project is licensed under the MIT License. 163 | --------------------------------------------------------------------------------