Mosaic
A drag-and-drop grid for metric tiles. Users reposition tiles by dragging and resize them by dragging edge handles. Tile content adapts to its current size via a render prop.
Installation
npx dafink-ui add mosaicRequires: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities
Demo
Composition
Props
| Name | Type | Default | Description |
|---|---|---|---|
| layout | MosaicTileLayout[] | - | Required. Array of tile layout entries. Each entry has id, col, row, colSpan, and rowSpan. col and row are 1-based grid positions. |
| onLayoutChange | (layout: MosaicTileLayout[]) => void | - | Required. Called when tiles are reordered or resized. |
| cols | number | 12 | Number of grid columns. |
| rowHeight | number | 160 | Base row height in pixels. |
| gap | number | 16 | Gap between tiles in pixels. |
| minColSpan | number | 2 | Minimum column span a tile can shrink to. |
| minRowSpan | number | 1 | Minimum row span a tile can shrink to. |
| maxColSpan | number | cols | Maximum column span. Defaults to the full grid width. |
| maxRowSpan | number | 4 | Maximum row span. |
Accessibility
Mosaic doesn't use roving tabindex. The grid container is role="grid" aria-label="Mosaic", and each tile's repositioning affordance — a small drag-handle div carrying dnd-kit's own role="button", tabIndex=0, and aria-roledescription="draggable" — sits in normal document tab order. Repositioning is fully keyboard-operable via dnd-kit's KeyboardSensor. Resizing by dragging a tile's edge is pointer/touch-only (those handles are aria-hidden), but the same resize is available from the keyboard via the "Resize" corner button, which opens a picker of real, focusable buttons offering the same size choices.
| Key | Function |
|---|---|
| tab | Moves focus to a tile's drag handle, following normal document order. |
| space | Picks up the focused tile to start a keyboard-driven move; press again to drop it at the current cell. |
| enter | Picks up the focused tile to start a keyboard-driven move; press again to drop it at the current cell. |
| up arrow | While picked up, moves the tile toward the row above. |
| down arrow | While picked up, moves the tile toward the row below. |
| left arrow | While picked up, moves the tile toward the previous column. |
| right arrow | While picked up, moves the tile toward the next column. |
| escape | Cancels an in-progress keyboard move, returning the tile to its original cell. |