A responsive tile grid for displaying and selecting from a collection of items. Uses CSS grid with auto-fill columns so tiles flow naturally at any viewport
width. Keyboard navigation moves focus between tiles with arrow keys. Accepts the same field
mapping and snippet patterns as List.
Basic Example
Pass an array of objects. The label and icon fields are displayed in
each tile by default. Bind value to track the selected item.
<script>
import { Grid } from '@rokkit/ui'
const items = [
{ label: 'Dashboard', icon: 'i-glyph:home' },
{ label: 'Reports', icon: 'i-glyph:chart' },
{ label: 'Settings', icon: 'i-glyph:settings' }
]
let selected = $state(null)
</script>
<Grid {items} bind:value={selected} />Tile Size Control
Use minSize to control the minimum tile width. The grid fills available columns
automatically. Use size for the content size variant (sm, md, lg).
<Grid {items} minSize="80px" size="sm" bind:value />Custom Tile Content
Use the itemContent snippet to replace what renders inside each tile. The snippet
receives a ProxyItem — use proxy.label, proxy.icon, and proxy.get('field').
{#snippet itemContent(proxy)}
<div class="flex flex-col items-center gap-1 p-2">
<span class="{proxy.icon} text-2xl text-secondary-z7"></span>
<span class="text-xs font-medium">{proxy.label}</span>
<span class="text-xs text-surface-z5">{proxy.get('count')} items</span>
</div>
{/snippet}
<Grid {items} {itemContent} bind:value />Props
- items: Array of objects
- fields: Remap data keys to component fields
- value (bindable): Currently selected item value
- size: Content size —
sm,md,lg - minSize: Minimum tile width (CSS value, default
120px) - gap: Grid gap (CSS value, default
1rem) - disabled: Disable all tiles
- label: ARIA label for the grid container
- class: Additional CSS classes
Snippets
- itemContent(proxy): Custom content inside each tile button
- [name](proxy): Per-item snippet — set
item.snippet = 'name'
Events
- onselect(value, proxy): Fired when a tile is selected