diff --git a/next.config.ts b/next.config.ts
index 1a329fe..14884e1 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -50,6 +50,26 @@ const nextConfig: NextConfig = {
destination: "/docs/sankey-chart/static",
permanent: true,
},
+ {
+ source: "/docs/scatter-chart",
+ destination: "/docs/scatter-chart/static",
+ permanent: true,
+ },
+ {
+ source: "/docs/treemap-chart",
+ destination: "/docs/treemap-chart/static",
+ permanent: true,
+ },
+ {
+ source: "/docs/funnel-chart",
+ destination: "/docs/funnel-chart/static",
+ permanent: true,
+ },
+ {
+ source: "/docs/waterfall-chart",
+ destination: "/docs/waterfall-chart/static",
+ permanent: true,
+ },
// Some old projects redirects cached on google
{
source: "/docs/line-charts",
diff --git a/registry.json b/registry.json
index 9d885e5..c193c84 100644
--- a/registry.json
+++ b/registry.json
@@ -272,6 +272,95 @@
}
]
},
+ {
+ "name": "scatter-chart",
+ "description": "Scatter chart component for visualizing correlations between two variables",
+ "registryDependencies": [
+ "@evilcharts/chart",
+ "@evilcharts/tooltip",
+ "@evilcharts/legend",
+ "@evilcharts/dot",
+ "@evilcharts/background"
+ ],
+ "dependencies": [
+ "recharts",
+ "motion"
+ ],
+ "type": "registry:component",
+ "files": [
+ {
+ "path": "src/registry/charts/scatter-chart.tsx",
+ "type": "registry:component",
+ "target": "components/evilcharts/charts/scatter-chart.tsx"
+ }
+ ]
+ },
+ {
+ "name": "treemap-chart",
+ "description": "Treemap chart component for hierarchical category breakdowns",
+ "registryDependencies": [
+ "@evilcharts/chart",
+ "@evilcharts/tooltip",
+ "@evilcharts/legend",
+ "@evilcharts/background"
+ ],
+ "dependencies": [
+ "recharts",
+ "motion"
+ ],
+ "type": "registry:component",
+ "files": [
+ {
+ "path": "src/registry/charts/treemap-chart.tsx",
+ "type": "registry:component",
+ "target": "components/evilcharts/charts/treemap-chart.tsx"
+ }
+ ]
+ },
+ {
+ "name": "funnel-chart",
+ "description": "Funnel chart component for conversion and stage drop-off analysis",
+ "registryDependencies": [
+ "@evilcharts/chart",
+ "@evilcharts/tooltip",
+ "@evilcharts/legend",
+ "@evilcharts/background"
+ ],
+ "dependencies": [
+ "recharts",
+ "motion"
+ ],
+ "type": "registry:component",
+ "files": [
+ {
+ "path": "src/registry/charts/funnel-chart.tsx",
+ "type": "registry:component",
+ "target": "components/evilcharts/charts/funnel-chart.tsx"
+ }
+ ]
+ },
+ {
+ "name": "waterfall-chart",
+ "description": "Waterfall chart component for revenue bridges and variance walkthroughs",
+ "registryDependencies": [
+ "@evilcharts/chart",
+ "@evilcharts/tooltip",
+ "@evilcharts/legend",
+ "@evilcharts/background"
+ ],
+ "dependencies": [
+ "recharts",
+ "motion"
+ ],
+ "type": "registry:component",
+ "files": [
+ {
+ "path": "src/registry/charts/waterfall-chart.tsx",
+ "type": "registry:component",
+ "target": "components/evilcharts/charts/waterfall-chart.tsx"
+ }
+ ]
+ },
{
"name": "ex-area-chart",
"registryDependencies": [
@@ -1455,6 +1544,175 @@
}
]
},
+ {
+ "name": "ex-scatter-chart",
+ "registryDependencies": [
+ "@evilcharts/scatter-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-scatter-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-gradient-colors-scatter-chart",
+ "registryDependencies": [
+ "@evilcharts/scatter-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-gradient-colors-scatter-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-loading-state-scatter-chart",
+ "registryDependencies": [
+ "@evilcharts/scatter-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-loading-state-scatter-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-glowing-scatter-chart",
+ "registryDependencies": [
+ "@evilcharts/scatter-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-glowing-scatter-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-treemap-chart",
+ "registryDependencies": [
+ "@evilcharts/treemap-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-treemap-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-glowing-treemap-chart",
+ "registryDependencies": [
+ "@evilcharts/treemap-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-glowing-treemap-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-loading-state-treemap-chart",
+ "registryDependencies": [
+ "@evilcharts/treemap-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-loading-state-treemap-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-funnel-chart",
+ "registryDependencies": [
+ "@evilcharts/funnel-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-funnel-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-glowing-funnel-chart",
+ "registryDependencies": [
+ "@evilcharts/funnel-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-glowing-funnel-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-loading-state-funnel-chart",
+ "registryDependencies": [
+ "@evilcharts/funnel-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-loading-state-funnel-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-waterfall-chart",
+ "registryDependencies": [
+ "@evilcharts/waterfall-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-waterfall-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-glowing-waterfall-chart",
+ "registryDependencies": [
+ "@evilcharts/waterfall-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-glowing-waterfall-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
+ {
+ "name": "ex-loading-state-waterfall-chart",
+ "registryDependencies": [
+ "@evilcharts/waterfall-chart"
+ ],
+ "type": "registry:block",
+ "files": [
+ {
+ "path": "src/registry/examples/ex-loading-state-waterfall-chart.tsx",
+ "type": "registry:block"
+ }
+ ]
+ },
{
"name": "ex-sankey-chart",
"registryDependencies": [
diff --git a/src/assets/icons/index.tsx b/src/assets/icons/index.tsx
index 4230ef4..1883237 100644
--- a/src/assets/icons/index.tsx
+++ b/src/assets/icons/index.tsx
@@ -324,6 +324,118 @@ export function SankeyChartIcon({
);
}
+export function ScatterChartIcon({
+ fill = "currentColor",
+ secondaryfill,
+ width = "1em",
+ height = "1em",
+ ...props
+}: IconProps) {
+ secondaryfill = secondaryfill || fill;
+
+ return (
+
+ );
+}
+
+export function TreemapChartIcon({
+ fill = "currentColor",
+ secondaryfill,
+ width = "1em",
+ height = "1em",
+ ...props
+}: IconProps) {
+ secondaryfill = secondaryfill || fill;
+
+ return (
+
+ );
+}
+
+export function FunnelChartIcon({
+ fill = "currentColor",
+ secondaryfill,
+ width = "1em",
+ height = "1em",
+ ...props
+}: IconProps) {
+ secondaryfill = secondaryfill || fill;
+
+ return (
+
+ );
+}
+
+export function WaterfallChartIcon({
+ fill = "currentColor",
+ secondaryfill,
+ width = "1em",
+ height = "1em",
+ ...props
+}: IconProps) {
+ secondaryfill = secondaryfill || fill;
+
+ return (
+
+ );
+}
+
export function ShapesIcon({
fill = "currentColor",
secondaryfill,
diff --git a/src/components/docs/mdx/components/showcase-grid.tsx b/src/components/docs/mdx/components/showcase-grid.tsx
index b6edc1a..94fc5da 100644
--- a/src/components/docs/mdx/components/showcase-grid.tsx
+++ b/src/components/docs/mdx/components/showcase-grid.tsx
@@ -8,6 +8,10 @@ import { LinePreview } from "@/components/docs/svg-previews/line-preview";
import { AreaPreview } from "@/components/docs/svg-previews/area-preview";
import { PiePreview } from "@/components/docs/svg-previews/pie-preview";
import { BarPreview } from "@/components/docs/svg-previews/bar-preview";
+import { ScatterPreview } from "@/components/docs/svg-previews/scatter-preview";
+import { TreemapPreview } from "@/components/docs/svg-previews/treemap-preview";
+import { FunnelPreview } from "@/components/docs/svg-previews/funnel-preview";
+import { WaterfallPreview } from "@/components/docs/svg-previews/waterfall-preview";
import { Grid } from "@/components/docs/svg-previews/background-grid";
import Link from "next/link";
@@ -67,6 +71,30 @@ const CHARTS: Chart[] = [
Component: SankeyPreview,
url: "/docs/sankey-chart",
},
+ {
+ name: "Scatter Chart",
+ description: "Explore correlations between two variables.",
+ Component: ScatterPreview,
+ url: "/docs/scatter-chart",
+ },
+ {
+ name: "Treemap Chart",
+ description: "Break down categories by weighted area tiles.",
+ Component: TreemapPreview,
+ url: "/docs/treemap-chart",
+ },
+ {
+ name: "Funnel Chart",
+ description: "Track conversion drop-off across stages.",
+ Component: FunnelPreview,
+ url: "/docs/funnel-chart",
+ },
+ {
+ name: "Waterfall Chart",
+ description: "Bridge totals with increases and decreases.",
+ Component: WaterfallPreview,
+ url: "/docs/waterfall-chart",
+ },
];
interface ShowcaseItemProps {
diff --git a/src/components/docs/svg-previews/funnel-preview.tsx b/src/components/docs/svg-previews/funnel-preview.tsx
new file mode 100644
index 0000000..3678eb5
--- /dev/null
+++ b/src/components/docs/svg-previews/funnel-preview.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+export const FunnelPreview = () => (
+
+);
diff --git a/src/components/docs/svg-previews/scatter-preview.tsx b/src/components/docs/svg-previews/scatter-preview.tsx
new file mode 100644
index 0000000..5422339
--- /dev/null
+++ b/src/components/docs/svg-previews/scatter-preview.tsx
@@ -0,0 +1,64 @@
+import React from "react";
+
+export const ScatterPreview = () => {
+ return (
+
+ );
+};
diff --git a/src/components/docs/svg-previews/treemap-preview.tsx b/src/components/docs/svg-previews/treemap-preview.tsx
new file mode 100644
index 0000000..5ed0d4c
--- /dev/null
+++ b/src/components/docs/svg-previews/treemap-preview.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+export const TreemapPreview = () => (
+
+);
diff --git a/src/components/docs/svg-previews/waterfall-preview.tsx b/src/components/docs/svg-previews/waterfall-preview.tsx
new file mode 100644
index 0000000..f9967e2
--- /dev/null
+++ b/src/components/docs/svg-previews/waterfall-preview.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+export const WaterfallPreview = () => (
+
+);
diff --git a/src/content/docs/bar-chart/static.mdx b/src/content/docs/bar-chart/static.mdx
index 4f1835c..19b5902 100644
--- a/src/content/docs/bar-chart/static.mdx
+++ b/src/content/docs/bar-chart/static.mdx
@@ -8,7 +8,8 @@ links:
api: https://recharts.github.io/en-US/api/BarChart/
---
-
+
+
## Installation
@@ -182,10 +183,9 @@ Below are some examples of the bar chart with different `variants`. Each ``
### Horizontal Layout
-
- Use `layout="horizontal"` on `` to display bars horizontally. In horizontal mode, the `` shows categories while the `` shows values — pass a `tickFormatter` to `` for category formatting.
+ Use `layout="horizontal"` on `` to display bars horizontally. Compose both `` (values) and `` (categories). See the preview at the top of this page.
diff --git a/src/content/docs/funnel-chart/meta.json b/src/content/docs/funnel-chart/meta.json
new file mode 100644
index 0000000..53fc185
--- /dev/null
+++ b/src/content/docs/funnel-chart/meta.json
@@ -0,0 +1 @@
+{ "title": "Funnel Chart", "pages": ["static"] }
diff --git a/src/content/docs/funnel-chart/static.mdx b/src/content/docs/funnel-chart/static.mdx
new file mode 100644
index 0000000..a4c31ca
--- /dev/null
+++ b/src/content/docs/funnel-chart/static.mdx
@@ -0,0 +1,298 @@
+---
+title: Funnel Chart
+description: Stage-based funnel visuals built atop composable EvilCharts primitives
+image: /og/funnel-chart.png
+links:
+ github: https://github.com/legions-developer/evilcharts/blob/main/src/registry/charts/funnel-chart.tsx
+ doc: https://recharts.github.io/en-US/examples/SimpleBarChart/
+ api: https://recharts.github.io/en-US/api/BarChart/
+---
+
+
+
+## Installation
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+
+
+ Install the following dependencies:
+
+
+
+
+
+ Copy and paste the following code snippets into your project.
+
+ To use the chart, first create the folder `evilcharts` and a subfolder called `charts` inside your `components` directory.
+ Then, copy the following base funnel-chart code into a new file in that folder.
+
+
+
+
+
+
+ Now, Let's add the chart component to your project.
+
+ These Components are required by the chart component to render the chart. Make a folder called `ui` inside the `evilcharts` folder and paste the code there.
+
+ Below is main chart component.
+
+
+
+
+
+
+ Now, We need to add sub components.
+
+ Create a file called `tooltip.tsx` inside the `evilcharts/ui` folder and paste the code there.
+
+
+
+
+
+ Now, create another file called `legend.tsx` inside the `evilcharts/ui` folder and paste the code there.
+
+
+
+
+
+
+
+
+
+## Usage
+
+The funnel chart is composible. `` wraps a vertically laid out Recharts `` with custom trapezoid shapes per stage (`stageKey`) and measured values (`valueKey`). Compose ``, ``, ``, ``, ``, `` as needed, and set optional `backgroundVariant` on the chart root — Recharts has no standalone funnel primitive, but every native chart prop can pass through `chartProps` alongside the underlying BarChart escape hatch documented below.
+
+```tsx
+import {
+ EvilFunnelChart,
+ Stages,
+ XAxis,
+ YAxis,
+ Grid,
+ Tooltip,
+ Legend,
+} from "@/components/evilcharts/charts/funnel-chart";
+```
+
+```tsx
+
+
+
+
+
+
+
+
+```
+
+### Interactive Selection
+
+Add `isClickable` to `` (plus `` when you want swatches clickable) then listen on `onSelectionChange` (`{ dataKey, value } | null`). `dataKey` matches rows’ `stageKey` string:
+
+```tsx
+ {
+ if (selection) {
+ console.log("Selected:", selection.dataKey, selection.value);
+ } else {
+ console.log("Deselected");
+ }
+ }}
+>
+
+
+
+
+
+
+```
+
+### Loading State
+
+
+
+
+ The funnel chart supports loading state. Pass `isLoading` to shimmer placeholder stages synthesized from deterministic loading rows while awaiting real funnel data (tune fictitious heights with `loadingStages`).
+
+
+
+## Examples
+
+### Glowing Stages
+
+
+
+## API Reference
+
+The chart is composed of several parts. The props below are grouped by the component they belong to.
+
+EvilFunnelChart
+
+The root container wrapping a vertical ``. Holds stage metadata, synthesized loading rows when `isLoading`, max-value scaling shared by funnel shapes, and selection state surfaced to ``/``.
+
+
+
+ Keys must correspond to serialized `stageKey` values (`string`) so gradients + legend labels resolve per funnel stage color stop.
+
+
+ Rows with `stageKey` + numeric `valueKey` fields typed as literals for inference (`TData extends Record`).
+
+
+ Categorical funnel stage identifier surfaced on `` ticks and gradients.
+
+
+ Numeric throughput used to scale each trapezoid width plus tooltip payload.
+
+
+ ``, ``, ``, ``, ``, ``, plus optional root `backgroundVariant`, and escapes through forwarded Recharts props via `chartProps`.
+
+
+ Additional wrapper classes forwarded to ``.
+
+
+ Vertical gutter between stacked funnel polygons inside each category band.
+
+
+ Draws `` beneath the funnel (same pattern as bar and scatter charts).
+
+
+ Pre-select matching `stageKey` string (`null` clears).
+
+
+ Fires when clickable legend / stage polygons toggle visibility focus.
+
+
+ Swaps rendered rows with motion-shimmer placeholders while preserving axes + tooltip wiring.
+
+
+ Count of synthesized placeholder polygons while `isLoading` is active.
+
+
+ Native Recharts props forwarded to `` — sizing, responsiveness, syncing, brushes, margins, anything outside `data/layout` defaults we already encode. Refer to Recharts BarChart; there is no dedicated funnel primitive, so this escape hatch doubles as funnel tuning.
+
+
+
+Stages
+
+Configuration slot mirrored by funnel renderer — determines whether polygons listen for clicks / glow defs.
+
+
+
+ Enables polygon click toggling. Selection dimming applies whenever a stage is selected (legend, default, or click).
+
+
+ Names matching `stageKey` values emitting glow filters akin to EvilBars.
+
+
+
+XAxis
+
+Mirrors numeric scale even though EvilFunnel hides ticks by default to keep silhouette clean (`hide` forwarding Recharts semantics).
+
+
+
+ Default hides axis line / ticks consistent with EvilFunnels marketing aesthetic.
+
+
+ Forwarded verbatim to `` while loading states hide axes automatically.
+
+
+ Every remaining Recharts `XAxis` prop is forwarded. Read the Recharts XAxis documentation for available props.
+
+
+
+YAxis
+
+Shows ordered funnel stages (category axis for vertical funnel layout).
+
+
+
+ Default tick gutter width accommodating stage labels before trapezoid math runs.
+
+
+ Drives categorical placement for each funnel row (`dataKey={stageKey}` internally).
+
+
+ Every remaining Recharts `YAxis` prop is forwarded. Read the Recharts YAxis documentation for available props.
+
+
+
+Grid
+
+Optional vertical-only dashed scaffolding for alignment reference.
+
+
+
+ Dash pattern forwarded to ``.
+
+
+ Horizontal lines stay disabled intentionally; remaining grid props forwarded. Read the Recharts CartesianGrid documentation for nuance.
+
+
+
+Tooltip
+
+Disables Cartesian cursor crosshair (`cursor={false}`) for cleaner funnel hovering.
+
+
+
+ Tooltip polish tier.
+
+
+ Tooltip radius.
+
+
+ Pre-highlights tooltip for a deterministic stage row while pointer idle.
+
+
+
+Legend
+
+Stage keyed legend syncing dimming + selection mirrored from ``.
+
+
+
+ Legend marker motifs.
+
+
+ Horizontal alignment.
+
+
+ Vertical stacking vs chart canvas.
+
+
+ Legend entries toggle shared selection; dimming follows `selectedStage` even when `` is not clickable.
+
+
diff --git a/src/content/docs/meta.json b/src/content/docs/meta.json
index bda5cef..9032f63 100644
--- a/src/content/docs/meta.json
+++ b/src/content/docs/meta.json
@@ -12,6 +12,10 @@
"pie-chart",
"radial-chart",
"sankey-chart",
+ "scatter-chart",
+ "treemap-chart",
+ "funnel-chart",
+ "waterfall-chart",
"ui/background",
"ui/tooltip",
"ui/legend",
diff --git a/src/content/docs/scatter-chart/meta.json b/src/content/docs/scatter-chart/meta.json
new file mode 100644
index 0000000..1bfbc60
--- /dev/null
+++ b/src/content/docs/scatter-chart/meta.json
@@ -0,0 +1 @@
+{ "title": "Scatter Chart", "pages": ["static"] }
diff --git a/src/content/docs/scatter-chart/static.mdx b/src/content/docs/scatter-chart/static.mdx
new file mode 100644
index 0000000..5bc0164
--- /dev/null
+++ b/src/content/docs/scatter-chart/static.mdx
@@ -0,0 +1,303 @@
+---
+title: Scatter Chart
+description: Beautiful scatter charts for exploring correlations between two variables
+image: /og/scatter-chart.png
+links:
+ github: https://github.com/legions-developer/evilcharts/blob/main/src/registry/charts/scatter-chart.tsx
+ doc: https://recharts.github.io/en-US/examples/SimpleScatterChart/
+ api: https://recharts.github.io/en-US/api/ScatterChart/
+---
+
+
+
+## Installation
+
+
+
+ CLI
+ Manual
+
+
+
+
+
+
+
+ Install the following dependencies:
+
+
+
+
+
+ Copy and paste the following code snippets into your project.
+
+ To use the chart, first create the folder `evilcharts` and a subfolder called `charts` inside your `components` directory.
+ Then, copy the following base scatter-chart code into a new file in that folder.
+
+
+
+
+
+
+ Now, Let's add the chart component to your project.
+
+ These Components are required by the chart component to render the chart. Make a folder called `ui` inside the `evilcharts` folder and paste the code there.
+
+ Below is main chart component.
+
+
+
+
+
+
+ Now, We need to add sub components.
+
+ Create a file called `tooltip.tsx` inside the `evilcharts/ui` folder and paste the code there.
+
+
+
+
+
+ Now, create another file called `legend.tsx` inside the `evilcharts/ui` folder and paste the code there.
+
+
+
+
+
+ Finally, create last file called `dot.tsx` inside the `evilcharts/ui` folder and paste the code there.
+
+
+
+
+
+
+
+
+
+## Usage
+
+The scatter chart is composible. `` is the container, and you compose only the parts you need — ``, ``, ``, `