@alphinex/dashboard-kit
v1.0.8
Published
Draggable/resizable widget grid for building saved dashboard layouts. Reuses @dnd-kit (ADR-0011) for pointer/touch drag; resize and keyboard repositioning are hand-rolled. See documentation/PRODUCT-RESEARCH-MASTER-PLAN.md §10 (Sprint 19).
Readme
@alphinex/dashboard-kit
Draggable/resizable widget grid for building saved dashboard layouts.
Usage
import { DashboardGrid, type DashboardWidgetLayout } from "@alphinex/dashboard-kit";
import { StatCard } from "@alphinex/business";
import { useState } from "react";
function Dashboard() {
const [layout, setLayout] = useState<DashboardWidgetLayout[]>([
{ id: "revenue", x: 0, y: 0, w: 3, h: 2 },
{ id: "orders", x: 3, y: 0, w: 3, h: 2 },
]);
return (
<DashboardGrid
widgets={layout.map((widget) => ({
...widget,
title: widget.id,
content: <StatCard label={widget.id} value="1,204" delta={4.2} />,
}))}
onWidgetsChange={(next) => {
setLayout(next);
// Persist however the app wants — a backend call, localStorage, etc. This package
// has no storage opinion of its own.
void saveDashboardLayout(next);
}}
/>
);
}Widget content is a plain ReactNode — drop in any existing component
(@alphinex/business's StatCard for a KPI tile, a @alphinex/charts chart, ...) rather than
this package reimplementing widget content types.
Interaction model
- Pointer/touch drag uses
@dnd-kit(already adopted for@alphinex/kanban, see ADR-0011) for its collision/pointer-capture handling. - Keyboard: focusing a widget's drag handle and pressing the arrow keys moves it one grid
cell at a time — a hand-rolled alternative to dragging, the same split
@alphinex/kanbanuses (a library for the pointer state machine, hand-rolled code for the bounded arrow-key path). - Resize (pointer drag on the corner handle, or arrow keys while it's focused) is entirely hand-rolled — pixel-delta-to-grid-cell math, not a separate dependency.
Known limitations
- No collision detection between widgets — this is a free-form grid, not a bin-packing algorithm. Overlapping widgets are a layout the caller chose, not an error this package corrects.
- Layout persistence is entirely the consumer's responsibility via
onWidgetsChange.
