Layout
Dashboard grid
A draggable, resizable dashboard canvas on gridstack — you own the layout data, 4ui owns the interaction.
Install
pnpm add gridstackgridstack is an optional peer: only apps that render a grid pay for it. The component dynamic-imports it in the browser, so SSR needs no special handling.
Use
import { DashboardGrid, DashboardGridItem } from '@chanrg/4ui/grid';let layout = $state([ { id: 'kpi', x: 0, y: 0, w: 4, h: 3 }, { id: 'trend', x: 4, y: 0, w: 8, h: 5 }]);<DashboardGrid bind:layout editable onlayoutchange={save}> {#each layout as item (item.id)} <DashboardGridItem id={item.id} x={item.x} y={item.y} w={item.w} h={item.h}> <KpiCard {...cards[item.id]} /> </DashboardGridItem> {/each}</DashboardGrid>Behavior
The layout array is bindable and updates as widgets are dragged or resized — persist it wherever you like via onlayoutchange. Set editable={false} for read-only views. Below 900px the grid squeezes to two columns, below 540px to one; squeezed positions are a projection and never overwrite your saved layout. Pass snapPresets={makePresets(12)} to snap resizes to a rhythmic size table.
Try it
The dashboard example runs the real thing — flip “Arrange” and drag widgets around. The homepage hero is the same component.