Component Porchlight CSS

Chart shell

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

52 components 51 stable 1 experimental

Command

Search Porchlight

Chart shell

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

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

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

States

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

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

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

Class contract

SelectorRole
.c-chartChart region shell and container query root.
.c-chart__headerTitle, description, and metric strip.
.c-chart__metrics, .c-chart__metricSummary KPIs above or beside the plot.
.c-chart__plotSlot for app-owned SVG, Canvas, image, or custom chart markup.
.c-chart__overlay, .c-chart__stateCentered loading, empty, or error message.
.c-chart__legendAccessible series legend.
.c-chart__swatchLegend color swatch; set --c-chart-series-color per item.
.c-chart__tableOptional 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 .c-chart__plot, .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.