PhoenixKitHelloWorld.Web.HelloWidget (PhoenixKitHelloWorld v0.2.1)

Copy Markdown View Source

The reference dashboard widget — a live example of every capability in the phoenix_kit_dashboards widget API, in one component. If you're writing a widget for your own module, copy this file and the definition in PhoenixKitHelloWorld.phoenix_kit_widgets/0.

What a widget IS

A plain Phoenix.LiveComponent. The dashboards host renders it as:

<.live_component
  module={HelloWidget}
  id={instance_id}
  settings={%{"greeting" => "Hi", ...}}  # this instance's saved settings
  view={"card" | "counter" | "contract"} # the selected render variant
  size={%{w: 4, h: 2}}                   # the instance's current span (cells)
  scope={@phoenix_kit_current_scope}     # the viewer — personalize with it
/>

It runs inside the host LiveView's process (LiveComponents have no process of their own). When the catalog entry declares a refresh_interval, the host re-send_update/2s the component on that cadence — update/2 runs again and any state kept in the socket persists between ticks (the counter view uses exactly that).

The three views (each declares its own min_size in the catalog entry)

  • "card" — a greeting card built from the settings (the simple case).
  • "counter" — proves live refresh: counts host ticks and shows the last tick time, stepping by the "step" setting.
  • "contract" — the living documentation: prints the exact assigns this component received, so you can SEE the contract on a real dashboard.

Notes for widget authors

  • No DB guard here on purpose: this widget renders purely from its assigns. The dashboards Registry already gates visibility on module_key (module enabled + permission), so an in-component enabled?/0 guard is only needed when the widget queries data of its own (see the projects widgets).
  • Render defensively: every setting read uses a default, size/view/scope may be nil, and a widget must NEVER crash the host dashboard.
  • A single-row instance (size.h < 2) renders compact — tighter paddings, smaller text — so the minimum box fits without scrollbars.