Skip to content

feat: support SVG renderer in ECharts charts - #38

Open
legions-developer wants to merge 2 commits into
mainfrom
codex/echarts-svg-renderer
Open

feat: support SVG renderer in ECharts charts#38
legions-developer wants to merge 2 commits into
mainfrom
codex/echarts-svg-renderer

Conversation

@legions-developer

@legions-developer legions-developer commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a shared Canvas/SVG renderer API to all eight ECharts chart roots, with Canvas remaining the default
  • safely recreate chart instances when the renderer changes and reset renderer-owned interaction state
  • add SVG renderer examples, documentation previews, and generated registry artifacts for every ECharts chart type
  • highlight the renderer="svg" line in every example's code preview
  • document renderer-specific texture behavior for area, bar, and composed charts

Validation

  • bunx eslint on the touched TypeScript and TSX files
  • bunx tsc --noEmit --incremental false
  • bun run registry:fresh (279 registry items)
  • bun run build (89 static pages)
  • browser QA across all eight SVG previews: one SVG surface, zero canvases, and no runtime errors
  • generated install payload audit: all eight SVG examples include the code-highlight marker

@vercel

vercel Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
evilcharts Ready Ready Preview Aug 13, 2026 10:26pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ba1c4aa-3684-45f9-89fb-94e23f11a5d2

📥 Commits

Reviewing files that changed from the base of the PR and between c52ed09 and d31f3c6.

📒 Files selected for processing (8)
  • src/registry/examples/echarts/ex-svg-renderer-echarts-area-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-bar-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-composed-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-line-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-pie-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-radar-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-radial-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-sankey-chart.tsx
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/registry/examples/echarts/ex-svg-renderer-echarts-sankey-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-radar-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-radial-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-pie-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-area-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-line-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-bar-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-composed-chart.tsx

📝 Walkthrough

Walkthrough

ECharts now supports Canvas and SVG renderers through shared configuration. Eight chart components accept a renderer prop, SVG examples are registered, and documentation describes renderer selection and behavior.

Changes

ECharts SVG renderer support

