{"id":29569201,"url":"https://github.com/seungwoo321/tailwind-grid-layout","last_synced_at":"2026-02-18T20:12:46.747Z","repository":{"id":299507679,"uuid":"1003264363","full_name":"Seungwoo321/tailwind-grid-layout","owner":"Seungwoo321","description":"A Tailwind CSS compatible grid layout system - Alternative to react-grid-layout","archived":false,"fork":false,"pushed_at":"2025-07-11T01:58:12.000Z","size":1458,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-18T12:58:45.609Z","etag":null,"topics":["react-grid-layout","tailwind-grid-layout","tailwindcss"],"latest_commit_sha":null,"homepage":"https://tailwind-grid-layout-omega.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Seungwoo321.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-16T22:07:27.000Z","updated_at":"2025-06-24T00:42:00.000Z","dependencies_parsed_at":"2025-06-16T23:21:36.260Z","dependency_job_id":"4d6d002b-b904-49ef-8832-5b2ede13fdfb","html_url":"https://github.com/Seungwoo321/tailwind-grid-layout","commit_stats":null,"previous_names":["seungwoo321/tailwind-grid-layout"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/Seungwoo321/tailwind-grid-layout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seungwoo321%2Ftailwind-grid-layout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seungwoo321%2Ftailwind-grid-layout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seungwoo321%2Ftailwind-grid-layout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seungwoo321%2Ftailwind-grid-layout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Seungwoo321","download_url":"https://codeload.github.com/Seungwoo321/tailwind-grid-layout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seungwoo321%2Ftailwind-grid-layout/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265871435,"owners_count":23842028,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react-grid-layout","tailwind-grid-layout","tailwindcss"],"created_at":"2025-07-19T01:39:03.703Z","updated_at":"2026-02-18T20:12:41.716Z","avatar_url":"https://github.com/Seungwoo321.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tailwind Grid Layout\n\nA modern, lightweight grid layout system for React built with Tailwind CSS. A powerful alternative to react-grid-layout with full feature parity and a smaller bundle size.\n\n[![npm version](https://img.shields.io/npm/v/tailwind-grid-layout.svg)](https://www.npmjs.com/package/tailwind-grid-layout)\n[![license](https://img.shields.io/npm/l/tailwind-grid-layout.svg)](https://github.com/Seungwoo321/tailwind-grid-layout/blob/main/LICENSE)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/tailwind-grid-layout)](https://bundlephobia.com/package/tailwind-grid-layout)\n\n\u003e Version 0.1.0 - First stable release\n\n\u003e English | [한국어](./README.ko.md)\n\n## Features\n\n- 🎯 **Full Feature Parity** with react-grid-layout\n- 🪶 **Lightweight** - Smaller bundle size using Tailwind CSS\n- 🎨 **Tailwind Native** - Built with Tailwind CSS utilities\n- 📱 **Responsive** - Works on all screen sizes\n- 📱 **Mobile Touch** - Full touch device optimization with enhanced gesture support\n  - Improved touch point accuracy\n  - Long press gesture support\n  - Prevent scroll-drag conflicts\n  - Multi-touch prevention for stability\n- 🔧 **TypeScript** - Full TypeScript support\n- ⚡ **Performance** - Optimized rendering and animations\n- 🧪 **Well Tested** - 100% test coverage\n\n## Installation\n\n```bash\nnpm install tailwind-grid-layout\n# or\nyarn add tailwind-grid-layout\n# or\npnpm add tailwind-grid-layout\n```\n\n### Prerequisites\n\n- React 19.1.0\n- Tailwind CSS 4.1.8+ (v4 only - CSS-first configuration)\n- Node.js 20.0.0+\n- pnpm 10.11.0+\n\n## Tailwind CSS v4 Setup\n\nThis library requires Tailwind CSS v4 with its new CSS-first configuration approach. No JavaScript configuration file is needed.\n\n```css\n/* In your main CSS file */\n@import \"tailwindcss\";\n\n/* Optional: Add custom theme configuration */\n@theme {\n  --color-grid-placeholder: oklch(0.7 0.15 210);\n  --color-grid-handle: oklch(0.3 0.05 210);\n}\n```\n\n## Quick Start\n\n```tsx\nimport { GridContainer } from 'tailwind-grid-layout'\n\nconst items = [\n  { id: '1', x: 0, y: 0, w: 2, h: 2 },\n  { id: '2', x: 2, y: 0, w: 2, h: 2 },\n  { id: '3', x: 0, y: 2, w: 4, h: 2 }\n]\n\nfunction App() {\n  return (\n    \u003cGridContainer\n      items={items}\n      cols={12}\n      rowHeight={60}\n      onLayoutChange={(newLayout) =\u003e console.log(newLayout)}\n    \u003e\n      {(item) =\u003e (\n        \u003cdiv className=\"bg-blue-500 text-white p-4 rounded\"\u003e\n          Item {item.id}\n        \u003c/div\u003e\n      )}\n    \u003c/GridContainer\u003e\n  )\n}\n```\n\n## Testing\n\n```bash\n# Run tests\npnpm test\n\n# Watch mode\npnpm test:watch\n\n# Coverage report\npnpm test:coverage\n```\n\n### Test Coverage\n\nThis library maintains 100% test coverage:\n\n- ✅ Lines: 100%\n- ✅ Statements: 100%\n- ✅ Functions: 100%\n- ✅ Branches: 100%\n\n## Props Reference\n\n### GridContainer Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| **items** | `GridItem[]` | required | Array of grid items with position and size |\n| **children** | `(item: GridItem) =\u003e ReactNode` | required | Render function for grid items |\n| **cols** | `number` | `12` | Number of columns in the grid |\n| **rowHeight** | `number` | `60` | Height of each row in pixels |\n| **gap** | `number` | `16` | Gap between grid items in pixels |\n| **margin** | `[number, number]` | `[gap, gap]` | Margin between items [horizontal, vertical] |\n| **containerPadding** | `[number, number]` | `[16, 16]` | Padding inside the grid container [horizontal, vertical] |\n| **maxRows** | `number` | - | Maximum number of rows |\n| **isDraggable** | `boolean` | `true` | Enable/disable dragging |\n| **isResizable** | `boolean` | `true` | Enable/disable resizing |\n| **preventCollision** | `boolean` | `false` | Prevent items from colliding |\n| **allowOverlap** | `boolean` | `false` | Allow items to overlap |\n| **isBounded** | `boolean` | `true` | Keep items within container bounds |\n| **compactType** | `'vertical' \\| 'horizontal' \\| null` | `'vertical'` | Compaction type |\n| **resizeHandles** | `Array\u003c's' \\| 'w' \\| 'e' \\| 'n' \\| 'sw' \\| 'nw' \\| 'se' \\| 'ne'\u003e` | `['se']` | Resize handle positions |\n| **draggableCancel** | `string` | - | CSS selector for elements that should not trigger drag |\n| **draggableHandle** | `string` | - | CSS selector for drag handle |\n| **autoSize** | `boolean` | `true` | Container height adjusts to fit all items |\n| **verticalCompact** | `boolean` | `true` | DEPRECATED: Use compactType |\n| **transformScale** | `number` | `1` | Scale factor for drag/resize when zoomed |\n| **droppingItem** | `Partial\u003cGridItem\u003e` | - | Preview item while dragging from outside |\n| **className** | `string` | - | Additional CSS classes for the container |\n| **style** | `React.CSSProperties` | - | Inline styles for the container |\n| **onLayoutChange** | `(layout: GridItem[]) =\u003e void` | - | Callback when layout changes |\n| **onDragStart** | `(layout, oldItem, newItem, placeholder, e, element) =\u003e void` | - | Drag start callback |\n| **onDrag** | `(layout, oldItem, newItem, placeholder, e, element) =\u003e void` | - | Drag callback |\n| **onDragStop** | `(layout, oldItem, newItem, placeholder, e, element) =\u003e void` | - | Drag stop callback |\n| **onResizeStart** | `(layout, oldItem, newItem, placeholder, e, element) =\u003e void` | - | Resize start callback |\n| **onResize** | `(layout, oldItem, newItem, placeholder, e, element) =\u003e void` | - | Resize callback |\n| **onResizeStop** | `(layout, oldItem, newItem, placeholder, e, element) =\u003e void` | - | Resize stop callback |\n\n### GridItem Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| **id** | `string` | ✓ | Unique identifier for the item |\n| **x** | `number` | ✓ | X position in grid units |\n| **y** | `number` | ✓ | Y position in grid units |\n| **w** | `number` | ✓ | Width in grid units |\n| **h** | `number` | ✓ | Height in grid units |\n| **minW** | `number` | - | Minimum width |\n| **minH** | `number` | - | Minimum height |\n| **maxW** | `number` | - | Maximum width |\n| **maxH** | `number` | - | Maximum height |\n| **isDraggable** | `boolean` | - | Override container's isDraggable |\n| **isResizable** | `boolean` | - | Override container's isResizable |\n| **static** | `boolean` | - | Make item static (unmovable/unresizable) |\n| **className** | `string` | - | Additional CSS classes for the item |\n\n### ResponsiveGridContainer Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| **layouts** | `BreakpointLayouts` | required | Object with layouts for each breakpoint |\n| **breakpoints** | `{ [breakpoint: string]: number }` | `{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }` | Minimum widths for each breakpoint |\n| **cols** | `{ [breakpoint: string]: number }` | `{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }` | Number of columns for each breakpoint |\n| **onLayoutChange** | `(layout: GridItem[], layouts: BreakpointLayouts) =\u003e void` | - | Called when layout changes with current layout and all layouts |\n| **onBreakpointChange** | `(newBreakpoint: string, cols: number) =\u003e void` | - | Called when breakpoint changes |\n| **width** | `number` | - | Container width (provided by WidthProvider) |\n| ...GridContainerProps | - | - | All other GridContainer props except items, cols, onLayoutChange |\n\n## Comparison with react-grid-layout\n\n| Feature | react-grid-layout | tailwind-grid-layout | Notes |\n|---------|-------------------|---------------------|--------|\n| **Core Features** |\n| Drag \u0026 Drop | ✅ | ✅ | Full support |\n| Resize | ✅ | ✅ | 8-direction resize |\n| Collision Detection | ✅ | ✅ | 50% overlap rule |\n| Auto-compaction | ✅ | ✅ | Vertical, horizontal, or none |\n| Static Items | ✅ | ✅ | Full support |\n| Bounded Movement | ✅ | ✅ | Keep items in bounds |\n| **Layout Options** |\n| Responsive Breakpoints | ✅ | ✅ | Real-time responsive layouts with ResizeObserver |\n| Persist Layout | ✅ | ✅ | Via onLayoutChange |\n| Min/Max Dimensions | ✅ | ✅ | Full support |\n| Prevent Collision | ✅ | ✅ | Full support |\n| Allow Overlap | ✅ | ✅ | Full support |\n| **Events** |\n| Layout Change | ✅ | ✅ | Full support |\n| Drag Events | ✅ | ✅ | Start, move, stop |\n| Resize Events | ✅ | ✅ | Start, resize, stop |\n| Drop from Outside | ✅ | ✅ | Full support with DroppableGridContainer |\n| **Styling** |\n| CSS-in-JS | ✅ | ❌ | Uses Tailwind |\n| Custom Classes | ✅ | ✅ | Full support |\n| Animations | ✅ | ✅ | Tailwind transitions |\n| **Performance** |\n| Bundle Size | ~30KB | ~22KB (gzip) | Smaller bundle |\n| Dependencies | React only | React + Tailwind | |\n| Tree-shaking | ✅ | ✅ | Full support |\n\n## Advanced Examples\n\n### With Custom Drag Handle\n\n```tsx\n\u003cGridContainer items={items}\u003e\n  {(item) =\u003e (\n    \u003cdiv className=\"bg-white rounded-lg shadow p-4\"\u003e\n      \u003cdiv className=\"cursor-move p-2 bg-gray-100 rounded\" data-drag-handle\u003e\n        \u003cGripIcon className=\"w-4 h-4\" /\u003e\n      \u003c/div\u003e\n      \u003cdiv className=\"p-4\"\u003e\n        Content for {item.id}\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )}\n\u003c/GridContainer\u003e\n```\n\n### Static Items\n\n```tsx\nconst items = [\n  { id: '1', x: 0, y: 0, w: 4, h: 2, static: true }, // This item cannot be moved\n  { id: '2', x: 4, y: 0, w: 4, h: 2 },\n]\n```\n\n### Responsive Breakpoints\n\n```tsx\nimport { ResponsiveGridContainer, WidthProvider } from 'tailwind-grid-layout'\n\n// Define layouts for each breakpoint\nconst layouts = {\n  lg: [\n    { id: '1', x: 0, y: 0, w: 6, h: 2 },\n    { id: '2', x: 6, y: 0, w: 6, h: 2 },\n    { id: '3', x: 0, y: 2, w: 4, h: 2 },\n    { id: '4', x: 4, y: 2, w: 8, h: 2 }\n  ],\n  md: [\n    { id: '1', x: 0, y: 0, w: 10, h: 2 },\n    { id: '2', x: 0, y: 2, w: 10, h: 2 },\n    { id: '3', x: 0, y: 4, w: 5, h: 2 },\n    { id: '4', x: 5, y: 4, w: 5, h: 2 }\n  ],\n  sm: [\n    { id: '1', x: 0, y: 0, w: 6, h: 2 },\n    { id: '2', x: 0, y: 2, w: 6, h: 2 },\n    { id: '3', x: 0, y: 4, w: 6, h: 2 },\n    { id: '4', x: 0, y: 6, w: 6, h: 2 }\n  ],\n  xs: [\n    { id: '1', x: 0, y: 0, w: 4, h: 2 },\n    { id: '2', x: 0, y: 2, w: 4, h: 2 },\n    { id: '3', x: 0, y: 4, w: 4, h: 2 },\n    { id: '4', x: 0, y: 6, w: 4, h: 2 }\n  ],\n  xxs: [\n    { id: '1', x: 0, y: 0, w: 2, h: 2 },\n    { id: '2', x: 0, y: 2, w: 2, h: 2 },\n    { id: '3', x: 0, y: 4, w: 2, h: 2 },\n    { id: '4', x: 0, y: 6, w: 2, h: 2 }\n  ]\n}\n\n// Option 1: Manual width tracking\nfunction ResponsiveExample() {\n  const [currentBreakpoint, setCurrentBreakpoint] = useState('lg')\n  \n  return (\n    \u003cResponsiveGridContainer\n      layouts={layouts}\n      onBreakpointChange={(breakpoint) =\u003e {\n        setCurrentBreakpoint(breakpoint)\n        console.log(`Switched to ${breakpoint} breakpoint`)\n      }}\n      onLayoutChange={(layout, allLayouts) =\u003e {\n        // Save layouts to state or backend\n        console.log('Layout changed:', allLayouts)\n      }}\n    \u003e\n      {(item) =\u003e (\n        \u003cdiv className=\"bg-blue-500 text-white p-4 rounded\"\u003e\n          Item {item.id}\n        \u003c/div\u003e\n      )}\n    \u003c/ResponsiveGridContainer\u003e\n  )\n}\n\n// Option 2: Using WidthProvider for automatic width detection\nconst ResponsiveGridWithWidth = WidthProvider(ResponsiveGridContainer)\n\nfunction App() {\n  return (\n    \u003cResponsiveGridWithWidth\n      layouts={layouts}\n      // Custom breakpoints (optional)\n      breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}\n      // Custom column configuration (optional)\n      cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}\n    \u003e\n      {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n    \u003c/ResponsiveGridWithWidth\u003e\n  )\n}\n```\n\n### Drag and Drop from Outside\n\n```tsx\nimport { DroppableGridContainer } from 'tailwind-grid-layout'\n\n\u003cDroppableGridContainer\n  items={items}\n  onDrop={(newItem) =\u003e setItems([...items, newItem])}\n  droppingItem={{ w: 2, h: 2 }} // Default size for dropped items\n\u003e\n  {(item) =\u003e \u003cdiv\u003eDropped Item {item.id}\u003c/div\u003e}\n\u003c/DroppableGridContainer\u003e\n```\n\n### Custom Resize Handles\n\n```tsx\n\u003cGridContainer\n  items={items}\n  resizeHandles={['se', 'sw', 'ne', 'nw']} // Enable corner handles only\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/GridContainer\u003e\n```\n\n### Prevent Collision\n\n```tsx\n\u003cGridContainer\n  items={items}\n  preventCollision={true} // Items cannot overlap\n  allowOverlap={false}\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/GridContainer\u003e\n```\n\n### Bounded Grid with Max Rows\n\n```tsx\n\u003cGridContainer\n  items={items}\n  isBounded={true}\n  maxRows={10}\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/GridContainer\u003e\n```\n\n### AutoSize Container\n\n```tsx\n\u003cGridContainer\n  items={items}\n  autoSize={true} // Container height adjusts automatically\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/GridContainer\u003e\n\n// With fixed height\n\u003cdiv style={{ height: 400, overflow: 'auto' }}\u003e\n  \u003cGridContainer\n    items={items}\n    autoSize={false}\n    style={{ height: '100%' }}\n  \u003e\n    {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n  \u003c/GridContainer\u003e\n\u003c/div\u003e\n```\n\n### Real-time Responsive Updates\n\nThe responsive grid automatically updates layouts when the window is resized, with debounced handling for optimal performance:\n\n```tsx\nimport { ResponsiveGridContainer } from 'tailwind-grid-layout'\n\nfunction DashboardExample() {\n  const [layouts, setLayouts] = useState({\n    lg: dashboardLayoutLg,\n    md: dashboardLayoutMd,\n    sm: dashboardLayoutSm,\n    xs: dashboardLayoutXs,\n    xxs: dashboardLayoutXxs\n  })\n  const [currentBreakpoint, setCurrentBreakpoint] = useState('')\n  const [currentCols, setCurrentCols] = useState(12)\n\n  return (\n    \u003c\u003e\n      {/* Visual breakpoint indicator */}\n      \u003cdiv className=\"mb-4 p-2 bg-green-100 rounded\"\u003e\n        Current: {currentBreakpoint} ({currentCols} columns)\n      \u003c/div\u003e\n      \n      \u003cResponsiveGridContainer\n        layouts={layouts}\n        onLayoutChange={(layout, allLayouts) =\u003e {\n          setLayouts(allLayouts)\n        }}\n        onBreakpointChange={(breakpoint, cols) =\u003e {\n          setCurrentBreakpoint(breakpoint)\n          setCurrentCols(cols)\n        }}\n        rowHeight={100}\n        gap={16}\n        containerPadding={[16, 16]}\n      \u003e\n        {(item) =\u003e (\n          \u003cCard key={item.id}\u003e\n            \u003cCardHeader\u003e\n              \u003cCardTitle\u003e{item.title}\u003c/CardTitle\u003e\n            \u003c/CardHeader\u003e\n            \u003cCardContent\u003e\n              {item.content}\n            \u003c/CardContent\u003e\n          \u003c/Card\u003e\n        )}\n      \u003c/ResponsiveGridContainer\u003e\n    \u003c/\u003e\n  )\n}\n```\n\n### Dropping Item Preview\n\n```tsx\n\u003cDroppableGridContainer\n  items={items}\n  droppingItem={{ w: 4, h: 2 }} // Shows preview while dragging\n  onDrop={(newItem) =\u003e setItems([...items, newItem])}\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/DroppableGridContainer\u003e\n```\n\n## Layout Utilities\n\n### generateLayouts\n\nGenerate identical layouts for all breakpoints from a single layout definition.\n\n```tsx\nimport { generateLayouts } from 'tailwind-grid-layout'\n\nconst items = [\n  { id: '1', x: 0, y: 0, w: 4, h: 2 },\n  { id: '2', x: 4, y: 0, w: 4, h: 2 }\n]\n\n// Creates layouts for lg, md, sm, xs, xxs with identical positioning\nconst layouts = generateLayouts(items)\n```\n\n### generateResponsiveLayouts\n\nAutomatically adjust layouts to fit different column counts per breakpoint.\n\n```tsx\nimport { generateResponsiveLayouts } from 'tailwind-grid-layout'\n\nconst items = [\n  { id: '1', x: 0, y: 0, w: 12, h: 2 },\n  { id: '2', x: 0, y: 2, w: 6, h: 2 }\n]\n\n// Adjusts item widths and positions to fit column constraints\nconst layouts = generateResponsiveLayouts(items, {\n  lg: 12,\n  md: 10, \n  sm: 6,\n  xs: 4,\n  xxs: 2\n})\n```\n\n### WidthProvider HOC\n\nAutomatically provides container width to ResponsiveGridContainer using ResizeObserver for optimal performance.\n\n```tsx\nimport { ResponsiveGridContainer, WidthProvider } from 'tailwind-grid-layout'\n\nconst ResponsiveGridWithWidth = WidthProvider(ResponsiveGridContainer)\n\n// Basic usage\n\u003cResponsiveGridWithWidth\n  layouts={layouts}\n  rowHeight={100}\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/ResponsiveGridWithWidth\u003e\n\n// With measureBeforeMount to prevent layout shift on initial render\n\u003cResponsiveGridWithWidth\n  layouts={layouts}\n  measureBeforeMount={true}\n  rowHeight={100}\n\u003e\n  {(item) =\u003e \u003cdiv\u003eItem {item.id}\u003c/div\u003e}\n\u003c/ResponsiveGridWithWidth\u003e\n\n// WidthProvider features:\n// - Uses ResizeObserver for efficient width detection\n// - Falls back to window resize events if ResizeObserver is unavailable\n// - Handles SSR correctly with measureBeforeMount option\n// - Debounced resize handling (150ms) for better performance\n```\n\n\n## Styling Guide\n\n### Using with Tailwind CSS\n\nThe library is built to work seamlessly with Tailwind CSS:\n\n```tsx\n\u003cGridContainer items={items} className=\"bg-gray-50 rounded-lg\"\u003e\n  {(item) =\u003e (\n    \u003cdiv className=\"bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow\"\u003e\n      \u003cdiv className=\"p-4\"\u003e\n        \u003ch3 className=\"text-lg font-semibold\"\u003eItem {item.id}\u003c/h3\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  )}\n\u003c/GridContainer\u003e\n```\n\n### Custom Placeholders\n\nThe drag and resize placeholders can be styled via CSS:\n\n```css\n/* Drag placeholder */\n.tailwind-grid-layout .drag-placeholder {\n  background: rgba(59, 130, 246, 0.15);\n  border: 2px dashed rgb(59, 130, 246);\n}\n\n/* Resize placeholder */\n.tailwind-grid-layout .resize-placeholder {\n  background: rgba(59, 130, 246, 0.1);\n  border: 2px dashed rgb(59, 130, 246);\n}\n```\n\n## Performance Optimizations\n\n- **Hardware Acceleration**: Uses CSS transforms with will-change\n- **Gesture Debouncing**: Optimized touch event handling\n  - Touch events are debounced at 16ms (60fps)\n  - Minimizes unnecessary re-renders\n- **Memory Management**: Proper cleanup of event listeners\n- **Bundle Splitting**: Tree-shakable exports\n- **ResizeObserver**: Efficient container width detection\n- **Animation Control**: Transitions disabled during interactions\n\n### Touch Event Handling\n\nOptimized touch event handling for best performance on mobile devices:\n\n- **Passive Listeners**: Uses passive touch events for improved scroll performance\n- **Gesture Recognition**: Accurately distinguishes between tap, long press, and drag gestures\n- **Momentum Scrolling**: Natural momentum effects after touch release\n- **Pointer Events API**: Unified handling for touch, mouse, and pen input\n\n## Browser Support\n\n- Chrome (latest)\n- Firefox (latest)\n- Safari (latest)\n- Edge (latest)\n- **Mobile Safari** (iOS 12+)\n- **Chrome Mobile** (Android 7+)\n- **ResizeObserver support** required for optimal performance\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n## License\n\nMIT © [Seungwoo, Lee](./LICENSE)\n\n## Acknowledgments\n\nThis library is inspired by [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) and aims to provide a modern, Tailwind-first alternative.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseungwoo321%2Ftailwind-grid-layout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseungwoo321%2Ftailwind-grid-layout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseungwoo321%2Ftailwind-grid-layout/lists"}