Skip to content

feat: add recharts library and implement various chart components wit… - #61

Merged
Aunshon merged 4 commits into
mainfrom
add/charts
Mar 4, 2026
Merged

feat: add recharts library and implement various chart components wit…#61
Aunshon merged 4 commits into
mainfrom
add/charts

Conversation

@Aunshon

@Aunshon Aunshon commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

…h stories (#60)

  • Added recharts dependency to package.json
  • Created Chart component with ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, and ChartLegendContent
  • Implemented multiple chart types (Area, Bar, Line, Pie, Radar, Radial) in Chart.stories.tsx
  • Updated Card component styles for better layout consistency
  • Exported new chart components in index.ts files

Summary by CodeRabbit

  • New Features

    • Added charting components with configurable legends, tooltips and theming for area, bar, line, pie, radar and radial charts.
    • Added RichTextEditor component.
  • Documentation / Examples

    • Added comprehensive Storybook examples showcasing all chart variants and usage patterns.
  • Chores

    • Added recharts dependency and updated public UI exports.
    • Minor UI/story refinements and import cleanup.

…h stories (#60)

- Added recharts dependency to package.json
- Created Chart component with ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, and ChartLegendContent
- Implemented multiple chart types (Area, Bar, Line, Pie, Radar, Radial) in Chart.stories.tsx
- Updated Card component styles for better layout consistency
- Exported new chart components in index.ts files
@Aunshon Aunshon self-assigned this Mar 4, 2026
@coderabbitai

coderabbitai Bot commented Mar 4, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds Recharts as a dependency, a new charting UI module (ChartContainer, ChartStyle, tooltip/legend helpers, context), Storybook stories demonstrating many chart types, and public exports for chart components; minor UI and story tweaks elsewhere.

Changes

Cohort / File(s) Summary
Dependencies
package.json
Added recharts (^2.15.4) to dependencies.
Chart module (new)
src/components/ui/chart.tsx
New charting implementation: ChartContext and useChart hook, ChartContainer wrapping Recharts, ChartStyle CSS-vars theming, ChartTooltipContent/ChartLegendContent, helper getPayloadConfigFromPayload, types and exports.
Stories / Examples
src/components/ui/Chart.stories.tsx
New comprehensive Storybook file with many preconfigured chart stories (Area, Bar, Line, Pie, Radar, Radial, AllCharts) using Recharts and shared sample data/config.
Public exports / index
src/components/ui/index.ts, src/index.ts
Re-exported chart components/types from UI barrel; added chart exports to root index; added export * as recharts and RichTextEditor exports.
UI component formatting
src/components/ui/card.tsx
Minor className construction/formatting changes for Card components; no API surface changes.
Misc small edits
src/components/license.tsx, src/components/wordpress/Layout.stories.tsx
Removed unused Loader import; adjusted Layout stories (escaped code strings, introduced internal ActiveItemTrackingExample).

Sequence Diagram

sequenceDiagram
    participant App
    participant ChartContainer
    participant ChartContext
    participant ChartStyle
    participant Recharts
    participant Tooltip as ChartTooltipContent
    participant Legend as ChartLegendContent

    App->>ChartContainer: render with ChartConfig and children
    ChartContainer->>ChartContext: provide config
    ChartContainer->>ChartStyle: generate scoped CSS vars (id, config)
    ChartStyle-->>ChartContainer: inject theme CSS
    ChartContainer->>Recharts: wrap ResponsiveContainer and chart primitives
    App->>Recharts: user interaction (hover/click)
    Recharts->>Tooltip: request tooltip (payload)
    Tooltip->>ChartContext: useChart() to resolve labels/icons
    Tooltip->>Tooltip: call getPayloadConfigFromPayload(payload, key)
    Tooltip-->>Recharts: render formatted tooltip
    Recharts->>Legend: request legend payload
    Legend->>ChartContext: useChart() to resolve legend entries
    Legend-->>Recharts: render custom legend
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • mrabbani

Poem

🐰 I hopped the repo, found new charts bright,
Lines and pies lined up just right.
Tooltips whisper, legends beam,
CSS-vars stitch color and theme.
Hop—data dances in the night! 📈✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add recharts library and implement various chart components wit…' is truncated but clearly summarizes the main change: adding recharts and implementing chart components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add/charts

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 and usage tips.

@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: 4

🧹 Nitpick comments (1)
src/index.ts (1)

237-241: Expose ChartConfig at the package root for TS consumers.

ChartConfig is exported in src/components/ui/index.ts but not re-exported here, so root consumers lose the type unless they deep-import.

💡 Suggested diff
     // Rich Text Editor
     RichTextEditor,
     // Types
     type RichTextEditorProps,
+    type ChartConfig,
     type CircularProgressProps,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/index.ts` around lines 237 - 241, The package root index is missing a
re-export of the ChartConfig type (currently exported from the UI barrel), so
add a type-only re-export for ChartConfig alongside the existing exports (where
RichTextEditor and RichTextEditorProps are exported) so TypeScript consumers can
import ChartConfig from the package root; re-export the ChartConfig symbol from
the UI barrel using a type export.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/ui/chart.tsx`:
- Around line 235-239: The tooltip currently hides zero values because it uses a
truthy check on item.value; change the conditional around the span that renders
{item.value.toLocaleString()} to explicitly check for null/undefined (e.g.,
item.value !== null && item.value !== undefined) so that 0 is rendered; update
the conditional near the span inside the tooltip rendering (the block that
references item.value and the className "text-foreground font-mono font-medium
tabular-nums") to use this explicit existence check.
- Around line 301-302: The legend rendering currently shows only
itemConfig?.label which leaves the legend blank when config lookup fails; update
the JSX in the Chart component where {itemConfig?.label} is rendered to provide
a fallback (e.g., use the series key/id or a humanized version like itemKey ||
item.id or a formatted fallback string) by replacing the single-access with a
nullish-coalescing or logical-or fallback that uses the unique identifier
(itemKey, item.id, or similar) so the legend always displays meaningful text
when itemConfig is undefined.
- Around line 35-59: ChartContainer currently reads id from props but never
applies it to the root DOM node; add id={id} to the root <div> in the
ChartContainer component (keep the existing data-chart={chartId} attribute) so
the id prop passed into ChartContainer is forwarded to the root element and
available for anchors/tests; locate the ChartContainer function and add id={id}
on the div that currently has data-slot="chart" and data-chart={chartId}.

---

Nitpick comments:
In `@src/index.ts`:
- Around line 237-241: The package root index is missing a re-export of the
ChartConfig type (currently exported from the UI barrel), so add a type-only
re-export for ChartConfig alongside the existing exports (where RichTextEditor
and RichTextEditorProps are exported) so TypeScript consumers can import
ChartConfig from the package root; re-export the ChartConfig symbol from the UI
barrel using a type export.

ℹ️ Review info
Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 78ecb85d-0de2-4c41-8dd2-768aab97efb4

📥 Commits

Reviewing files that changed from the base of the PR and between 19174dc and 4e58953.

📒 Files selected for processing (6)
  • package.json
  • src/components/ui/Chart.stories.tsx
  • src/components/ui/card.tsx
  • src/components/ui/chart.tsx
  • src/components/ui/index.ts
  • src/index.ts

Comment on lines +35 to +59
function ChartContainer({
id,
className,
children,
config,
...props
}: React.ComponentProps<"div"> & {
config: ChartConfig
children: React.ComponentProps<
typeof RechartsPrimitive.ResponsiveContainer
>["children"]
}) {
const uniqueId = React.useId()
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`

return (
<ChartContext.Provider value={{ config }}>
<div
data-slot="chart"
data-chart={chartId}
className={cn(
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
className
)}
{...props}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Forward the id prop to the root element.

Line 36 reads id from ComponentProps<"div">, but it is not applied to the DOM node. That breaks expected anchor/test selectors.

💡 Suggested diff
       <div
+        id={id}
         data-slot="chart"
         data-chart={chartId}
         className={cn(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/chart.tsx` around lines 35 - 59, ChartContainer currently
reads id from props but never applies it to the root DOM node; add id={id} to
the root <div> in the ChartContainer component (keep the existing
data-chart={chartId} attribute) so the id prop passed into ChartContainer is
forwarded to the root element and available for anchors/tests; locate the
ChartContainer function and add id={id} on the div that currently has
data-slot="chart" and data-chart={chartId}.

Comment on lines +80 to +99
<style
dangerouslySetInnerHTML={{
__html: Object.entries(THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color
return color ? ` --color-${key}: ${color};` : null
})
.join("\n")}
}
`
)
.join("\n"),
}}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Harden dynamic style generation; avoid raw dangerouslySetInnerHTML injection.

Line 81 interpolates dynamic id/keys/colors directly into HTML/CSS text. This is an avoidable injection surface and can also break selectors with malformed values.

🔒 Suggested diff
 const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
+  const safeChartId = CSS.escape(id)
+  const toVarName = (value: string) => value.replace(/[^a-zA-Z0-9_-]/g, "")
+  const toCssValue = (value: string) => value.replace(/[;"{}<>]/g, "")
+
   const colorConfig = Object.entries(config).filter(
     ([, config]) => config.theme || config.color
   )

   if (!colorConfig.length) {
     return null
   }

+  const cssText = Object.entries(THEMES)
+    .map(
+      ([theme, prefix]) => `
+${prefix} [data-chart="${safeChartId}"] {
+${colorConfig
+  .map(([key, itemConfig]) => {
+    const color =
+      itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
+      itemConfig.color
+    return color
+      ? `  --color-${toVarName(key)}: ${toCssValue(String(color))};`
+      : null
+  })
+  .filter(Boolean)
+  .join("\n")}
+}
+`
+    )
+    .join("\n")
+
-  return (
-    <style
-      dangerouslySetInnerHTML={{
-        __html: Object.entries(THEMES)
-          .map(
-            ([theme, prefix]) => `
-${prefix} [data-chart=${id}] {
-${colorConfig
-  .map(([key, itemConfig]) => {
-    const color =
-      itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
-      itemConfig.color
-    return color ? `  --color-${key}: ${color};` : null
-  })
-  .join("\n")}
-}
-`
-          )
-          .join("\n"),
-      }}
-    />
-  )
+  return <style>{cssText}</style>
 }
#!/bin/bash
# Verify raw dynamic HTML/CSS interpolation points in chart style generation.
sed -n '70,110p' src/components/ui/chart.tsx
rg -n 'dangerouslySetInnerHTML|data-chart=\\$\\{id\\}|--color-\\$\\{key\\}' src/components/ui/chart.tsx
rg -n 'CSS\\.escape|toVarName|toCssValue' src/components/ui/chart.tsx
🧰 Tools
🪛 ast-grep (0.41.0)

[warning] 80-80: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.4.4)

[error] 81-81: Avoid passing content using the dangerouslySetInnerHTML prop.

(lint/security/noDangerouslySetInnerHtml)

Comment on lines +235 to +239
{item.value && (
<span className="text-foreground font-mono font-medium tabular-nums">
{item.value.toLocaleString()}
</span>
)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Render zero values in tooltip output.

Line 235 uses a truthy check, so 0 values are hidden.

💡 Suggested diff
-                      {item.value && (
+                      {item.value !== undefined && item.value !== null && (
                         <span className="text-foreground font-mono font-medium tabular-nums">
                           {item.value.toLocaleString()}
                         </span>
                       )}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{item.value && (
<span className="text-foreground font-mono font-medium tabular-nums">
{item.value.toLocaleString()}
</span>
)}
{item.value !== undefined && item.value !== null && (
<span className="text-foreground font-mono font-medium tabular-nums">
{item.value.toLocaleString()}
</span>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/chart.tsx` around lines 235 - 239, The tooltip currently
hides zero values because it uses a truthy check on item.value; change the
conditional around the span that renders {item.value.toLocaleString()} to
explicitly check for null/undefined (e.g., item.value !== null && item.value !==
undefined) so that 0 is rendered; update the conditional near the span inside
the tooltip rendering (the block that references item.value and the className
"text-foreground font-mono font-medium tabular-nums") to use this explicit
existence check.

Comment on lines +301 to +302
{itemConfig?.label}
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a legend label fallback when config lookup misses.

Line 301 renders only itemConfig?.label; if config resolution fails, legend text is blank.

💡 Suggested diff
-              {itemConfig?.label}
+              {itemConfig?.label ?? item.value}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/chart.tsx` around lines 301 - 302, The legend rendering
currently shows only itemConfig?.label which leaves the legend blank when config
lookup fails; update the JSX in the Chart component where {itemConfig?.label} is
rendered to provide a fallback (e.g., use the series key/id or a humanized
version like itemKey || item.id or a formatted fallback string) by replacing the
single-access with a nullish-coalescing or logical-or fallback that uses the
unique identifier (itemKey, item.id, or similar) so the legend always displays
meaningful text when itemConfig is undefined.

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

🧹 Nitpick comments (2)
src/index.ts (2)

50-51: Export ChartConfig from the root barrel to complete the chart API.

ChartContainer (Line 50) requires a config prop typed as ChartConfig, but src/index.ts does not re-export that type. Root consumers lose an ergonomic way to type chart configs.

Proposed fix
     // Types
+    type ChartConfig,
     type RichTextEditorProps,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/index.ts` around lines 50 - 51, Export the ChartConfig type from the root
barrel so consumers can import it alongside ChartContainer and related
components: add ChartConfig to the exported list in the root index module (the
same place ChartContainer, ChartTooltip, ChartLegend, ChartStyle are exported)
so ChartContainer's config prop is publicly typed; ensure you import ChartConfig
from its defining module and include it in the existing export statement.

329-329: Document the recharts namespace re-export and consider tree-shaking implications.

The export * as recharts from 'recharts' re-export couples your package API directly to upstream recharts surface/versioning. Additionally, namespace re-exports defeat recharts 2.15.4's tree-shaking optimization—bundlers must assume the entire namespace could be used, retaining unused code.

Since you have an internal Chart component that uses recharts, this re-export may be intentional. If so, document it explicitly in your README (e.g., mentioning that consumers can access recharts exports through this package or should import named components directly from recharts). Recommend guiding consumers toward named imports (import { LineChart } from 'recharts') to preserve tree-shaking benefits.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/index.ts` at line 329, The export line export * as recharts from
'recharts' exposes the entire recharts namespace (and can defeat tree-shaking)
and couples your package API to recharts; either remove this namespace re-export
or clearly document the intention: if you need to keep it (because internal
Chart component exposes recharts types/props), add a README note explaining that
consumers can access recharts via this package (and recommend preferred named
imports like import { LineChart } from 'recharts' to preserve tree-shaking) and
mention the specific exported namespace export * as recharts; otherwise delete
that export and update internal uses (e.g., Chart) to import recharts directly
from 'recharts' so consumers are not forced to pull the whole namespace.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/index.ts`:
- Around line 50-51: Export the ChartConfig type from the root barrel so
consumers can import it alongside ChartContainer and related components: add
ChartConfig to the exported list in the root index module (the same place
ChartContainer, ChartTooltip, ChartLegend, ChartStyle are exported) so
ChartContainer's config prop is publicly typed; ensure you import ChartConfig
from its defining module and include it in the existing export statement.
- Line 329: The export line export * as recharts from 'recharts' exposes the
entire recharts namespace (and can defeat tree-shaking) and couples your package
API to recharts; either remove this namespace re-export or clearly document the
intention: if you need to keep it (because internal Chart component exposes
recharts types/props), add a README note explaining that consumers can access
recharts via this package (and recommend preferred named imports like import {
LineChart } from 'recharts' to preserve tree-shaking) and mention the specific
exported namespace export * as recharts; otherwise delete that export and update
internal uses (e.g., Chart) to import recharts directly from 'recharts' so
consumers are not forced to pull the whole namespace.

ℹ️ Review info
Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7c39ad00-ef8c-412d-8e2c-729b8a0f5608

📥 Commits

Reviewing files that changed from the base of the PR and between f803c30 and 0063335.

📒 Files selected for processing (1)
  • src/index.ts

@Aunshon
Aunshon merged commit 982bfad into main Mar 4, 2026
1 check passed
@Aunshon
Aunshon deleted the add/charts branch March 4, 2026 07:27
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