@richardmcquiston01/dashboard-widgets-toolkit
| Install | |
|---|---|
npm install @richardmcquiston01/dashboard-widgets-toolkit |
|
| Latest Version: | 0.34.0 |
| Vue: | 3 |
| License: | Apache-2.0 |
| Last Updated: | Oct 21, 2026 |
| Links: | GitHub · npm |
Dashboard Widgets Toolkit
- Author: Richard McQuiston
- Website: https://richardmcquiston.com/
- Demo: https://dashboard-widgets-toolkit-demo.vercel.app/
Table of Contents
| Overview | Getting Started | Widget Kinds | More Information | Buy Me a Coffee | License | Copyright |
Overview
@richardmcquiston01/dashboard-widgets-toolkit helps you build dashboards out of widgets. A widget is one card on the dashboard, such as a number, a meter, a table, or a chart. The toolkit works with any framework and includes React components that draw the widgets.
It gives you:
- Typed widget definitions and data payloads. A payload is the data one widget shows.
- A layout that each viewer can change. They can reorder (by buttons, or by dragging with the
draggableprop), hide, and minimize widgets. - React renderers, including accessible charts drawn as Scalable Vector Graphics (SVG), each with a "View as table" twin.
- Controls for viewers, all saved in the layout: an edit mode, pages of widgets, and an Options dialog for each widget's title, width, view and options. A viewer can also duplicate a widget into a clone with its own settings.
- Dashboard-level filters (a date range, a store, a segment) chosen once in a filter bar and passed to every provider, with option-aware cache keys and reloads only for the widgets that use a changed filter.
- Locks that keep chosen widgets in place, a detail view with search, sort and paging, and CSS-variable theming with a
WidgetThemewrapper, contrast and color-vision checks, and presets. - Export: CSV for tables, bar lists, charts and the detail view, SVG and PNG download for charts (
exportFormats), and a print stylesheet. - Freshness: an "Updated 2 minutes ago" line and a refresh button on each card (
freshness,onRefresh), and a failed refresh keeps the last good data with a badge. - Storage helpers (an adapter contract and a
useStoredLayouthook) so you can keep layouts in localStorage, a database or a server.
You bring your own data. The package never fetches or stores anything. You register a provider for each widget, such as a database query, a web request, or a computed value. You also save each viewer's layout wherever you like. Payloads are plain JavaScript Object Notation (JSON), so a server can resolve widgets and a browser can check and draw them.
The package has five parts:
| Import path | What it is |
|---|---|
@richardmcquiston01/dashboard-widgets-toolkit (or /core) |
Runtime-neutral core (Node, Bun, browsers): definitions, payload types, validators, resolveWidgets, layout, formatting. No DOM, no network, no storage. |
@richardmcquiston01/dashboard-widgets-toolkit/builder |
Headless Widget Builder: describe a provider (defineSource), then create and edit a widget definition as JSON with functions that never return an invalid one. |
@richardmcquiston01/dashboard-widgets-toolkit/react |
React (18+) renderers: WidgetCard, one renderer per kind, WidgetGrid, a layout-aware Dashboard, and accessible inline-SVG charts with a "View as table" twin. |
@richardmcquiston01/dashboard-widgets-toolkit/vue |
Vue (3.3+) renderers over the same core and class names: WidgetCard, ResolvedWidgetCard, one renderer per kind, an SVG chart with a "View as table" twin, a layout-aware Dashboard with pages, and useWidgets / useStoredLayout. |
@richardmcquiston01/dashboard-widgets-toolkit/styles.css |
Optional stylesheet. Components are unstyled by default and carry stable dwt-* class names. |
Getting Started
The Getting Started guide has the full walkthrough and more than a dozen examples. The short version is below.
Prerequisites
- Node.js 18 or newer, or Bun 1.3 or newer (or any modern browser bundler)
- React 18 or newer, only if you use
/react - Vue 3.3 or newer, only if you use
/vue - TypeScript is optional. Type declarations are included.
Installation
bun add @richardmcquiston01/dashboard-widgets-toolkit
# or
npm install @richardmcquiston01/dashboard-widgets-toolkit
Usage
Define your widgets, write a provider for each one, then resolve them. A failing provider never breaks the dashboard. That widget comes back with an error message and the others still load.
import {
defineWidget,
resolveWidgets,
type WidgetContext,
type WidgetProviders,
} from '@richardmcquiston01/dashboard-widgets-toolkit';
interface ShopContext extends WidgetContext {
shopId: string;
}
const widgets = [
defineWidget({ key: 'revenue', title: 'Revenue', kind: 'KPI', sortOrder: 10 }),
];
const providers: WidgetProviders<ShopContext> = {
revenue: async ({ shopId }) => {
const { current, previous } = await loadRevenue(shopId); // your code
return {
kind: 'KPI',
value: current,
previous,
format: 'currency',
label: 'Revenue',
};
},
};
const resolved = await resolveWidgets(widgets, providers, {
shopId: 'shop-1',
roles: ['owner'], // widgets limited to other roles are skipped
});
To show the result in React, pass the resolved widgets to the Dashboard component:
import { Dashboard } from '@richardmcquiston01/dashboard-widgets-toolkit/react';
import '@richardmcquiston01/dashboard-widgets-toolkit/styles.css'; // optional
<Dashboard widgets={resolved} />;
Without onLayoutChange, the dashboard is read-only. The guide shows how to let viewers move, hide, and minimize widgets and how to save their layout.
Examples
The Getting Started guide covers these, and more:
- Layout functions on their own
- Styling with Tailwind (or any classes)
- Detail view
- Declared options and the Options dialog
- Alternate views, including views your provider supplies, and clones
- Locked widgets and edit mode
- Pages of widgets
- Storing the layout
- Theming
Widget Kinds
| Kind | Payload fields | Typical use |
|---|---|---|
TEXT |
value: string, label |
A count or status as text |
KPI |
value: number, previous?: number | null, format, currency?, label, hint?, higherIsBetter? |
Stat tile with a change vs previous period |
GAUGE |
value, max, label |
A meter (unread of total, quota used) |
TABLE |
columns: {label, numeric?, type?, formatter?}[], rows: {text, href?, value?}[][], footer? |
Small data tables |
BAR_LIST |
items: {label, value, display?}[], total? |
Ratings breakdown, purchases by country |
ALERT_LIST |
items: {title, href?, thumbnailUrl?, valueLabel, detail?}[], total, emptyText |
Low stock, stale listings, expiring soon |
GRAPH |
series: {name, points: {label, value}[]}[], chartType: 'bar' | 'line', valueFormat, currency?, xLabel? |
Revenue by month, views per day |
KPI stands for Key Performance Indicator.
format and valueFormat are 'number' | 'currency' | 'percent'. Money is in major units (12.5 is $12.50). Percents are fractions (0.25 is 25%). Any widget may return an empty state instead: { empty: true, text: 'No orders synced yet.' }.
A TABLE cell's optional value (a string or number) is what the card's table controls and the detail view sort and search on. Use it when text is made for reading, such as a timestamp behind "3 days ago", a rating behind stars, or an amount behind "$1,234.00". The tableControls setting on the widget definition turns the controls on.
More Information
- Getting Started guide: installation, usage, and every example
- Roadmap: what has shipped and what is planned
- Changelog: what changed in each release
- Contributing notes: scripts, conventions, and how to release
- Design notes for each feature, with what is built and what is still planned:
Buy Me a Coffee
If this app, code, or repository has helped you or someone you know, please consider donating. I appreciate any help to offset the costs of development and/or AI Credits.
Donate via Stripe, or scan:
License
Apache 2
Copyright
(c)2026 Richard McQuiston. All rights reserved.
Related Packages
A high-quality, advanced Vue 3 speedometer/gauge chart component with multiple g...
Circular gauge component for Vue.js with customizable colors, animations, and th...
Comprehensive icon library for the Sprout Design System, available as React and...
TypeScript/JS lib for dashboard layout and creation, responsive, mobile support,...
TypeScript/JS lib for dashboard layout and creation, responsive, mobile support,...
Version History
| Version | Released | License |
|---|---|---|
| 0.34.0 | Apache-2.0 | |
| 0.33.0 | Apache-2.0 | |
| 0.32.0 | Apache-2.0 | |
| 0.31.0 | Apache-2.0 | |
| 0.30.0 | Apache-2.0 | |
| 0.29.0 | Apache-2.0 | |
| 0.28.0 | Apache-2.0 | |
| 0.27.0 | Apache-2.0 | |
| 0.26.0 | Apache-2.0 | |
| 0.25.0 | Apache-2.0 | |
| 0.24.0 | Apache-2.0 | |
| 0.23.0 | Apache-2.0 | |
| 0.22.0 | Apache-2.0 | |
| 0.20.0 | Apache-2.0 | |
| 0.19.0 | Apache-2.0 | |
| 0.18.0 | Apache-2.0 | |
| 0.17.0 | Apache-2.0 | |
| 0.16.0 | Apache-2.0 | |
| 0.15.0 | Apache-2.0 | |
| 0.14.0 | Apache-2.0 | |
| 0.13.0 | Apache-2.0 | |
| 0.12.0 | Apache-2.0 | |
| 0.11.2 | Apache-2.0 | |
| 0.11.1 | Apache-2.0 | |
| 0.11.0 | Apache-2.0 | |
| 0.10.0 | Apache-2.0 | |
| 0.9.0 | Apache-2.0 | |
| 0.8.0 | Apache-2.0 | |
| 0.7.0 | Apache-2.0 | |
| 0.6.0 | Apache-2.0 |
Showing the latest 30 of 35. See every release on npm