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 mosaic

Requires: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities

Demo

Revenue
$48.5k
+12%
Active users
3,204+5.2%
Revenue over timeLast 8 months
Growth+24%

Composition

<Mosaic>
<MosaicTile />
</Mosaic>

Props

NameTypeDefaultDescription
layoutMosaicTileLayout[]-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.
colsnumber12Number of grid columns.
rowHeightnumber160Base row height in pixels.
gapnumber16Gap between tiles in pixels.
minColSpannumber2Minimum column span a tile can shrink to.
minRowSpannumber1Minimum row span a tile can shrink to.
maxColSpannumbercolsMaximum column span. Defaults to the full grid width.
maxRowSpannumber4Maximum 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.

KeyFunction
tabMoves focus to a tile's drag handle, following normal document order.
spacePicks up the focused tile to start a keyboard-driven move; press again to drop it at the current cell.
enterPicks up the focused tile to start a keyboard-driven move; press again to drop it at the current cell.
up arrowWhile picked up, moves the tile toward the row above.
down arrowWhile picked up, moves the tile toward the row below.
left arrowWhile picked up, moves the tile toward the previous column.
right arrowWhile picked up, moves the tile toward the next column.
escapeCancels an in-progress keyboard move, returning the tile to its original cell.