
Recharts از همون اول چارتهای کارکردنی میده، ولی ظاهر پیشفرضش هیچ شباهتی به بقیهی سایت طراحیشده با Tailwind نداره — فونتهای متفاوت، رنگهای hex هاردکد، یه tooltip که با هرچی دورشه در تضاده. طبیعیکردنش با سیستم طراحی عمدتاً سهتا کار میخواد: درست Client Component کردنش، وصلکردن رنگهاش به تم Tailwind/CSS variable بهجای hex خام، و جایگزینکردن tooltip و legend پیشفرض با markup خودت.
۱. مجبوره Client Component باشه
Recharts سایز container رو اندازه میگیره و SVG رو با API های مرورگر رندر میکنه، پس هر کامپوننتی که یه چارت رندر میکنه به "use client" نیاز داره — ولی معنیش این نیست که کل صفحه هم باید همینطور باشه. داده رو توی یه Server Component والد fetch کن و بهشکل prop پاسش بده.
// Server Component — داده رو fetch میکنه، سمت سرور میمونه
import { SkillsChart } from "./skills-chart";
export default async function SkillsSection() {
const skills = await skillRepository.findAllWithLevels();
return <SkillsChart data={skills} />; // فقط همین برگ به "use client" نیاز داره
}۲. تمدهی با CSS variable بهجای hex خام
کامپوننتهای Recharts هر مقدار CSS معتبری رو بهعنوان stroke/fill قبول میکنن — از جمله var(--some-token). خوندن رنگها مستقیم از تم Tailwind سایت یعنی چارت خودش توی dark mode دوباره تم میگیره، بدون نیاز به یه نگاشت رنگ جدا برای روشن/تاریک که دستی نگهداری بشه.
// globals.css (همون توکنهای طراحی که همهجای دیگه استفاده میشن رو تعریف میکنه)
:root {
--chart-1: oklch(0.65 0.22 260);
--chart-2: oklch(0.7 0.18 160);
--chart-grid: oklch(0.9 0 0);
--chart-text: oklch(0.45 0 0);
}
.dark {
--chart-1: oklch(0.75 0.2 260);
--chart-2: oklch(0.78 0.16 160);
--chart-grid: oklch(0.3 0 0);
--chart-text: oklch(0.7 0 0);
}"use client";
import {
ResponsiveContainer,
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
} from "recharts";
export function SkillsChart({ data }: { data: { name: string; level: number }[] }) {
return (
<ResponsiveContainer width="100%" height={320}>
<BarChart data={data}>
<CartesianGrid strokeDasharray="3 3" stroke="var(--chart-grid)" />
<XAxis dataKey="name" stroke="var(--chart-text)" fontSize={12} tickLine={false} />
<YAxis stroke="var(--chart-text)" fontSize={12} tickLine={false} />
<Tooltip content={<ChartTooltip />} cursor={{ fill: "var(--chart-grid)", opacity: 0.3 }} />
<Bar dataKey="level" fill="var(--chart-1)" radius={[6, 6, 0, 0]} />
</BarChart>
</ResponsiveContainer>
);
}به ResponsiveContainer یه height صریح پیکسلی بده (یه height درصدی تنها ممکنه داخل یه والد flex/grid بهشکل ۰px رندر بشه، چون Recharts نسبت به ارتفاع resolved-شدهی والد اندازه میگیره) — این رایجترین باگ «چارتم نمایش داده نمیشه»ست.
۳. یه tooltip که واقعاً با طراحی هماهنگه
tooltip پیشفرض یه جعبهی سفید ساده با inline styleه. پاسدادن کامپوننت خودت به content یه المان معمولیِ استایلدادهشده با Tailwind بهت میده بهجاش.
function ChartTooltip({ active, payload, label }: any) {
if (!active || !payload?.length) return null;
return (
<div className="rounded-lg border bg-popover px-3 py-2 text-sm shadow-md">
<p className="font-medium text-popover-foreground">{label}</p>
{payload.map((entry: any) => (
<p key={entry.dataKey} className="text-muted-foreground">
{entry.name}: <span className="text-foreground">{entry.value}</span>
</p>
))}
</div>
);
}۴. چارت چندسری و یه legend سفارشی
<LineChart data={monthlyViews}>
<Line type="monotone" dataKey="en" stroke="var(--chart-1)" strokeWidth={2} dot={false} />
<Line type="monotone" dataKey="fa" stroke="var(--chart-2)" strokeWidth={2} dot={false} />
<Legend content={<ChartLegend />} />
</LineChart>function ChartLegend({ payload }: any) {
return (
<div className="mt-3 flex justify-center gap-4 text-sm">
{payload.map((entry: any) => (
<span key={entry.value} className="flex items-center gap-1.5">
<span className="size-2.5 rounded-full" style={{ background: entry.color }} />
{entry.value}
</span>
))}
</div>
);
}۵. RTL و لوکیل فارسی این سایت
Recharts برای چیدمان RTL خودکار flip نمیشه — ترتیب محوری که توی انگلیسی طبیعی خونده میشه، ممکنه توی فارسی برعکس خونده بشه. بهجای اینکه بخوای خودِ SVG رو آینه کنی، وقتی لوکیل فعال فارسیه ترتیب داده رو برعکس کن (یا روی محور reversed ست کن).
const locale = useLocale(); // next-intl
const chartData = locale === "fa" ? [...data].reverse() : data;چکلیست
کامپوننت چارت یه برگ کوچیک Client Componentه؛ گرفتن داده توی یه Server Component والد میمونه.
رنگها از CSS variable های وصلشده به تم Tailwind خونده میشن، نه hex هاردکد — پس dark mode به هیچ منطق اضافهی مخصوص چارت نیاز نداره.
ResponsiveContainer یه height پیکسلی صریح داره، نه فقط width="100%".
Tooltip و legend با markup واقعی Tailwind جایگزین شدن، نه نسخههای پیشفرض inline-styled خودِ Recharts.
ترتیب داده برای لوکیلهای RTL که جهت محور واقعاً اهمیت داره برعکس شده.
مطالب بیشتر

احرازهویت با better-auth در Next.js: یه راهاندازی دستاول
راهاندازی دقیق پشت لاگین ادمین همین سایت: کانفیگ سرور، route handler catch-all در Next.js، کلاینت، و محافظت دولایهای middleware + layout که واقعاً /admin رو امن میکنه.

راهاندازی Tiptap در Next.js: پنل ادمین قابلویرایش، رندر عمومی فقطخواندنی
راهاندازی دقیق Tiptap پشت هر پست این سایت: یه لیست extension مشترک برای ادیتور و generateHTML()، ذخیرهی JSON توی Postgres، بلاکهای کد با syntax highlighting، و عکسهای آپلودشده (نه base64).