Skip to content

Latest commit

 

History

History
229 lines (187 loc) · 5.91 KB

File metadata and controls

229 lines (187 loc) · 5.91 KB
title Plugin Dashboard

import { InteractiveDemo } from '@/app/components/InteractiveDemo'; import { PluginLoader } from '@/app/components/PluginLoader';

Dashboard layouts and metric widgets for creating beautiful dashboards with KPIs, charts, and statistics.

Installation

npm install @object-ui/plugin-dashboard

<PluginLoader plugins={['dashboard']}>

Interactive Examples

Features

  • Dashboard Layouts - Responsive grid-based layouts
  • Metric Cards - Display KPIs with trends and icons
  • Widget System - Modular widget architecture
  • Customizable - Full Tailwind CSS styling support

Schema API

Dashboard

{
  type: 'dashboard',
  widgets: Widget[],
  columns?: number,               // Grid columns (default: 3)
  gap?: number,                   // Gap between widgets
  className?: string
}

Metric Card

{
  type: 'metric-card',
  title: string,
  value: string | number,
  icon?: string,                  // Lucide icon name
  trend?: 'up' | 'down' | 'neutral',
  trendValue?: string,
  description?: string,
  className?: string
}

Usage

Auto-registration (Side-effect Import)

import '@object-ui/plugin-dashboard';

Manual Registration

import { dashboardComponents } from '@object-ui/plugin-dashboard';
import { ComponentRegistry } from '@object-ui/core';

Object.entries(dashboardComponents).forEach(([type, component]) => {
  ComponentRegistry.register(type, component);
});

Examples

Dashboard with Multiple Metrics

{
  "type": "dashboard",
  "columns": 4,
  "gap": 6,
  "widgets": [
    {
      "type": "metric-card",
      "title": "Total Sales",
      "value": "$123,456",
      "icon": "shopping-cart",
      "trend": "up",
      "trendValue": "+15%"
    },
    {
      "type": "metric-card",
      "title": "New Customers",
      "value": "856",
      "icon": "user-plus",
      "trend": "up",
      "trendValue": "+22%"
    },
    {
      "type": "metric-card",
      "title": "Bounce Rate",
      "value": "2.4%",
      "icon": "trending-down",
      "trend": "down",
      "trendValue": "-5%"
    },
    {
      "type": "metric-card",
      "title": "Avg. Order Value",
      "value": "$144.20",
      "icon": "dollar-sign",
      "trend": "up",
      "trendValue": "+8%"
    }
  ]
}

Dashboard with Charts

{
  "type": "dashboard",
  "widgets": [
    {
      "type": "metric-card",
      "title": "Total Revenue",
      "value": "$123,456"
    },
    {
      "type": "card",
      "title": "Sales Trend",
      "body": {
        "type": "line-chart",
        "data": [],
        "height": 300
      }
    }
  ]
}

Dashboard-level filters

A dashboard can declare top-level filters — a date range plus any number of select / text filters — whose values drive every bound widget at once. Filter values live as dashboard-level variables; each widget declares which of its own fields a filter binds to via filterBindings, and the dashboard merges the active values into each bound widget's inline query (AND-combined with the widget's own filter).

{
  "type": "dashboard",
  "dateRange": { "field": "created_at", "defaultRange": "last_30_days", "allowCustomRange": true },
  "globalFilters": [
    { "name": "region", "field": "region", "label": "Region", "type": "select", "options": ["EMEA", "APAC", "AMER"] }
  ],
  "widgets": [
    { "id": "w1", "type": "bar", "object": "invoices", "aggregate": "count" },
    {
      "id": "w2", "type": "line", "object": "accounts", "aggregate": "count",
      "filterBindings": { "dateRange": "signed_at", "region": "sales_region" }
    },
    {
      "id": "w3", "type": "metric", "object": "invoices", "aggregate": "count",
      "filterBindings": { "region": false }
    }
  ]
}

Binding rules, in precedence order:

  1. filterBindings[name] as a string — apply the filter to that field.
  2. filterBindings[name]: false — opt this widget out.
  3. Legacy targetWidgets on the filter — when set, only listed widget ids get the default binding (an explicit filterBindings entry still wins).
  4. Otherwise the filter applies to its own field (the built-in date range defaults to dateRange.field ?? 'created_at').

Date presets stay symbolic (date-macro tokens such as {30_days_ago}) until query time. Dataset-bound widgets receive the merged filter through the dataset query's runtimeFilter. Static-data widgets (inline data arrays) have no query to scope and are not filtered. Filter values are also readable in widget expressions as page.<name>.

For a step-by-step tutorial — filter types, optionsFrom dynamic options, page.* expression usage, and known limitations with workarounds — see the Dashboard-Level Filters guide. The schema catalog ships runnable variants under plugin-dashboard/filtered-dashboard* (dynamic options, filter types, dataset widgets, targetWidgets, date presets).

TypeScript Support

import type { DashboardSchema, MetricCardSchema } from '@object-ui/plugin-dashboard';

const dashboard: DashboardSchema = {
  type: 'dashboard',
  columns: 3,
  widgets: [...]
};

Type-aware list/table widget cells

type: 'table' widgets bound to an objectName infer the renderer for each cell from the object's field type — Badges for select, expanded display name for lookup/user/owner, formatted currency/percent/date for numeric fields, and so on. Lookup columns are auto-expanded server-side via $expand, so you don't see raw FK ids. See @object-ui/plugin-dashboard README for the full mapping table and an example.

License

MIT