MetricCardGrid

A CSS grid layout with @dnd-kit drag-and-drop reordering. Renders metric cards in a paginated grid with sortable slots, delegating card rendering to a renderCard render prop.

Drag & Drop Grid

Grab any card and drag to reorder. The grid uses @dnd-kit with pointer and keyboard sensors, constrained within the grid container.

Layout Presets

The grid's column count, row height, gap, and max rows are controlled via the layout prop. Toggle between presets to see how the grid adapts.

Columns: 6Row Height: 120pxGap: 15pxMax Rows: 3Pages: 1

Empty Slot Rendering

When fewer cards exist than available slots, the renderEmptySlot callback renders placeholders for remaining positions.

Usage

JSX
import { MetricCardGrid, MetricCard } from '@so.boss/gloss-ui';
import type { GridCardData, GridLayout } from '@so.boss/gloss-ui';

const layout: GridLayout = {
  columns: 6,
  rowHeight: 120,
  gap: 15,
  maxRows: 3,
  currentPage: 0,
  totalPages: 1,
};

<MetricCardGrid
  cards={dashboardCards}
  cardOrder={cardOrder}
  layout={layout}
  onReorder={(newOrder) => setCardOrder(newOrder)}
  onPageChange={(page) => setCurrentPage(page)}
  renderCard={(card) => <MetricCard {...card.props} />}
  renderEmptySlot={(index) => <EmptyCardPlaceholder />}
/>

Props Reference

MetricCardGrid

PropTypeDefaultDescription
cardsGridCardData[]—Array of card data objects with id, colSpan, and content
cardOrderstring[]—Ordered array of card IDs controlling display order
layoutGridLayout—Grid layout config: columns, rowHeight, gap, maxRows, currentPage, totalPages
renderCard(card: GridCardData) => ReactNode—Render prop for card content. Receives full card data.
renderEmptySlot(index: number) => ReactNodeundefinedRender prop for empty grid slots when cards < slots
onReorder(newOrder: string[]) => void—Callback after drag-and-drop reorder with new card ID order
onPageChange(page: number) => void—Page change callback for pagination

GridLayout

FieldTypeDescription
columnsnumberNumber of grid columns
rowHeightnumberHeight of each grid row in pixels
gapnumberGap between grid cells in pixels
maxRowsnumberMaximum visible rows per page
currentPagenumberZero-indexed current page
totalPagesnumberTotal number of pages for pagination dots

GridCardData

FieldTypeDescription
idstringUnique card identifier
colSpan1 | 2Column span (1 for standard, 2 for wide cards)
contentReactNodeCard content passed to renderCard