- Prop
nodes- Type
readonly NetworkNode[]- Default
- —
- Requirement
- required
- Description
- —
SankeyChart
React example follows below.
Vue example follows below.
Angular example follows below.
Svelte example follows below.
Solid example follows below.
- surface
- —
- marks
- —
- size
- —
- value
- —
ts
import { useState } from "react";import { SankeyChart } from "@grassroot/charts-react";import { VariantToggle } from "./VariantToggle";const sankeyNodes = [ { id: "organic", label: "Organic", value: 520, group: "Acquisition", color: "var(--accent)", }, { id: "paid", label: "Paid", value: 380, group: "Acquisition", color: "var(--vs-success)", }, { id: "partners", label: "Partners", value: 210, group: "Acquisition", color: "var(--vs-info)", }, { id: "events", label: "Events", value: 140, group: "Acquisition", color: "var(--vs-warning)", }, { id: "referral", label: "Referral", value: 90, group: "Acquisition", color: "var(--vs-neutral-400)", }, { id: "trial", label: "Self-serve trial", value: 620, group: "Evaluation", color: "var(--accent)", }, { id: "sales", label: "Sales qualified", value: 340, group: "Evaluation", color: "var(--vs-success)", }, { id: "nurture", label: "Nurture", value: 180, group: "Evaluation", color: "var(--vs-warning)", }, { id: "unqualified", label: "Unqualified", value: 200, group: "Evaluation", color: "var(--vs-error)", }, { id: "activated", label: "Activated", value: 480, group: "Conversion", color: "var(--vs-success)", }, { id: "contracted", label: "Contracted", value: 220, group: "Conversion", color: "var(--accent)", }, { id: "lost", label: "Lost", value: 440, group: "Conversion", color: "var(--vs-error)", }, { id: "retained", label: "Retained", value: 520, group: "Outcome", color: "var(--vs-success)", }, { id: "expanded", label: "Expanded", value: 105, group: "Outcome", color: "var(--vs-info)", }, { id: "churned", label: "Churned", value: 47, group: "Outcome", color: "var(--vs-error)", }, { id: "dormant", label: "Dormant", value: 28, group: "Outcome", color: "var(--vs-neutral-400)", },];const sankeyLinks = [ { source: "organic", target: "trial", value: 360, color: "var(--accent)", }, { source: "organic", target: "sales", value: 90, color: "var(--accent)", }, { source: "organic", target: "nurture", value: 40, color: "var(--accent)", }, { source: "organic", target: "unqualified", value: 30, color: "var(--accent)", }, { source: "paid", target: "trial", value: 180, color: "var(--vs-success)", }, { source: "paid", target: "sales", value: 140, color: "var(--vs-success)", }, { source: "paid", target: "nurture", value: 30, color: "var(--vs-success)", }, { source: "paid", target: "unqualified", value: 30, color: "var(--vs-success)", }, { source: "partners", target: "trial", value: 50, color: "var(--vs-info)", }, { source: "partners", target: "sales", value: 80, color: "var(--vs-info)", }, { source: "partners", target: "nurture", value: 40, color: "var(--vs-info)", }, { source: "partners", target: "unqualified", value: 40, color: "var(--vs-info)", }, { source: "events", target: "trial", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "sales", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "nurture", value: 50, color: "var(--vs-warning)", }, { source: "events", target: "unqualified", value: 50, color: "var(--vs-warning)", }, { source: "referral", target: "trial", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "sales", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "nurture", value: 20, color: "var(--vs-neutral-400)", }, { source: "referral", target: "unqualified", value: 50, color: "var(--vs-neutral-400)", }, { source: "trial", target: "activated", value: 380, color: "var(--accent)", }, { source: "trial", target: "contracted", value: 40, color: "var(--accent)", }, { source: "trial", target: "lost", value: 200, color: "var(--accent)", }, { source: "sales", target: "activated", value: 70, color: "var(--vs-success)", }, { source: "sales", target: "contracted", value: 160, color: "var(--vs-success)", }, { source: "sales", target: "lost", value: 110, color: "var(--vs-success)", }, { source: "nurture", target: "activated", value: 30, color: "var(--vs-warning)", }, { source: "nurture", target: "contracted", value: 20, color: "var(--vs-warning)", }, { source: "nurture", target: "lost", value: 130, color: "var(--vs-warning)", }, { source: "activated", target: "retained", value: 360, color: "var(--vs-success)", }, { source: "activated", target: "expanded", value: 55, color: "var(--vs-success)", }, { source: "activated", target: "churned", value: 40, color: "var(--vs-success)", }, { source: "activated", target: "dormant", value: 25, color: "var(--vs-success)", }, { source: "contracted", target: "retained", value: 160, color: "var(--accent)", }, { source: "contracted", target: "expanded", value: 50, color: "var(--accent)", }, { source: "contracted", target: "churned", value: 7, color: "var(--accent)", }, { source: "contracted", target: "dormant", value: 3, color: "var(--accent)", },]; export default function SankeyChartDemo() { const [layout, setLayout] = useState<"sankey" | "alluvial">("sankey"); return ( <div> <VariantToggle label="Layout" options={[ { value: "sankey" as const, label: "Sankey" }, { value: "alluvial" as const, label: "Alluvial" }, ]} value={layout} onChange={setLayout} /> <SankeyChart nodes={sankeyNodes} links={sankeyLinks} layout={layout} ariaLabel="Journey of 1,340 prospect sessions from acquisition through evaluation, conversion, and customer outcomes, 2026" /> </div> );}- surface
- —
- marks
- —
- size
- —
- value
- —
ts
<script setup lang="ts">import { ref } from "vue";import { SankeyChart } from "@grassroot/charts-vue";import VariantToggle from "./VariantToggle.vue"; const layout = ref<"sankey" | "alluvial">("sankey");const layouts = [ { value: "sankey", label: "Sankey" }, { value: "alluvial", label: "Alluvial" },];const sankeyNodes = [ { id: "organic", label: "Organic", value: 520, group: "Acquisition", color: "var(--accent)", }, { id: "paid", label: "Paid", value: 380, group: "Acquisition", color: "var(--vs-success)", }, { id: "partners", label: "Partners", value: 210, group: "Acquisition", color: "var(--vs-info)", }, { id: "events", label: "Events", value: 140, group: "Acquisition", color: "var(--vs-warning)", }, { id: "referral", label: "Referral", value: 90, group: "Acquisition", color: "var(--vs-neutral-400)", }, { id: "trial", label: "Self-serve trial", value: 620, group: "Evaluation", color: "var(--accent)", }, { id: "sales", label: "Sales qualified", value: 340, group: "Evaluation", color: "var(--vs-success)", }, { id: "nurture", label: "Nurture", value: 180, group: "Evaluation", color: "var(--vs-warning)", }, { id: "unqualified", label: "Unqualified", value: 200, group: "Evaluation", color: "var(--vs-error)", }, { id: "activated", label: "Activated", value: 480, group: "Conversion", color: "var(--vs-success)", }, { id: "contracted", label: "Contracted", value: 220, group: "Conversion", color: "var(--accent)", }, { id: "lost", label: "Lost", value: 440, group: "Conversion", color: "var(--vs-error)", }, { id: "retained", label: "Retained", value: 520, group: "Outcome", color: "var(--vs-success)", }, { id: "expanded", label: "Expanded", value: 105, group: "Outcome", color: "var(--vs-info)", }, { id: "churned", label: "Churned", value: 47, group: "Outcome", color: "var(--vs-error)", }, { id: "dormant", label: "Dormant", value: 28, group: "Outcome", color: "var(--vs-neutral-400)", },];const sankeyLinks = [ { source: "organic", target: "trial", value: 360, color: "var(--accent)", }, { source: "organic", target: "sales", value: 90, color: "var(--accent)", }, { source: "organic", target: "nurture", value: 40, color: "var(--accent)", }, { source: "organic", target: "unqualified", value: 30, color: "var(--accent)", }, { source: "paid", target: "trial", value: 180, color: "var(--vs-success)", }, { source: "paid", target: "sales", value: 140, color: "var(--vs-success)", }, { source: "paid", target: "nurture", value: 30, color: "var(--vs-success)", }, { source: "paid", target: "unqualified", value: 30, color: "var(--vs-success)", }, { source: "partners", target: "trial", value: 50, color: "var(--vs-info)", }, { source: "partners", target: "sales", value: 80, color: "var(--vs-info)", }, { source: "partners", target: "nurture", value: 40, color: "var(--vs-info)", }, { source: "partners", target: "unqualified", value: 40, color: "var(--vs-info)", }, { source: "events", target: "trial", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "sales", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "nurture", value: 50, color: "var(--vs-warning)", }, { source: "events", target: "unqualified", value: 50, color: "var(--vs-warning)", }, { source: "referral", target: "trial", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "sales", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "nurture", value: 20, color: "var(--vs-neutral-400)", }, { source: "referral", target: "unqualified", value: 50, color: "var(--vs-neutral-400)", }, { source: "trial", target: "activated", value: 380, color: "var(--accent)", }, { source: "trial", target: "contracted", value: 40, color: "var(--accent)", }, { source: "trial", target: "lost", value: 200, color: "var(--accent)", }, { source: "sales", target: "activated", value: 70, color: "var(--vs-success)", }, { source: "sales", target: "contracted", value: 160, color: "var(--vs-success)", }, { source: "sales", target: "lost", value: 110, color: "var(--vs-success)", }, { source: "nurture", target: "activated", value: 30, color: "var(--vs-warning)", }, { source: "nurture", target: "contracted", value: 20, color: "var(--vs-warning)", }, { source: "nurture", target: "lost", value: 130, color: "var(--vs-warning)", }, { source: "activated", target: "retained", value: 360, color: "var(--vs-success)", }, { source: "activated", target: "expanded", value: 55, color: "var(--vs-success)", }, { source: "activated", target: "churned", value: 40, color: "var(--vs-success)", }, { source: "activated", target: "dormant", value: 25, color: "var(--vs-success)", }, { source: "contracted", target: "retained", value: 160, color: "var(--accent)", }, { source: "contracted", target: "expanded", value: 50, color: "var(--accent)", }, { source: "contracted", target: "churned", value: 7, color: "var(--accent)", }, { source: "contracted", target: "dormant", value: 3, color: "var(--accent)", },];</script> <template> <div> <VariantToggle v-model="layout" label="Layout" :options="layouts" /> <SankeyChart :nodes="sankeyNodes" :links="sankeyLinks" :layout="layout" aria-label="Journey of 1,340 prospect sessions from acquisition through evaluation, conversion, and customer outcomes, 2026" /> </div></template>- surface
- —
- marks
- —
- size
- —
- value
- —
ts
import { ChangeDetectionStrategy, Component, signal } from "@angular/core";import { GrassrootSankeyChart } from "@grassroot/charts-angular";import { VariantToggleComponent } from "./VariantToggle.component"; @Component({ selector: "app-sankey-chart-chart-demo", standalone: true, imports: [GrassrootSankeyChart, VariantToggleComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `<app-variant-toggle label="Layout" [options]="layouts" [value]="layout()" (valueChange)="setLayout($event)" /><grassroot-sankey-chart [nodes]="sankeyNodes" [links]="sankeyLinks" [layout]="layout()" ariaLabel="Journey of 1,340 prospect sessions from acquisition through evaluation, conversion, and customer outcomes, 2026" />`,})export class SankeyChartDemoComponent { readonly layout = signal<"sankey" | "alluvial">("sankey"); readonly layouts = [ { value: "sankey", label: "Sankey" }, { value: "alluvial", label: "Alluvial" }, ] as const; readonly sankeyNodes = [ { id: "organic", label: "Organic", value: 520, group: "Acquisition", color: "var(--accent)", }, { id: "paid", label: "Paid", value: 380, group: "Acquisition", color: "var(--vs-success)", }, { id: "partners", label: "Partners", value: 210, group: "Acquisition", color: "var(--vs-info)", }, { id: "events", label: "Events", value: 140, group: "Acquisition", color: "var(--vs-warning)", }, { id: "referral", label: "Referral", value: 90, group: "Acquisition", color: "var(--vs-neutral-400)", }, { id: "trial", label: "Self-serve trial", value: 620, group: "Evaluation", color: "var(--accent)", }, { id: "sales", label: "Sales qualified", value: 340, group: "Evaluation", color: "var(--vs-success)", }, { id: "nurture", label: "Nurture", value: 180, group: "Evaluation", color: "var(--vs-warning)", }, { id: "unqualified", label: "Unqualified", value: 200, group: "Evaluation", color: "var(--vs-error)", }, { id: "activated", label: "Activated", value: 480, group: "Conversion", color: "var(--vs-success)", }, { id: "contracted", label: "Contracted", value: 220, group: "Conversion", color: "var(--accent)", }, { id: "lost", label: "Lost", value: 440, group: "Conversion", color: "var(--vs-error)", }, { id: "retained", label: "Retained", value: 520, group: "Outcome", color: "var(--vs-success)", }, { id: "expanded", label: "Expanded", value: 105, group: "Outcome", color: "var(--vs-info)", }, { id: "churned", label: "Churned", value: 47, group: "Outcome", color: "var(--vs-error)", }, { id: "dormant", label: "Dormant", value: 28, group: "Outcome", color: "var(--vs-neutral-400)", }, ]; readonly sankeyLinks = [ { source: "organic", target: "trial", value: 360, color: "var(--accent)", }, { source: "organic", target: "sales", value: 90, color: "var(--accent)", }, { source: "organic", target: "nurture", value: 40, color: "var(--accent)", }, { source: "organic", target: "unqualified", value: 30, color: "var(--accent)", }, { source: "paid", target: "trial", value: 180, color: "var(--vs-success)", }, { source: "paid", target: "sales", value: 140, color: "var(--vs-success)", }, { source: "paid", target: "nurture", value: 30, color: "var(--vs-success)", }, { source: "paid", target: "unqualified", value: 30, color: "var(--vs-success)", }, { source: "partners", target: "trial", value: 50, color: "var(--vs-info)", }, { source: "partners", target: "sales", value: 80, color: "var(--vs-info)", }, { source: "partners", target: "nurture", value: 40, color: "var(--vs-info)", }, { source: "partners", target: "unqualified", value: 40, color: "var(--vs-info)", }, { source: "events", target: "trial", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "sales", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "nurture", value: 50, color: "var(--vs-warning)", }, { source: "events", target: "unqualified", value: 50, color: "var(--vs-warning)", }, { source: "referral", target: "trial", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "sales", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "nurture", value: 20, color: "var(--vs-neutral-400)", }, { source: "referral", target: "unqualified", value: 50, color: "var(--vs-neutral-400)", }, { source: "trial", target: "activated", value: 380, color: "var(--accent)", }, { source: "trial", target: "contracted", value: 40, color: "var(--accent)", }, { source: "trial", target: "lost", value: 200, color: "var(--accent)", }, { source: "sales", target: "activated", value: 70, color: "var(--vs-success)", }, { source: "sales", target: "contracted", value: 160, color: "var(--vs-success)", }, { source: "sales", target: "lost", value: 110, color: "var(--vs-success)", }, { source: "nurture", target: "activated", value: 30, color: "var(--vs-warning)", }, { source: "nurture", target: "contracted", value: 20, color: "var(--vs-warning)", }, { source: "nurture", target: "lost", value: 130, color: "var(--vs-warning)", }, { source: "activated", target: "retained", value: 360, color: "var(--vs-success)", }, { source: "activated", target: "expanded", value: 55, color: "var(--vs-success)", }, { source: "activated", target: "churned", value: 40, color: "var(--vs-success)", }, { source: "activated", target: "dormant", value: 25, color: "var(--vs-success)", }, { source: "contracted", target: "retained", value: 160, color: "var(--accent)", }, { source: "contracted", target: "expanded", value: 50, color: "var(--accent)", }, { source: "contracted", target: "churned", value: 7, color: "var(--accent)", }, { source: "contracted", target: "dormant", value: 3, color: "var(--accent)", }, ]; setLayout(value: string): void { if (value === "sankey" || value === "alluvial") this.layout.set(value); }} export default SankeyChartDemoComponent;- surface
- —
- marks
- —
- size
- —
- value
- —
ts
<script lang="ts"> import { SankeyChart } from "@grassroot/charts-svelte"; import VariantToggle from "./VariantToggle.svelte"; let layout = $state<"sankey" | "alluvial">("sankey"); const layouts = [ { value: "sankey", label: "Sankey" }, { value: "alluvial", label: "Alluvial" }, ]; const sankeyNodes = [ { id: "organic", label: "Organic", value: 520, group: "Acquisition", color: "var(--accent)", }, { id: "paid", label: "Paid", value: 380, group: "Acquisition", color: "var(--vs-success)", }, { id: "partners", label: "Partners", value: 210, group: "Acquisition", color: "var(--vs-info)", }, { id: "events", label: "Events", value: 140, group: "Acquisition", color: "var(--vs-warning)", }, { id: "referral", label: "Referral", value: 90, group: "Acquisition", color: "var(--vs-neutral-400)", }, { id: "trial", label: "Self-serve trial", value: 620, group: "Evaluation", color: "var(--accent)", }, { id: "sales", label: "Sales qualified", value: 340, group: "Evaluation", color: "var(--vs-success)", }, { id: "nurture", label: "Nurture", value: 180, group: "Evaluation", color: "var(--vs-warning)", }, { id: "unqualified", label: "Unqualified", value: 200, group: "Evaluation", color: "var(--vs-error)", }, { id: "activated", label: "Activated", value: 480, group: "Conversion", color: "var(--vs-success)", }, { id: "contracted", label: "Contracted", value: 220, group: "Conversion", color: "var(--accent)", }, { id: "lost", label: "Lost", value: 440, group: "Conversion", color: "var(--vs-error)", }, { id: "retained", label: "Retained", value: 520, group: "Outcome", color: "var(--vs-success)", }, { id: "expanded", label: "Expanded", value: 105, group: "Outcome", color: "var(--vs-info)", }, { id: "churned", label: "Churned", value: 47, group: "Outcome", color: "var(--vs-error)", }, { id: "dormant", label: "Dormant", value: 28, group: "Outcome", color: "var(--vs-neutral-400)", }, ]; const sankeyLinks = [ { source: "organic", target: "trial", value: 360, color: "var(--accent)", }, { source: "organic", target: "sales", value: 90, color: "var(--accent)", }, { source: "organic", target: "nurture", value: 40, color: "var(--accent)", }, { source: "organic", target: "unqualified", value: 30, color: "var(--accent)", }, { source: "paid", target: "trial", value: 180, color: "var(--vs-success)", }, { source: "paid", target: "sales", value: 140, color: "var(--vs-success)", }, { source: "paid", target: "nurture", value: 30, color: "var(--vs-success)", }, { source: "paid", target: "unqualified", value: 30, color: "var(--vs-success)", }, { source: "partners", target: "trial", value: 50, color: "var(--vs-info)", }, { source: "partners", target: "sales", value: 80, color: "var(--vs-info)", }, { source: "partners", target: "nurture", value: 40, color: "var(--vs-info)", }, { source: "partners", target: "unqualified", value: 40, color: "var(--vs-info)", }, { source: "events", target: "trial", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "sales", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "nurture", value: 50, color: "var(--vs-warning)", }, { source: "events", target: "unqualified", value: 50, color: "var(--vs-warning)", }, { source: "referral", target: "trial", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "sales", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "nurture", value: 20, color: "var(--vs-neutral-400)", }, { source: "referral", target: "unqualified", value: 50, color: "var(--vs-neutral-400)", }, { source: "trial", target: "activated", value: 380, color: "var(--accent)", }, { source: "trial", target: "contracted", value: 40, color: "var(--accent)", }, { source: "trial", target: "lost", value: 200, color: "var(--accent)", }, { source: "sales", target: "activated", value: 70, color: "var(--vs-success)", }, { source: "sales", target: "contracted", value: 160, color: "var(--vs-success)", }, { source: "sales", target: "lost", value: 110, color: "var(--vs-success)", }, { source: "nurture", target: "activated", value: 30, color: "var(--vs-warning)", }, { source: "nurture", target: "contracted", value: 20, color: "var(--vs-warning)", }, { source: "nurture", target: "lost", value: 130, color: "var(--vs-warning)", }, { source: "activated", target: "retained", value: 360, color: "var(--vs-success)", }, { source: "activated", target: "expanded", value: 55, color: "var(--vs-success)", }, { source: "activated", target: "churned", value: 40, color: "var(--vs-success)", }, { source: "activated", target: "dormant", value: 25, color: "var(--vs-success)", }, { source: "contracted", target: "retained", value: 160, color: "var(--accent)", }, { source: "contracted", target: "expanded", value: 50, color: "var(--accent)", }, { source: "contracted", target: "churned", value: 7, color: "var(--accent)", }, { source: "contracted", target: "dormant", value: 3, color: "var(--accent)", }, ];</script> <div> <VariantToggle label="Layout" options={layouts} value={layout} onchange={(value) => (layout = value as typeof layout)} /> <SankeyChart nodes={sankeyNodes} links={sankeyLinks} {layout} ariaLabel="Journey of 1,340 prospect sessions from acquisition through evaluation, conversion, and customer outcomes, 2026" /></div>- surface
- —
- marks
- —
- size
- —
- value
- —
ts
/** @jsxImportSource solid-js */import { createSignal } from "solid-js";import { SankeyChart } from "@grassroot/charts-solid";import { VariantToggle } from "./VariantToggle";const sankeyNodes = [ { id: "organic", label: "Organic", value: 520, group: "Acquisition", color: "var(--accent)", }, { id: "paid", label: "Paid", value: 380, group: "Acquisition", color: "var(--vs-success)", }, { id: "partners", label: "Partners", value: 210, group: "Acquisition", color: "var(--vs-info)", }, { id: "events", label: "Events", value: 140, group: "Acquisition", color: "var(--vs-warning)", }, { id: "referral", label: "Referral", value: 90, group: "Acquisition", color: "var(--vs-neutral-400)", }, { id: "trial", label: "Self-serve trial", value: 620, group: "Evaluation", color: "var(--accent)", }, { id: "sales", label: "Sales qualified", value: 340, group: "Evaluation", color: "var(--vs-success)", }, { id: "nurture", label: "Nurture", value: 180, group: "Evaluation", color: "var(--vs-warning)", }, { id: "unqualified", label: "Unqualified", value: 200, group: "Evaluation", color: "var(--vs-error)", }, { id: "activated", label: "Activated", value: 480, group: "Conversion", color: "var(--vs-success)", }, { id: "contracted", label: "Contracted", value: 220, group: "Conversion", color: "var(--accent)", }, { id: "lost", label: "Lost", value: 440, group: "Conversion", color: "var(--vs-error)", }, { id: "retained", label: "Retained", value: 520, group: "Outcome", color: "var(--vs-success)", }, { id: "expanded", label: "Expanded", value: 105, group: "Outcome", color: "var(--vs-info)", }, { id: "churned", label: "Churned", value: 47, group: "Outcome", color: "var(--vs-error)", }, { id: "dormant", label: "Dormant", value: 28, group: "Outcome", color: "var(--vs-neutral-400)", },];const sankeyLinks = [ { source: "organic", target: "trial", value: 360, color: "var(--accent)", }, { source: "organic", target: "sales", value: 90, color: "var(--accent)", }, { source: "organic", target: "nurture", value: 40, color: "var(--accent)", }, { source: "organic", target: "unqualified", value: 30, color: "var(--accent)", }, { source: "paid", target: "trial", value: 180, color: "var(--vs-success)", }, { source: "paid", target: "sales", value: 140, color: "var(--vs-success)", }, { source: "paid", target: "nurture", value: 30, color: "var(--vs-success)", }, { source: "paid", target: "unqualified", value: 30, color: "var(--vs-success)", }, { source: "partners", target: "trial", value: 50, color: "var(--vs-info)", }, { source: "partners", target: "sales", value: 80, color: "var(--vs-info)", }, { source: "partners", target: "nurture", value: 40, color: "var(--vs-info)", }, { source: "partners", target: "unqualified", value: 40, color: "var(--vs-info)", }, { source: "events", target: "trial", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "sales", value: 20, color: "var(--vs-warning)", }, { source: "events", target: "nurture", value: 50, color: "var(--vs-warning)", }, { source: "events", target: "unqualified", value: 50, color: "var(--vs-warning)", }, { source: "referral", target: "trial", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "sales", value: 10, color: "var(--vs-neutral-400)", }, { source: "referral", target: "nurture", value: 20, color: "var(--vs-neutral-400)", }, { source: "referral", target: "unqualified", value: 50, color: "var(--vs-neutral-400)", }, { source: "trial", target: "activated", value: 380, color: "var(--accent)", }, { source: "trial", target: "contracted", value: 40, color: "var(--accent)", }, { source: "trial", target: "lost", value: 200, color: "var(--accent)", }, { source: "sales", target: "activated", value: 70, color: "var(--vs-success)", }, { source: "sales", target: "contracted", value: 160, color: "var(--vs-success)", }, { source: "sales", target: "lost", value: 110, color: "var(--vs-success)", }, { source: "nurture", target: "activated", value: 30, color: "var(--vs-warning)", }, { source: "nurture", target: "contracted", value: 20, color: "var(--vs-warning)", }, { source: "nurture", target: "lost", value: 130, color: "var(--vs-warning)", }, { source: "activated", target: "retained", value: 360, color: "var(--vs-success)", }, { source: "activated", target: "expanded", value: 55, color: "var(--vs-success)", }, { source: "activated", target: "churned", value: 40, color: "var(--vs-success)", }, { source: "activated", target: "dormant", value: 25, color: "var(--vs-success)", }, { source: "contracted", target: "retained", value: 160, color: "var(--accent)", }, { source: "contracted", target: "expanded", value: 50, color: "var(--accent)", }, { source: "contracted", target: "churned", value: 7, color: "var(--accent)", }, { source: "contracted", target: "dormant", value: 3, color: "var(--accent)", },]; export default function SankeyChartDemo() { const [layout, setLayout] = createSignal<"sankey" | "alluvial">("sankey"); const layouts = [ { value: "sankey", label: "Sankey" }, { value: "alluvial", label: "Alluvial" }, ]; return ( <div> <VariantToggle label="Layout" options={layouts} value={layout} onChange={(value) => setLayout(value as "sankey" | "alluvial")} /> <SankeyChart nodes={sankeyNodes} links={sankeyLinks} layout={layout()} ariaLabel="Journey of 1,340 prospect sessions from acquisition through evaluation, conversion, and customer outcomes, 2026" /> </div> );}Installation
API Reference
Import
import { useState } from "react";
import { SankeyChart } from "@grassroot/charts-react";
import { VariantToggle } from "./VariantToggle";
Props
Prop
Type
Default
Requirement
Description
nodesreadonly NetworkNode[]—
required
—
linksreadonly NetworkLink[]—
required
—
layoutSankeyLayoutMode | undefined—
optional
—
legendboolean | import("@grassroot/chart-spec").LegendConfig | undefined—
optional
—
tooltipboolean | import("./base").ExpandedChartTooltipConfig<unknown> | undefined—
optional
—
animationboolean | import("./base").ExpandedChartAnimationConfig | undefined—
optional
—
onHiddenSeriesChange((ids: readonly string[]) => void) | undefined—
optional
—
onActiveDatumChange((id: string | null) => void) | undefined—
optional
—
rendererChartRenderer | undefined—
optional
—
classNamestring | undefined—
optional
—
themeimport("@grassroot/theme").PartialChartTheme | undefined—
optional
—
titlestring | undefined—
optional
—
descriptionstring | undefined—
optional
—
ariaLabelstring | undefined—
optional
—
- Prop
links- Type
readonly NetworkLink[]- Default
- —
- Requirement
- required
- Description
- —
- Prop
layout- Type
SankeyLayoutMode | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
legend- Type
boolean | import("@grassroot/chart-spec").LegendConfig | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
tooltip- Type
boolean | import("./base").ExpandedChartTooltipConfig<unknown> | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
animation- Type
boolean | import("./base").ExpandedChartAnimationConfig | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
onHiddenSeriesChange- Type
((ids: readonly string[]) => void) | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
onActiveDatumChange- Type
((id: string | null) => void) | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
renderer- Type
ChartRenderer | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
className- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
theme- Type
import("@grassroot/theme").PartialChartTheme | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
title- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
description- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
ariaLabel- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
keyboardNavigation- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
width- Type
number | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
height- Type
number | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
gpuBackend- Type
ChartGpuBackend | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
rendererStrategy- Type
Partial<import("@grassroot/core").ChartRendererStrategy> | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
renderPlanMode- Type
"svg" | "host" | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
showGrid- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
interactive- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Description
- Gates every pointer/keyboard interaction the shell owns (hit-test on pointer move, focus-to-first, arrow navigation, Escape) and, with `keyboardNavigation`, whether the plot surface is focusable at all.
- Prop
hiddenSeries- Type
readonly string[] | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
defaultHiddenSeries- Type
readonly string[] | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
activeDatum- Type
string | null | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
defaultActiveDatum- Type
string | null | undefined- Default
- —
- Requirement
- optional
- Description
- Uncontrolled initial value for the `activeDatum`/`onActiveDatumChange` pair.
- Prop
speed- Type
number | undefined- Default
- —
- Requirement
- optional
- Description
- Playback-speed multiplier for entrance/ambient motion.
- Prop
morphDurationMs- Type
number | undefined- Default
- —
- Requirement
- optional
- Description
- How long a dataset change tweens, in milliseconds.
- Prop
replayToken- Type
string | number | undefined- Default
- —
- Requirement
- optional
- Description
- Changing this value replays the entrance animation.
- Prop
selectionMode- Type
SelectionMode | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
selectedIds- Type
SelectionValue | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
defaultSelectedIds- Type
SelectionValue | undefined- Default
- —
- Requirement
- optional
- Description
- —
- Prop
onSelectedIdsChange- Type
((ids: readonly string[]) => void) | undefined- Default
- —
- Requirement
- optional
- Description
- —
Events
| Event | Payload |
|---|---|
onHiddenSeriesChange | ((ids: readonly string[]) => void) | undefined |
onActiveDatumChange | ((id: string | null) => void) | undefined |
onSelectedIdsChange | ((ids: readonly string[]) => void) | undefined |
Content regions
childrendataSummary
Native attributes
Standard DOM and ARIA attributes not listed above spread onto the root element.
Import
import { ref } from "vue";
import { SankeyChart } from "@grassroot/charts-vue";
import VariantToggle from "./VariantToggle.vue";
Props
Prop
Type
Default
Requirement
classNamestring | undefined—
optional
gpuBackend"auto" | "webgpu" | "webgl2" | undefined—
optional
widthnumber | undefined—
optional
heightnumber | undefined—
optional
rendererChartRenderer | undefined—
optional
rendererStrategyPartial<ChartRendererStrategy> | undefined—
optional
renderPlanMode"svg" | "host" | undefined"host"optional
showGridboolean | undefined—
optional
legendboolean | LegendConfig | undefinedfalseoptional
tooltipboolean | TooltipBehaviorConfig | undefinedtrueoptional
animationChartAnimationInput | undefined—
optional
interactiveboolean | undefinedtrueoptional
- Prop
className- Type
string | undefined- Default
- —
- Requirement
- optional
- Prop
gpuBackend- Type
"auto" | "webgpu" | "webgl2" | undefined- Default
- —
- Requirement
- optional
- Prop
width- Type
number | undefined- Default
- —
- Requirement
- optional
- Prop
height- Type
number | undefined- Default
- —
- Requirement
- optional
- Prop
renderer- Type
ChartRenderer | undefined- Default
- —
- Requirement
- optional
- Prop
rendererStrategy- Type
Partial<ChartRendererStrategy> | undefined- Default
- —
- Requirement
- optional
- Prop
renderPlanMode- Type
"svg" | "host" | undefined- Default
"host"- Requirement
- optional
- Prop
showGrid- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Prop
legend- Type
boolean | LegendConfig | undefined- Default
false- Requirement
- optional
- Prop
tooltip- Type
boolean | TooltipBehaviorConfig | undefined- Default
true- Requirement
- optional
- Prop
animation- Type
ChartAnimationInput | undefined- Default
- —
- Requirement
- optional
- Prop
interactive- Type
boolean | undefined- Default
true- Requirement
- optional
- Prop
keyboardNavigation- Type
boolean | undefined- Default
true- Requirement
- optional
- Prop
hiddenSeries- Type
readonly string[] | undefined- Default
- —
- Requirement
- optional
- Prop
defaultHiddenSeries- Type
readonly string[] | undefined- Default
() => []- Requirement
- optional
- Prop
activeDatum- Type
string | null | undefined- Default
- —
- Requirement
- optional
- Prop
defaultActiveDatum- Type
string | null | undefined- Default
- —
- Requirement
- optional
- Prop
speed- Type
number | undefined- Default
- —
- Requirement
- optional
- Prop
morphDurationMs- Type
number | undefined- Default
- —
- Requirement
- optional
- Prop
replayToken- Type
string | number | undefined- Default
- —
- Requirement
- optional
- Prop
theme- Type
PartialChartTheme | undefined- Default
- —
- Requirement
- optional
- Prop
title- Type
string | undefined- Default
- —
- Requirement
- optional
- Prop
description- Type
string | undefined- Default
- —
- Requirement
- optional
- Prop
ariaLabel- Type
string | undefined- Default
- —
- Requirement
- optional
- Prop
nodes- Type
readonly NetworkNode[]- Default
- —
- Requirement
- required
- Prop
links- Type
readonly NetworkLink[]- Default
- —
- Requirement
- required
- Prop
layout- Type
SankeyLayoutMode | undefined- Default
- —
- Requirement
- optional
- Prop
selectionMode- Type
SelectionMode | undefined- Default
"none"- Requirement
- optional
- Prop
selectedIds- Type
readonly string[] | undefined- Default
- —
- Requirement
- optional
- Prop
defaultSelectedIds- Type
readonly string[] | undefined- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
hiddenSeriesChange | [ids: readonly string[]] |
activeDatumChange | [id: string | null] |
selectedIdsChange | [ids: readonly string[]] |
Content regions
dataSummarydefault
Import
import { ChangeDetectionStrategy, Component, signal } from "@angular/core";
import { GrassrootSankeyChart } from "@grassroot/charts-angular";
import { VariantToggleComponent } from "./VariantToggle.component";
Props
Prop
Type
Default
Requirement
rendererChartRenderer—
optional
gpuBackendChartGpuBackend—
optional
rendererStrategyPartial<ChartRendererStrategy>—
optional
renderPlanMode"svg" | "host""host"optional
ariaLabelstring—
optional
titlestring—
optional
descriptionstring—
optional
themePartialChartTheme—
optional
animationChartAnimationInput—
optional
interactivebooleantrueoptional
tooltipboolean | TooltipBehaviorConfigtrueoptional
legendboolean | LegendConfig—
optional
- Prop
renderer- Type
ChartRenderer- Default
- —
- Requirement
- optional
- Prop
gpuBackend- Type
ChartGpuBackend- Default
- —
- Requirement
- optional
- Prop
rendererStrategy- Type
Partial<ChartRendererStrategy>- Default
- —
- Requirement
- optional
- Prop
renderPlanMode- Type
"svg" | "host"- Default
"host"- Requirement
- optional
- Prop
ariaLabel- Type
string- Default
- —
- Requirement
- optional
- Prop
title- Type
string- Default
- —
- Requirement
- optional
- Prop
description- Type
string- Default
- —
- Requirement
- optional
- Prop
theme- Type
PartialChartTheme- Default
- —
- Requirement
- optional
- Prop
animation- Type
ChartAnimationInput- Default
- —
- Requirement
- optional
- Prop
interactive- Type
boolean- Default
true- Requirement
- optional
- Prop
keyboardNavigation- Type
boolean- Default
true- Requirement
- optional
- Prop
tooltip- Type
boolean | TooltipBehaviorConfig- Default
true- Requirement
- optional
- Prop
legend- Type
boolean | LegendConfig- Default
- —
- Requirement
- optional
- Prop
hiddenSeries- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
defaultHiddenSeries- Type
readonly string[]- Default
[]- Requirement
- optional
- Prop
activeDatum- Type
string | null- Default
- —
- Requirement
- optional
- Prop
defaultActiveDatum- Type
string | null- Default
null- Requirement
- optional
- Prop
speed- Type
number- Default
- —
- Requirement
- optional
- Prop
morphDurationMs- Type
number- Default
- —
- Requirement
- optional
- Prop
replayToken- Type
string | number- Default
- —
- Requirement
- optional
- Prop
selectionMode- Type
SelectionMode- Default
"none"- Requirement
- optional
- Prop
selectedIds- Type
SelectionValue- Default
- —
- Requirement
- optional
- Prop
defaultSelectedIds- Type
SelectionValue- Default
- —
- Requirement
- optional
- Prop
onSelectedIdsChange- Type
(ids: SelectionValue) => void- Default
- —
- Requirement
- optional
- Prop
nodes- Type
readonly NetworkNode[]- Default
- —
- Requirement
- required
- Prop
links- Type
readonly NetworkLink[]- Default
- —
- Requirement
- required
- Prop
width- Type
number- Default
- —
- Requirement
- optional
- Prop
height- Type
number- Default
- —
- Requirement
- optional
- Prop
showGrid- Type
boolean- Default
- —
- Requirement
- optional
- Prop
className- Type
string- Default
- —
- Requirement
- optional
- Prop
layout- Type
SankeyLayoutMode- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
activeDatumChange | string | null |
hiddenSeriesChange | readonly string[] |
selectedIdsChange | readonly string[] |
Content regions
dataSummarydefault
Import
import { SankeyChart } from "@grassroot/charts-svelte";
import VariantToggle from "./VariantToggle.svelte";
Props
Prop
Type
Default
Requirement
nodesreadonly NetworkNode[]—
required
linksreadonly NetworkLink[]—
required
layoutSankeyLayoutMode—
optional
selectionMode"none" | "single" | "multiple""none"optional
selectedIdsreadonly string[]—
optional
defaultSelectedIdsreadonly string[]—
optional
onSelectedIdsChange(ids: readonly string[]) => void—
optional
onHiddenSeriesChange(ids: readonly string[]) => void—
optional
onActiveDatumChange(id: string | null) => void—
optional
classstring—
optional
stylestring—
optional
widthnumber—
optional
heightnumber—
optional
rendererChartRenderer—
optional
- Prop
nodes- Type
readonly NetworkNode[]- Default
- —
- Requirement
- required
- Prop
links- Type
readonly NetworkLink[]- Default
- —
- Requirement
- required
- Prop
layout- Type
SankeyLayoutMode- Default
- —
- Requirement
- optional
- Prop
selectionMode- Type
"none" | "single" | "multiple"- Default
"none"- Requirement
- optional
- Prop
selectedIds- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
defaultSelectedIds- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
onSelectedIdsChange- Type
(ids: readonly string[]) => void- Default
- —
- Requirement
- optional
- Prop
onHiddenSeriesChange- Type
(ids: readonly string[]) => void- Default
- —
- Requirement
- optional
- Prop
onActiveDatumChange- Type
(id: string | null) => void- Default
- —
- Requirement
- optional
- Prop
class- Type
string- Default
- —
- Requirement
- optional
- Prop
style- Type
string- Default
- —
- Requirement
- optional
- Prop
width- Type
number- Default
- —
- Requirement
- optional
- Prop
height- Type
number- Default
- —
- Requirement
- optional
- Prop
renderer- Type
ChartRenderer- Default
- —
- Requirement
- optional
- Prop
gpuBackend- Type
ChartGpuBackend- Default
- —
- Requirement
- optional
- Prop
rendererStrategy- Type
Partial<ChartRendererStrategy>- Default
- —
- Requirement
- optional
- Prop
renderPlanMode- Type
"svg" | "host"- Default
"host"- Requirement
- optional
- Prop
showGrid- Type
boolean- Default
- —
- Requirement
- optional
- Prop
legend- Type
boolean | LegendConfig- Default
false- Requirement
- optional
- Prop
tooltip- Type
boolean | TooltipBehaviorConfig- Default
true- Requirement
- optional
- Prop
animation- Type
ChartAnimationInput- Default
- —
- Requirement
- optional
- Prop
interactive- Type
boolean- Default
true- Requirement
- optional
- Prop
keyboardNavigation- Type
boolean- Default
true- Requirement
- optional
- Prop
hiddenSeries- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
defaultHiddenSeries- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
activeDatum- Type
string | null- Default
- —
- Requirement
- optional
- Prop
defaultActiveDatum- Type
string | null- Default
- —
- Requirement
- optional
- Prop
speed- Type
number- Default
- —
- Requirement
- optional
- Prop
morphDurationMs- Type
number- Default
- —
- Requirement
- optional
- Prop
replayToken- Type
string | number- Default
- —
- Requirement
- optional
- Prop
theme- Type
PartialChartTheme- Default
- —
- Requirement
- optional
- Prop
title- Type
string- Default
- —
- Requirement
- optional
- Prop
description- Type
string- Default
- —
- Requirement
- optional
- Prop
ariaLabel- Type
string- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onSelectedIdsChange | (ids: readonly string[]) => void |
onHiddenSeriesChange | (ids: readonly string[]) => void |
onActiveDatumChange | (id: string | null) => void |
Content regions
childrendataSummary
Import
import { createSignal } from "solid-js";
import { SankeyChart } from "@grassroot/charts-solid";
import { VariantToggle } from "./VariantToggle";
Props
Prop
Type
Default
Requirement
nodesreadonly NetworkNode[]—
required
linksreadonly NetworkLink[]—
required
layoutSankeyLayoutMode—
optional
onActiveDatumChange(id: string | null) => void—
optional
onHiddenSeriesChange(ids: readonly string[]) => void—
optional
classstring—
optional
styleJSX.CSSProperties—
optional
widthnumber—
optional
heightnumber—
optional
rendererChartRenderer—
optional
gpuBackendChartGpuBackend"auto"optional
rendererStrategyPartial<ChartRendererStrategy>—
optional
renderPlanMode"svg" | "host""host"optional
showGridboolean—
optional
- Prop
nodes- Type
readonly NetworkNode[]- Default
- —
- Requirement
- required
- Prop
links- Type
readonly NetworkLink[]- Default
- —
- Requirement
- required
- Prop
layout- Type
SankeyLayoutMode- Default
- —
- Requirement
- optional
- Prop
onActiveDatumChange- Type
(id: string | null) => void- Default
- —
- Requirement
- optional
- Prop
onHiddenSeriesChange- Type
(ids: readonly string[]) => void- Default
- —
- Requirement
- optional
- Prop
class- Type
string- Default
- —
- Requirement
- optional
- Prop
style- Type
JSX.CSSProperties- Default
- —
- Requirement
- optional
- Prop
width- Type
number- Default
- —
- Requirement
- optional
- Prop
height- Type
number- Default
- —
- Requirement
- optional
- Prop
renderer- Type
ChartRenderer- Default
- —
- Requirement
- optional
- Prop
gpuBackend- Type
ChartGpuBackend- Default
"auto"- Requirement
- optional
- Prop
rendererStrategy- Type
Partial<ChartRendererStrategy>- Default
- —
- Requirement
- optional
- Prop
renderPlanMode- Type
"svg" | "host"- Default
"host"- Requirement
- optional
- Prop
showGrid- Type
boolean- Default
- —
- Requirement
- optional
- Prop
legend- Type
boolean | LegendConfig- Default
- —
- Requirement
- optional
- Prop
tooltip- Type
boolean | TooltipBehaviorConfig- Default
- —
- Requirement
- optional
- Prop
animation- Type
ChartAnimationInput- Default
- —
- Requirement
- optional
- Prop
interactive- Type
boolean- Default
- —
- Requirement
- optional
- Prop
keyboardNavigation- Type
boolean- Default
- —
- Requirement
- optional
- Prop
hiddenSeries- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
defaultHiddenSeries- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
activeDatum- Type
string | null- Default
- —
- Requirement
- optional
- Prop
defaultActiveDatum- Type
string | null- Default
- —
- Requirement
- optional
- Prop
speed- Type
number- Default
- —
- Requirement
- optional
- Prop
morphDurationMs- Type
number- Default
- —
- Requirement
- optional
- Prop
replayToken- Type
string | number- Default
- —
- Requirement
- optional
- Prop
theme- Type
PartialChartTheme- Default
- —
- Requirement
- optional
- Prop
title- Type
string- Default
- —
- Requirement
- optional
- Prop
description- Type
string- Default
- —
- Requirement
- optional
- Prop
ariaLabel- Type
string- Default
- —
- Requirement
- optional
- Prop
selectionMode- Type
SelectionMode- Default
- —
- Requirement
- optional
- Prop
selectedIds- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
defaultSelectedIds- Type
readonly string[]- Default
- —
- Requirement
- optional
- Prop
onSelectedIdsChange- Type
(ids: readonly string[]) => void- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onActiveDatumChange | (id: string | null) => void |
onHiddenSeriesChange | (ids: readonly string[]) => void |
onSelectedIdsChange | (ids: readonly string[]) => void |
Content regions
childrendataSummary