Floating cards dashboard
Dashboard of floating cards with KPI charts.
Usage
import { FloatingDashboard } from '@/components/blocks/dashboard-02'
<FloatingDashboard />
// Fill a parent that has a height instead of the viewport
<FloatingDashboard height="100%" />
// Your own workspace, navigation and data
<FloatingDashboard
workspaces={[{ id: 'acme', name: 'Acme Logistics', detail: 'Operations' }]}
user={{ name: 'Sam Lee', email: 'sam@acme.dev', avatar: '/avatars/sam.jpg' }}
title="Shipments overview"
primaryAction={{ label: 'New shipment', onClick: () => open() }}
kpis={kpis}
series={series}
seriesLabels={{ foot: 'Parcels', vehicle: 'Pallets' }}
routes={lanes}
activity={shipments}
activeId={pathname}
onNavigate={(id) => navigate(id)}
onRangeChange={(range) => refetch(range)}
/>
Install
pnpm dlx shadcn@latest add @pastaui-pro/dashboard-02npx shadcn@latest add @pastaui-pro/dashboard-02yarn dlx shadcn@latest add @pastaui-pro/dashboard-02bunx --bun shadcn@latest add @pastaui-pro/dashboard-02Source
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| workspaces | FloatingWorkspace[] | = Three workspaces | Workspaces in the switcher ({ id, name, detail? }). The first is selected unless defaultWorkspaceId is set. |
| defaultWorkspaceId | string | = First workspace | Workspace selected on first render. |
| onWorkspaceChange | (id: string) => void | = — | Called when another workspace is chosen. |
| nav | FloatingNavSection[] | = Operations and Crew groups | Sidebar groups ({ id, label?, items }). Each item has an id, label, icon, optional href and optional count. |
| footerNav | FloatingNavItem[] | = Settings | Links pinned to the bottom of the sidebar. |
| activeId | string | = — | Controlled id of the active nav item. Pair with onNavigate. |
| defaultActiveId | string | = 'overview' | Active nav item on first render when uncontrolled. |
| onNavigate | (id: string) => void | = — | Called when a nav link is chosen. The drawer closes itself. |
| user | FloatingUser | = Halvard Brannock | Signed-in user ({ name, email, avatar? }) for the account menu. Initials are shown without an avatar. |
| notifications | FloatingNotification[] | = Three notifications | Items in the notifications menu ({ id, title, time, unread? }). Unread items light the dot on the bell. |
| title | string | = 'Sailings overview' | Page title at the top of the main card. |
| description | ReactNode | = One line | Supporting line under the title. |
| primaryAction | { label: string; onClick?: () => void } | = { label: 'Schedule sailing' } | The blue button next to the date range menu. |
| defaultRange | '7d' | '30d' | '90d' | = '30d' | Date range on first render. It drives the KPI cards and the chart. |
| onRangeChange | (range: '7d' | '30d' | '90d') => void | = — | Called when a range is picked from the date range menu or a KPI card’s period menu. |
| kpis | FloatingKpi[] | = Four KPIs | KPI cards: id, label, format (number or percent), decimals, higherIsBetter, values (a { value, previous } pair for each range), today (text before 'today', such as '+1,204'), series (sparkline points { date, value } for each range), pointLabel (word after a value in the chart tooltip) and trend ('good', 'bad' or 'neutral' for green, red or blue; worked out from the change and higherIsBetter when omitted). Percent deltas show in points. |
| series | FloatingSeriesPoint[] | = 180 days of data | Daily points ({ date: YYYY-MM-DD, foot, vehicle }) stacked in the chart. 7 and 30 days show days, 90 days shows weeks. |
| seriesLabels | { foot: string; vehicle: string } | = { foot: 'Walk-on', vehicle: 'With vehicle' } | Names of the two series in the legend and tooltip. |
| routes | FloatingRoute[] | = Four routes | Rows in the route load list ({ id, from, to, load, sailings }). |
| activity | FloatingSailing[] | = Twelve sailings | Table rows: id, vessel, departs, from, to, captain, passengers, capacity and status (arrived, boarding, scheduled, delayed or cancelled). The search input filters them. |
| searchPlaceholder | string | = 'Search sailings, vessels, crew' | Placeholder of the search input. |
| onSearch | (query: string) => void | = — | Called when Enter is pressed in the search input. |
| onUpgrade | () => void | = — | Called from the upgrade prompt at the bottom of the sidebar. |
| shortcuts | 'auto' | 'within' | false | = 'auto' | Where Ctrl or Cmd + K (focus search) and Ctrl or Cmd + B (sidebar) work. 'within' handles them only while focus or the pointer is inside the dashboard, 'auto' also handles them anywhere when the dashboard fills the page, and false turns them off. |
| defaultCollapsed | boolean | = Below 1024px | Start with the sidebar folded to icons. Left unset, it folds when the dashboard is narrower than 1024px. |
| height | number | string | = '100dvh' | Height of the shell; the panes scroll inside it. Numbers are pixels and strings take any CSS length: '100%' fills a parent that has a height, such as the area under your own header, and 800 gives a fixed frame. |
| className | string | = — | Additional classes for the root. Use height rather than an h-* class. |
| style | CSSProperties | = — | Inline styles, handy for overriding the --pp-* theme variables. |