Skip to content

Support D3-backed chart types and a Vega-Lite widget for custom visualizations #12

Description

@arsalann

What problem are you trying to solve?

DAC's chart widget is currently limited to the chart types Recharts can render cleanly (line, bar, area, pie, scatter, combo, funnel, sankey) plus a handful of bespoke React components. There is no way to express visualizations that go beyond this fixed list without forking the frontend.

  • Common analytics visualizations such as treemaps, sunbursts, chord diagrams, force-directed networks, radial charts, and choropleth maps are not available.
  • Power users who need a custom encoding (e.g. a scatter with size + color + faceting, a layered chart, or a domain-specific viz) have no declarative escape hatch in YAML or TSX.
  • Recharts is built on D3, but D3's full capability is not exposed — users cannot opt into richer chart types without writing a new widget component upstream.
  • TSX dashboards run server-side via Goja, so authors cannot drop in client-side D3 code either.
  • The only current workaround is to fork DAC and add a new chart component, which creates maintenance and upgrade drift.

Proposed solution

Add D3 capability to DAC in two complementary phases, both fully declarative and version-controllable.

Phase 1 — Expand the chart widget with D3-backed chart types

Add new chart: values that render via D3 primitives (d3-hierarchy, d3-force, d3-geo, d3-chord) while keeping the existing {columns, rows} data contract. No new widget type, no user JS — just more chart types behind the same YAML/TSX surface.

- name: Revenue by Product Hierarchy
  type: chart
  chart: treemap
  sql: |
    SELECT category, product, revenue
    FROM product_revenue
  group: [category, product]
  value: revenue

- name: Account Relationships
  type: chart
  chart: force
  sql: |
    SELECT source_account, target_account, weight
    FROM account_links
  source: source_account
  target: target_account
  weight: weight

- name: Revenue by Region
  type: chart
  chart: geo
  sql: |
    SELECT country_code, revenue
    FROM revenue_by_country
  region: country_code
  value: revenue

Initial chart types to support:

  • treemap
  • sunburst
  • chord
  • force (network / node-link)
  • radial (radial bar / polar)
  • geo (choropleth)

Phase 2 — New vega widget type for custom visualizations

Add a 7th widget type that accepts a Vega-Lite spec as JSON/YAML. DAC injects the query result as data.values before render. This unlocks the long tail of custom visualizations without exposing arbitrary client-side JS.

- name: Deal Size vs Close Rate
  type: vega
  sql: |
    SELECT segment, deal_size, close_rate, deal_count
    FROM segment_performance
  spec:
    mark: circle
    encoding:
      x: { field: deal_size, type: quantitative }
      y: { field: close_rate, type: quantitative }
      size: { field: deal_count, type: quantitative }
      color: { field: segment, type: nominal }

Support should include:

  • new D3-backed chart types behind the existing chart widget (Phase 1)
  • a new vega widget type wrapping Vega-Lite via react-vega (Phase 2)
  • per-chart-type field mappings (group, value, source, target, region, etc.) in YAML and TSX
  • correct rendering in legends, tooltips, and the existing template system
  • documentation and skill updates in .claude/skills/create-dashboard/SKILL.md

Alternatives considered

  • Stick with Recharts only — keeps the surface small but blocks every visualization Recharts cannot express, and users have already hit these limits.
  • Allow custom widget bundles (.widget.tsx compiled at dac build) — most flexible, but introduces a client-side JS execution model, sandboxing/CSP questions, viewer trust, and a build pipeline. Better deferred until Phases 1 and 2 prove insufficient.
  • Recommend embedding external dashboards via iframe — breaks the single-binary, dashboard-as-code model and removes version control of the visualization.
  • Fork DAC locally to add chart types — works, but creates maintenance and upgrade drift, and every team ends up reinventing the same set of charts.

Additional context

D3 is the de facto foundation for advanced data visualization on the web, and Vega-Lite is the established declarative grammar built on top of it (used by Streamlit, Apache Superset, Observable, and others). Both options preserve DAC's core principles: declarative authoring, version-controlled dashboards, no user JS in the browser at render time, and a single embedded binary.

Phase 1 is low risk and immediately unlocks the most-requested chart types; Phase 2 gives power users a declarative escape hatch for everything else. Phase 1 alone is likely to resolve the majority of "we need D3" requests, with Phase 2 as a follow-up if demand persists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions