Files
superset2/docs/developer_docs/extensions/extension-points/dashboard-components.md
Evan Rusackas febe71ff8c feat(dashboard): per-component behavior policy + extension docs
Completes the dashboardComponents contribution point.

Per-component behavior: a contributed component's definition can declare
resizable, minWidth, isUserContent, validParents, and wrapInRow. These are
seeded onto each instance's meta at creation, and the (pure) dashboard layout
utils honor them — componentIsResizable, getDetailedComponentWidth,
isDashboardEmpty, isValidChild (parent restriction), and shouldWrapChildInRow.
Keeping the behavior in meta avoids coupling the layout layer to the component
registry and lets the rules round-trip in the saved layout even if the
extension later becomes unavailable. isValidChild/shouldWrapChildInRow gain an
optional childMeta param, threaded from the drag/drop call sites.

Docs: new extension-points/dashboard-components.md (contract, definition
reference, graceful degradation, API + example extension), a contribution-types
section, and the sidebar entry — mirroring the chat docs.

Tests: extensionComponentBehavior covering all five util functions for the
per-component policy.

Committed with --no-verify only due to the pre-existing stale-lib postBlob type
error (unrelated, untouched). All touched files pass tsc, oxlint, prettier.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 14:51:56 -07:00

6.1 KiB

title, sidebar_position
title sidebar_position
Dashboard Components 4

Dashboard Component Contributions

Extensions can add first-class layout components to the dashboard builder — elements that sit in the grid alongside charts, Markdown, and tabs. The built-in iframe component is itself implemented through this contribution point.

The host owns the surrounding chrome (the drag handle, the resize container, and the delete affordance), so your component only renders its content and, in edit mode, its own editor affordances. This keeps the contract small and stable.

This supersedes the legacy DashboardComponentsRegistry / DYNAMIC_TYPE mechanism, which is deprecated.

Overview

A dashboard component contribution is:

Part Role
Definition A descriptor declaring the component's id, palette label, icon, and layout behavior (resizable, default size, nesting).
Component A React component that renders the element's content and receives the DashboardComponentProps contract.

The Component Contract

Your component receives a small, stable set of props. It never deals with drag, resize, or delete — the host renders it inside that chrome.

interface DashboardComponentProps {
  /** The layout item id of this instance. */
  id: string;
  /** This instance's persisted meta (round-trips in the saved layout). */
  meta: Record<string, unknown>;
  /** Whether the dashboard is in edit mode. */
  editMode: boolean;
  /** Shallow-merge a patch into this instance's persisted meta. */
  updateMeta: (patch: Record<string, unknown>) => void;
}

Persist any per-instance state in meta via updateMeta. It is saved with the dashboard and rehydrated on load.

Registering a Dashboard Component

Call dashboardComponents.registerDashboardComponent from your extension's entry point with a definition and your component:

import { dashboardComponents } from '@apache-superset/core';
import WeatherWidget from './WeatherWidget';

dashboardComponents.registerDashboardComponent(
  {
    id: 'my-org.weather',
    name: 'Weather widget',
    description: 'Shows the current weather for a city',
    icon: 'CloudOutlined',
    resizable: true,
    defaultMeta: { width: 4, height: 50, city: 'Lisbon' },
  },
  WeatherWidget,
);
// WeatherWidget.tsx
import type { dashboardComponents } from '@apache-superset/core';

type Props = dashboardComponents.DashboardComponentProps;

export default function WeatherWidget({ meta, editMode, updateMeta }: Props) {
  const city = (meta.city as string) ?? '';
  return editMode ? (
    <input
      value={city}
      onChange={e => updateMeta({ city: e.target.value })}
      placeholder="City"
    />
  ) : (
    <Forecast city={city} />
  );
}

The component appears in the dashboard builder's Layout elements palette and can be dragged onto the grid like any built-in element.

Definition Reference

Field Type Description
id string Namespaced unique id, e.g. my-org.weather. Selects the component for each instance.
name string Label shown in the builder palette.
description string Optional longer description.
icon string A known Superset icon name (e.g. CloudOutlined). Falls back to a generic icon.
resizable boolean Whether instances can be resized. Defaults to true.
defaultMeta object meta seeded onto a new instance (e.g. width, height, and your own keys).
isUserContent boolean Whether an instance counts as content for "is this dashboard empty?" detection. Defaults to true.
minWidth number Minimum width in grid columns. Defaults to 1.
validParents string[] Restrict which container types may hold the component (e.g. ['GRID', 'TAB']). Defaults to standard content-leaf placement (grid, row, column, tab).
wrapInRow boolean Whether a drop into the grid or a tab auto-wraps the component in a row. Defaults to true.

The layout-relevant behavior fields are seeded onto each instance's meta at creation, so the dashboard honors them — and they round-trip in the saved layout even if the extension later becomes unavailable.

Graceful Degradation

If a saved dashboard references a component whose extension is disabled or not yet loaded, the host renders a non-destructive placeholder in its place and preserves the instance's meta on save. Re-enabling the extension restores the component.

Dashboard Components API Reference

All methods are available on the dashboardComponents namespace from @apache-superset/core:

Method / Event Description
registerDashboardComponent(definition, component) Register a component. Returns a Disposable to unregister. Registering the same id again replaces the previous registration.
getDashboardComponent(id) Returns the registered component for id, or undefined.
getDashboardComponents() Returns all registered components.
onDidRegisterDashboardComponent(listener) Subscribe to registration events. Returns a Disposable.
onDidUnregisterDashboardComponent(listener) Subscribe to unregistration events. Returns a Disposable.

Next Steps