DashboardGrid
A 12-column widget board for overview screens. Each widget declares a span in twelfths, and the grid measures its OWN width (never the window) to pick a tier: a wide container honors every span, a narrower one reflows widgets to their narrowSpan, and a phone-sized one stacks them full width.
Cells render bare, because a widget arrives with its own surface (a Card, a Chart, a Stats row) and a second frame around it would only double up. A widget's title is its accessible name rather than a header the grid paints: customize mode uses it to name the widget's drag grip and its drop zone.
Locked, it is a plain static grid and no drag machinery is mounted at all; unlocked turns on customize mode, where every cell gains a grip and the board reorders by pointer, keyboard, or screen reader through the kit's own drag-and-drop. The order is a plain array of ids, controlled through order and onOrderChange so the app can persist it, or left to the grid with defaultOrder.
The board takes its widgets through items, the collection prop every other collection-taking component in the kit uses; the original widgets spelling still works as a deprecated alias and warns in development.
Revenue
12
18
15
22
Mon
Tue
Wed
Thu
Signups
Web
82
iOS
64
Slowest endpoints
/api/search
240
/api/feed
180
iOS
Revenue
12
18
15
22
Mon
Tue
Wed
Thu
Signups
Web
82
iOS
64
Slowest endpoints
/api/search
240
/api/feed
180
Android
Revenue
12
18
15
22
Mon
Tue
Wed
Thu
Signups
Web
82
iOS
64
Slowest endpoints
/api/search
240
/api/feed
180
Web
tsx
Default
Customize mode
Controlled order
Narrow spans
Compact
Props
Do & Don’t
The order lives in the consumer's data
Don’t
Don't pass a controlled order and drop the change on the floor: the drop completes and announces, and then the widget snaps back because nothing updated the array.
Do
Signups
Web
64
Revenue
Pro
82
Treat order as the single source of truth and persist every onOrderChange through your own API, so a layout survives a reload on any device.
title names the widget for assistive tech
Don’t
Don't pass a slug, an id, or a placeholder. The board looks identical, and that is the trap: a keyboard or screen-reader user in customize mode is left dragging "widget-2" around with nothing to tell them which tile it is.
Do
Signups
1,204
Revenue
Pro
82
Give every widget the title its own header already shows. Nothing paints it, but customize mode reads it out: the grip announces "Reorder Signups", and moving the widget announces which one moved and what it landed against.
Widgets bring their own surface
Don’t
Don't hand-roll the widget frame out of a styled View. That rebuilds Card at the call site, drifts from the kit's radius and elevation, and is exactly the shim the bare cell exists to avoid.
Do
Signups
1,204
Revenue
Pro
82
Hand each widget a component that already carries a surface. The cell is bare on purpose, so a Card, a Chart, a Stats row, or a BarList lands with exactly one frame around it.