Layer / File(s) Summary
Shared renderer foundation
src/registry/ui/echarts-chart.tsx
Registers Canvas and SVG renderers and exports renderer identifiers, the renderer type, and the Canvas default.
Chart renderer integration
src/registry/charts/echarts-*.tsx
Adds the renderer prop to eight chart components. Renderer changes recreate chart instances and refresh related effects and state.
SVG chart examples
src/registry/examples/echarts/ex-svg-renderer-*
Adds SVG examples for area, line, bar, composed, radar, pie, radial, and Sankey charts.
Example registry wiring
registry.json, src/registry/__index__.tsx, src/registry/registry-example.ts
Registers and lazy-loads the eight SVG examples.
Renderer documentation
src/content/docs/echarts/*, src/content/docs/index.mdx, src/globals/constants/providers.ts, AGENTS.md
Documents Canvas as the default, SVG through renderer="svg", and renderer-specific chart behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Mergeability Score: 🟡 Moderate · up to d31f3

The PR is not merge-ready until the reported lint errors in the changed chart components are fixed or explicitly accepted; otherwise the renderer update carries a concrete validation and maintenance risk. The remaining radar documentation typo is minor and non-blocking.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely summarizes the primary change: adding SVG renderer support to ECharts charts.
Description check ✅ Passed The description directly explains the renderer API, state handling, examples, documentation, generated artifacts, and validation for this changeset.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/echarts-svg-renderer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2770f1ac-184c-43a3-bc8c-4ebec9e6e657

📥 Commits

Reviewing files that changed from the base of the PR and between 53d2b32 and c52ed09.

📒 Files selected for processing (34)
  • AGENTS.md
  • registry.json
  • src/content/docs/echarts/area-chart/static.mdx
  • src/content/docs/echarts/bar-chart/static.mdx
  • src/content/docs/echarts/composed-chart/static.mdx
  • src/content/docs/echarts/installation.mdx
  • src/content/docs/echarts/line-chart/static.mdx
  • src/content/docs/echarts/pie-chart/static.mdx
  • src/content/docs/echarts/radar-chart/static.mdx
  • src/content/docs/echarts/radial-chart/static.mdx
  • src/content/docs/echarts/sankey-chart/static.mdx
  • src/content/docs/echarts/ui/brush.mdx
  • src/content/docs/index.mdx
  • src/globals/constants/providers.ts
  • src/registry/__index__.tsx
  • src/registry/charts/echarts-area-chart.tsx
  • src/registry/charts/echarts-bar-chart.tsx
  • src/registry/charts/echarts-composed-chart.tsx
  • src/registry/charts/echarts-line-chart.tsx
  • src/registry/charts/echarts-pie-chart.tsx
  • src/registry/charts/echarts-radar-chart.tsx
  • src/registry/charts/echarts-radial-chart.tsx
  • src/registry/charts/echarts-sankey-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-area-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-bar-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-composed-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-line-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-pie-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-radar-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-radial-chart.tsx
  • src/registry/examples/echarts/ex-svg-renderer-echarts-sankey-chart.tsx
  • src/registry/registry-example.ts
  • src/registry/registry-ui.ts
  • src/registry/ui/echarts-chart.tsx

## API Reference

The radar chart is a root container plus composible parts. On canvas each part is declarative config the root compiles, but the API mirrors the Recharts twin. Each is documented below.
The radar chart is a root container plus composible parts. Regardless of renderer, each part is declarative config the root compiles, but the API mirrors the Recharts twin. Each is documented below.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the API overview spelling.

Line 219 uses composible. Replace it with composable.

raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, [live, isLoading, loadingPoints, loadingData]);
}, [renderer, live, isLoading, loadingPoints, loadingData]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

for f in \
  src/registry/charts/echarts-area-chart.tsx \
  src/registry/charts/echarts-bar-chart.tsx \
  src/registry/charts/echarts-composed-chart.tsx \
  src/registry/charts/echarts-line-chart.tsx \
  src/registry/charts/echarts-radar-chart.tsx
do
  echo "===== $f ====="
  rg -n -C 14 'const live|live\s*=|useRef|useEffect|loadingPoints|loadingBars|loadingLineData|loadingData|renderer' "$f" | tail -n 220
done

Repository: legions-developer/evilcharts

Length of output: 45913


🏁 Script executed:

#!/bin/bash
set -eu

for f in \
  src/registry/charts/echarts-area-chart.tsx \
  src/registry/charts/echarts-bar-chart.tsx \
  src/registry/charts/echarts-composed-chart.tsx \
  src/registry/charts/echarts-line-chart.tsx \
  src/registry/charts/echarts-radar-chart.tsx
do
  echo "===== $f: ref declarations and nearby dependencies ====="
  rg -n -C 8 'useRef<|useRef\(|\.current\)|const live|let live|react-hooks/refs|exhaustive-deps' "$f" | head -n 180
done

echo "===== lint configuration and React Hooks versions ====="
git ls-files | rg '(^|/)(package\.json|eslint[^/]*|pnpm-lock\.yaml|yarn\.lock|package-lock\.json|bun\.lockb?)$' | sort
rg -n -C 3 'eslint-plugin-react-hooks|react-hooks|eslintConfig|flatConfig|recommended' \
  package.json .eslintrc* eslint.config.* 2>/dev/null || true

Repository: legions-developer/evilcharts

Length of output: 10508


🏁 Script executed:

#!/bin/bash
set -eu

for f in \
  src/registry/charts/echarts-area-chart.tsx \
  src/registry/charts/echarts-bar-chart.tsx \
  src/registry/charts/echarts-composed-chart.tsx \
  src/registry/charts/echarts-line-chart.tsx \
  src/registry/charts/echarts-radar-chart.tsx
do
  echo "===== $f: complete live initialization ====="
  start=$(rg -n 'const live = useRef<LiveState>' "$f" | cut -d: -f1)
  end=$((start + 145))
  sed -n "${start},${end}p" "$f" | nl -ba -v "$start"
done

echo "===== package and lint configuration ====="
cat package.json
cat eslint.config.mjs

Repository: legions-developer/evilcharts

Length of output: 292


🏁 Script executed:

#!/bin/bash
set -eu

for f in \
  src/registry/charts/echarts-area-chart.tsx \
  src/registry/charts/echarts-bar-chart.tsx \
  src/registry/charts/echarts-composed-chart.tsx \
  src/registry/charts/echarts-line-chart.tsx \
  src/registry/charts/echarts-radar-chart.tsx
do
  echo "===== $f: complete live initialization ====="
  start=$(rg -n 'const live = useRef<LiveState>' "$f" | cut -d: -f1)
  end=$((start + 145))
  sed -n "${start},${end}p" "$f"
done

echo "===== package and lint configuration ====="
cat package.json
cat eslint.config.mjs

Repository: legions-developer/evilcharts

Length of output: 28569


🌐 Web query:

React eslint-plugin-react-hooks react-hooks/refs rule useRef current during render dependency array official documentation

💡 Result:

According to official React documentation and the eslint-plugin-react-hooks rules, you should not include ref.current in a dependency array [1][2]. There are several authoritative technical reasons for this, centered on how React manages state and effects [3][2]. 1. Why you should not use ref.current as a dependency Mutable values like ref.current are not "reactive" [2]. In React, dependency arrays are intended to track values that, when changed, should trigger a re-render or a re-synchronization of an effect [4][2]. Because changing ref.current does not trigger a re-render of your component, React has no way of knowing when the value has changed [3][2]. Consequently, even if you include it in a dependency array, the effect will not reliably re-run when the ref is mutated [1][2]. 2. Reading or writing refs during render Official React documentation explicitly warns against reading or writing ref.current during the rendering phase [5][3]. Doing so makes your component's behavior unpredictable because React does not track changes to refs [3]. The only common exception is using a ref for lazy initialization during the first render (e.g., if (!ref.current) ref.current = new Thing) [5][3]. Generally, you should only access refs inside event handlers or Effects, which run after the commit phase [5][6]. 3. Proper alternatives If you need an effect to run in response to a value change, that value must be part of React's state management system (e.g., useState or useReducer) [1][7]. Using state ensures that updates trigger a re-render, making the data reactive and correctly observable by your effects [1][2]. If your goal is to be notified when a DOM node is attached or detached, you should use a callback ref instead of useRef [8][7]. In summary, the exhaustive-deps linting rule correctly flags ref.current because it is a mutable property that does not participate in the React data flow, and using it as a dependency creates a false expectation that your effect will respond to its changes [1][8][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

echo "===== lockfile entries for React Hooks lint packages ====="
rg -n -C 2 'eslint-plugin-react-hooks|react-hooks' bun.lock || true

echo "===== all render-time live accesses in the five files ====="
for f in \
  src/registry/charts/echarts-area-chart.tsx \
  src/registry/charts/echarts-bar-chart.tsx \
  src/registry/charts/echarts-composed-chart.tsx \
  src/registry/charts/echarts-line-chart.tsx \
  src/registry/charts/echarts-radar-chart.tsx
do
  echo "--- $f ---"
  rg -n '(^|[^[:alnum:]_])live(\.|[,)])|useRef<LiveState>|\.current' "$f"
done

Repository: legions-developer/evilcharts

Length of output: 24571


🌐 Web query:

site:github.com/facebook/react eslint-plugin-react-hooks "Cannot access refs during render" "react-hooks/refs"

💡 Result:

The ESLint error "Cannot access refs during render" (associated with the rule react-hooks/refs in eslint-plugin-react-hooks) occurs because reading or writing the .current property of a ref directly inside the body of a React component can lead to stale UI states and unpredictable behavior [1][2][3]. React refs are intended to hold mutable values that persist across renders without triggering re-renders [1][4][3]. Because the render function must be pure and predictable, accessing a ref value during render violates these principles, as the value of ref.current can change independently of React's state management [1][3]. Key points regarding this rule: 1. When it is acceptable: Refs are safe to access outside of the render phase, specifically within event handlers (e.g., onClick, onChange) and effects (useEffect, useLayoutEffect) [1][3]. 2. Why it happens: The rule identifies when you are reading or writing to ref.current during the component execution phase [2][5]. This is enforced to ensure that your component's render output remains consistent and does not depend on mutable values that React cannot track [1][3]. 3. Troubleshooting false positives: If you are seeing this error in scenarios where you believe ref access is safe (e.g., passing a ref object through to another component, or using refs inside asynchronous browser callbacks like IntersectionObserver), this may be a known issue with the plugin's analysis logic [2][6][7][8]. - Ref Forwarding: Recent updates to the compiler and linting rules have addressed false positives when simply passing a ref prop down to a child component, provided you are not reading the .current value itself during render [8]. - Async Callbacks: If you use refs inside callbacks that are executed by the browser asynchronously (not during the render phase), and the linter incorrectly flags them, ensure you are using the latest version of eslint-plugin-react-hooks, as ongoing fixes (such as those for IntersectionObserver) are regularly released to improve detection accuracy [7]. If you are encountering a legitimate error, the standard fix is to move the logic that reads or writes the ref value into a useEffect hook or an event handler [1][3]. If you believe the error is a false positive, you can check the React repository issues for similar patterns or temporarily suppress the rule for specific lines using // eslint-disable-next-line react-hooks/refs after verifying that your usage does not actually occur during render [1][6].

Citations:


🌐 Web query:

site:github.com/facebook/react packages/eslint-plugin-react-hooks refs rule "Cannot access ref value during render"

💡 Result:

The eslint-plugin-react-hooks rule react-hooks/refs is a validation check designed to enforce the architectural principle that React refs (the .current property) should not be read or written to during the render phase [1][2]. The core reason for this rule is that the render function should be pure and predictable [3][4]. Refs are mutable, and accessing or modifying them during render can cause side effects or lead to inconsistent component behavior, as the render phase may be interrupted, restarted, or run multiple times by React [1][3]. Key points regarding this rule: - Purpose: The rule specifically targets the current property of a ref [1][5]. According to React's design, refs are intended for values that do not affect the output of a component (e.g., storing a DOM element reference or a stable ID that persists across renders) [2]. - Exceptions: The only widely accepted use case for accessing a ref during render is the lazy initialization pattern, where a ref is used to lazily initialize and store an expensive object that is only set once [3][4]. - False Positives: As of recent versions (specifically since v7.0.0 of the plugin), many users have reported false positives [2][6][7]. These occur when the analysis tool incorrectly flags safe code—such as passing a ref to a function or storing refs within objects—as an "unsafe access" [2][6][7]. Development on the React compiler and the associated ESLint rules is ongoing, and these issues are actively tracked in the React repository [5][7]. If you are encountering this error and believe your code is safe, it may be due to a known false positive in the current version of the plugin [2][7]. Developers often choose to either suppress the warning if they are certain of the pattern's safety or refactor code to ensure refs are only accessed within useEffect or event handlers, which are the idiomatic locations for ref interaction [8][2].

Citations:


Refactor live into a ref object before merge.

All five files read useRef(...).current during render. The react-hooks/refs rule flags this initializer, so removing live from the loading-effect dependencies alone will not fix the lint errors. Keep the ref object stable, access .current only in effects and callbacks, and move render-time mutations such as live.handlers = ... out of render.

🧰 Tools
🪛 ESLint

[error] 2287-2287: Error: Cannot access refs during render

React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the current property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).

/home/jailuser/git/src/registry/charts/echarts-area-chart.tsx:2287:6
2285 | raf = requestAnimationFrame(tick);
2286 | return () => cancelAnimationFrame(raf);

2287 | }, [renderer, live, isLoading, loadingPoints, loadingData]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render
2288 |
2289 | // ── Legend overlay position ──────────────────────────────────────────────────
2290 | // Insets match the Recharts legend's breathing room inside the plot frame.

(react-hooks/refs)

📍 Affects 5 files
  • src/registry/charts/echarts-area-chart.tsx#L2287-L2287 (this comment)
  • src/registry/charts/echarts-bar-chart.tsx#L2139-L2139
  • src/registry/charts/echarts-composed-chart.tsx#L1973-L1973
  • src/registry/charts/echarts-line-chart.tsx#L2040-L2040
  • src/registry/charts/echarts-radar-chart.tsx#L1184-L1184

Source: Linters/SAST tools

raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, [live, isLoading, loadingData]);
}, [live, isLoading, loadingData, renderer]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- candidate file outline ---'
ast-grep outline src/registry/charts/echarts-radial-chart.tsx

printf '%s\n' '--- relevant source ---'
sed -n '980,1210p' src/registry/charts/echarts-radial-chart.tsx

printf '%s\n' '--- live declarations and effect references ---'
rg -n -C 4 '\blive\b|useEffect\(' src/registry/charts/echarts-radial-chart.tsx

printf '%s\n' '--- lint configuration and scripts ---'
rg -n -C 3 'eslint|react-hooks|Cannot access refs during render|lint' package.json .eslintrc* eslint.config.* 2>/dev/null || true

Repository: legions-developer/evilcharts

Length of output: 23841


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- live state declaration and hooks ---'
sed -n '850,1040p' src/registry/charts/echarts-radial-chart.tsx

printf '%s\n' '--- imports and React type versions ---'
sed -n '1,75p' src/registry/charts/echarts-radial-chart.tsx
rg -n '"react"|"eslint-plugin-react-hooks"|eslint-config-next' package.json bun.lockb bun.lock package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null || true

printf '%s\n' '--- all useRef declarations and dependency arrays ---'
rg -n -C 2 'useRef|^\s*\],?$|^\s*\}, \[' src/registry/charts/echarts-radial-chart.tsx

printf '%s\n' '--- installed lint tooling, if present (no project code execution) ---'
if [ -x node_modules/.bin/eslint ]; then
  node_modules/.bin/eslint --version
  node_modules/.bin/eslint --print-config src/registry/charts/echarts-radial-chart.tsx \
    | rg -n -C 2 'react-hooks/(exhaustive-deps|refs)|Cannot access refs'
else
  echo 'node_modules/.bin/eslint is unavailable'
fi

Repository: legions-developer/evilcharts

Length of output: 49447


🏁 Script executed:

#!/bin/bash
set -u

node_modules/.bin/eslint src/registry/charts/echarts-radial-chart.tsx
status=$?
printf '\nESLint exit status: %s\n' "$status"
exit "$status"

Repository: legions-developer/evilcharts

Length of output: 9735


Remove live from both effect dependency arrays and avoid reading .current during render.

live is a stable useRef(...).current value, not a reactive dependency. The react-hooks/refs rule reports the sync effect at line 1137 and the shimmer effect at line 1192. It also reports the .current access at line 915, so removing only the dependency at line 1192 does not resolve lint failures.

🧰 Tools
🪛 ESLint

[error] 1192-1192: Error: Cannot access refs during render

React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the current property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef).

/home/jailuser/git/src/registry/charts/echarts-radial-chart.tsx:1192:6
1190 | raf = requestAnimationFrame(tick);
1191 | return () => cancelAnimationFrame(raf);

1192 | }, [live, isLoading, loadingData, renderer]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render
1193 |
1194 | // ── Legend overlay (HTML) ─────────────────────────────────────────────────────
1195 | // One entry per ring. Unlike the area twin's absolutely-positioned legend, the

(react-hooks/refs)

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant