ComponentPorchlight CSS

Chart shell

Accessible chart container for metric headers, legends, plot slots, loading/empty/error states, and table fallback content.

51 components9 patterns46 stable5 experimental

Command

Search Porchlight

Chart shell

.pl-c-chart is a dependency-free chart frame, not a charting engine. It gives apps a consistent shell for SVG, Canvas, server-rendered images, metric headers, legends, loading states, empty states, errors, captions, and table fallback content.

Semantic HTML

<section
  class="pl-c-chart"
  aria-labelledby="pipeline-title"
  aria-describedby="pipeline-desc"
>
  <header class="pl-c-chart__header">
    <div>
      <h2 class="pl-c-chart__title" id="pipeline-title">Pipeline throughput</h2>
      <p class="pl-c-chart__description" id="pipeline-desc">
        Completed workflow items by day.
      </p>
    </div>
    <div class="pl-c-chart__metrics" aria-label="Summary metrics">
      <div class="pl-c-chart__metric">
        <span class="pl-c-chart__metric-label">Completed</span>
        <strong class="pl-c-chart__metric-value">1,284</strong>
        <span class="pl-c-chart__metric-delta" data-direction="up">+8.2%</span>
      </div>
    </div>
  </header>

  <div
    class="pl-c-chart__plot"
    role="img"
    aria-label="Line chart of completed items"
  >
    <svg viewBox="0 0 640 260" aria-hidden="true" focusable="false">
      <!-- App-owned chart drawing. -->
    </svg>
  </div>

  <ul class="pl-c-chart__legend" aria-label="Series">
    <li class="pl-c-chart__legend-item">
      <span
        class="pl-c-chart__swatch"
        style="--pl-c-chart-series-color: var(--pl-color-accent);"
      ></span>
      Completed
    </li>
  </ul>

  <p class="pl-c-chart__caption">Data refreshed 2 minutes ago.</p>
  <div class="pl-c-chart__table" hidden>
    <table class="pl-c-table">
      ...
    </table>
  </div>
</section>

States

<section class="pl-c-chart" data-state="loading" aria-busy="true">
  <div class="pl-c-chart__plot">
    <div class="pl-c-chart__overlay">
      <div class="pl-c-chart__state">
        <p class="pl-c-chart__state-title">Loading chart</p>
        <p>Fetching the latest run history.</p>
      </div>
    </div>
  </div>
</section>

<section class="pl-c-chart" data-state="empty">...</section>
<section class="pl-c-chart" data-state="error" role="alert">...</section>

data-state="loading", "empty", or "error" may be placed on .pl-c-chart or .pl-c-chart__plot. Loading animation respects prefers-reduced-motion.

Class contract

Selector Role
.pl-c-chart Chart region shell and container query root.
.pl-c-chart__header Title, description, and metric strip.
.pl-c-chart__metrics, .pl-c-chart__metric Summary KPIs above or beside the plot.
.pl-c-chart__plot Slot for app-owned SVG, Canvas, image, or custom chart markup.
.pl-c-chart__overlay, .pl-c-chart__state Centered loading, empty, or error message.
.pl-c-chart__legend Accessible series legend.
.pl-c-chart__swatch Legend color swatch; set --pl-c-chart-series-color per item.
.pl-c-chart__table Optional table fallback or source data slot.

Accessibility responsibilities

Charts need a text alternative that matches the business question. Use aria-labelledby and aria-describedby for the chart region, and give the plot role="img" with a useful label when the visual itself carries meaning. Keep a table fallback or source-data link available for complex charts. If chart data updates live, use aria-busy during fetches and announce meaningful changes in an app-owned live region.

SSR, hypermedia, and frameworks

The shell accepts ordinary HTML. SSR can emit a static SVG plus fallback table. Hypermedia updates can replace only .pl-c-chart__plot, .pl-c-chart__metrics, or the fallback table. Component frameworks can render Canvas or SVG inside the plot slot without Porchlight depending on that framework.

Preview

See the chart shell preview.