PhiaUi.Components.ChartShell (phia_ui v0.1.16)

Copy Markdown View Source

Titled card container for charts and data visualisations.

chart_shell/1 wraps any charting library output in a semantic PhiaUI Card, providing consistent header chrome (title, description, period label, action buttons) and a minimum-height content area — all without coupling to a specific charting library.

When to use

Use chart_shell/1 when you want the standard PhiaUI card presentation around a chart but need full control over the chart itself (custom hooks, third-party libraries, canvas elements, SVG, etc.). For a batteries-included experience, use phia_chart/1 which combines chart_shell/1 with the PhiaChart hook automatically.

Anatomy


  card_header                                         
     
   title                       period  | actions  
   description (optional)                         
     

  card_content                                        
   
    chart content area (min-height: 300px)         
   

Basic example — custom Chart.js hook

<.chart_shell
  title="Revenue Over Time"
  description="Monthly recurring revenue"
  period="Last 12 months"
  min_height="350px"
>
  <:actions>
    <.button variant={:outline} size={:sm}>Export CSV</.button>
  </:actions>
  <canvas id="revenue-chart" phx-hook="RevenueChart" class="w-full h-full" />
</.chart_shell>

Example with ECharts (manual hook wiring)

<.chart_shell title="User Growth" period="Last 90 days" min_height="400px">
  <div
    id="growth-chart"
    phx-hook="PhiaChart"
    data-config={Jason.encode!(@chart_config)}
    data-series={Jason.encode!(@chart_series)}
    style="height: 400px"
    class="w-full"
  />
</.chart_shell>

Example with multiple action buttons

<.chart_shell
  title="Conversion Funnel"
  description="Visitors to paying customers"
  period="Q1 2026"
  min_height="300px"
>
  <:actions>
    <.button variant={:ghost} size={:sm}><.icon name="refresh-cw" /></.button>
    <.button variant={:outline} size={:sm}>Download</.button>
  </:actions>
  <canvas id="funnel-chart" phx-hook="FunnelChart" />
</.chart_shell>

Responsive min-height

The min_height attribute accepts any CSS length: "300px", "20rem", "50vh". The container enforces this minimum so that the chart area does not collapse to zero before the JS hook mounts and sizes the canvas.

Library compatibility

chart_shell/1 renders a plain <div> inside its content area. Any charting library that targets a DOM element can be used:

  • ECharts via the PhiaChart hook (built-in)
  • Chart.js via the PhiaChart hook fallback or a custom hook
  • D3.js — mount on the container div ID
  • Vega-Lite — target the inner div
  • SVG charts — render inline SVG directly as inner block

Summary

Functions

Renders a titled card shell around a chart or data visualisation.

Functions

chart_shell(assigns)

Renders a titled card shell around a chart or data visualisation.

The header layout uses a two-column flex row:

  • Left: title + optional description (allows text to truncate on narrow screens)
  • Right: optional period label + optional action buttons (shrink-0, never truncated)

The content area wraps the inner block in a div with min-height applied as an inline style — this prevents the card from collapsing before the chart JS hook initialises.

Example

<.chart_shell
  title="MRR Growth"
  description="Monthly recurring revenue"
  period="Last 12 months"
  min_height="350px"
>
  <:actions>
    <.button variant={:outline} size={:sm}>Export</.button>
  </:actions>
  <canvas id="mrr-chart" phx-hook="PhiaChart" />
</.chart_shell>

Attributes

  • title (:string) (required) - Chart heading rendered in card_title. Always visible — use a clear, metric-focused label: "Revenue Over Time", "Active Users by Region".

  • description (:string) - Supporting text shown below the title in smaller muted text (omitted when nil). Use for metric clarification: "Monthly recurring revenue (USD)", "Unique sessions, excluding bots".

    Defaults to nil.

  • period (:string) - Time-range label displayed in the header to the right of the title block. Typical values: "Last 30 days", "Q1 2026", "YTD". Omitted when nil. This is a plain string; for interactive period selectors use the :actions slot.

    Defaults to nil.

  • min_height (:string) - Minimum CSS height of the chart content area. Prevents the container from collapsing before the JS chart hook has had time to mount and measure. Accepts any CSS length value: "300px", "20rem", "50vh".

    Defaults to "300px".

  • class (:string) - Additional CSS classes for the outer card element. Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the outer card element (e.g. id, data-*).

Slots

  • actions - Optional header action buttons rendered to the right of the period label. Use for download, refresh, period-selector, or settings buttons. Multiple actions are laid out in a horizontal flex row with gap-1 between them.

    <:actions>
      <.button variant={:ghost} size={:sm}><.icon name="refresh-cw" /></.button>
      <.button variant={:outline} size={:sm}>Export</.button>
    </:actions>
  • inner_block (required) - The chart content itself. Render any chart library output here: a <canvas> for Chart.js, a <div> for ECharts or D3, or inline SVG. The content area has min-height applied via inline style.