GitHubGitHub
← All widgets
Layout / widget

Dashboard grid

A draggable, resizable dashboard canvas: gravity packing, responsive column squeezing, optional size snapping, and a serializable layout you own.

EditableStaticResponsiveSnapping
A
B
C
import { DashboardGrid, DashboardGridItem } from '@chanrg/4ui/grid';<DashboardGrid bind:layout editable>  {#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>

Installation

pnpm add @chanrg/4ui

Import the stylesheet once, at the root of your app:

import '@chanrg/4ui/styles.css';

Usage

import { DashboardGrid } from '@chanrg/4ui';import { DashboardGrid, DashboardGridItem } from '@chanrg/4ui/grid';<DashboardGrid bind:layout editable>  {#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>

API reference

Props

PropTypeDefaultDescription
layoutGridItemLayout[] ($bindable)[]Widget positions; updates as the user drags and resizes.
columnsnumber12Grid columns.
cellHeightnumber54Row height in px, margins added on top.
editablebooleantrueWhen false the board is frozen for viewing.
breakpointsGridBreakpoint[]1 col < 540px, 2 < 900pxResponsive column squeezing; [] disables it.
snapPresetsGridPreset[]Snap resizes to the nearest preset from makePresets().
onlayoutchange(layout) => voidFires after a drag/resize settles — persist it where you like.

CSS variables

VariableDescription
--4ui-surfacePrimary component surface.
--4ui-textPrimary foreground color.
--4ui-borderDefault control and panel border.

Accessibility

  • Layout edits are pointer-driven; keep an alternative path (form or API) for keyboard users.
  • Squeezed responsive layouts are a projection and never overwrite the saved layout.

Dependencies

gridstack (optional peer — install alongside)