bruin-data / bruin-data/dac

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

Open
#12 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
730
Forks
33
Avg merge
11h 47m
Merged PRs (30d)
18

Description

## 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.

```yaml
- 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](https://vega.github.io/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.

```yaml
- 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.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the existing chart widget and its `{columns, rows}` contract across the YAML and TSX surfaces. Review `.claude/skills/create-dashboard/SKILL.md` and the existing chart rendering, legend, tooltip, and template behavior before evaluating the D3-backed types and the proposed Vega-Lite widget. Done means both phases, field mappings, rendering behavior, and documentation updates are supported without arbitrary user JavaScript.

Written by the indexing model from the issue text.

Assessment

Tech stack
d3, react, typescript, yaml
Domain
data-visualization, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.