@akhatmirzo/ui

Charts

Charts built on Recharts — ready-made AreaChart, BarChart, LineChart, DonutChart and Sparkline, plus primitives for your own charts.

  • Tushum
  • Xarajat

Installation

Charts live in a separate entry point — @akhatmirzo/ui/charts. They are built on Recharts, which is an optional peer dependency: if you don't use charts, you don't need to install it, and the main @akhatmirzo/ui import never pulls it in.

pnpm add recharts

Import

import { AreaChart, BarChart, LineChart, DonutChart, Sparkline } from '@akhatmirzo/ui/charts';

When to use

  • Change over time — AreaChart or LineChart (monthly revenue, daily visits).
  • Comparing categories — BarChart (regions, products). For long names use orientation="horizontal".
  • Parts of a whole — DonutChart, with no more than 5–6 slices; group the rest into "Other".
  • A small trend — Sparkline in KPI cards and table cells.
  • When exact values matter — show a table instead of, or next to, the chart (see Accessibility).

Ready-made charts

They all share the same props: data is a list of objects, index is the category field (x axis) and series lists the numeric fields to draw. Colors come only from tokens, so charts adapt to dark mode on their own.

AreaChart

The example above. stacked stacks the series on top of each other; curve is monotone (default), linear or step.

BarChart

stacked puts the series into one bar, showing the total and its breakdown together.

  • Onlayn
  • Do'kondan

orientation="horizontal" draws horizontal bars — handy for long names and rankings. The prop is named after what you see (vertical — upright columns) and deliberately differs from Recharts' layout, where layout="vertical" means the opposite (horizontal bars).

LineChart

For comparing several metrics. This one uses curve="linear".

  • Yangi
  • Qaytgan

DonutChart

index is the slice name and value is the value field. The center shows centerLabel and the total (formatted with valueFormat); override it with centerValue or hide it with null.

Jami, so'm7,2 mln
  • Oziq-ovqat
  • Transport
  • Kommunal
  • Ko'ngilochar
  • Boshqalar

Sparkline

A tiny line with no axes, grid or tooltip. If the value is already shown as text next to it, mark it as decorative with aria-hidden; otherwise give it an aria-label.

Tushum

63 100 000 so'm

Qaytarishlar

38 ta

Formatting

valueFormat controls the tooltip and the value axis (default formatNumber: 1 250 000); indexFormat controls the category axis and the tooltip title. Use formatMoney for money; if long values crowd the axis, pass a short form (42,5 mln so'm).

import { formatMoney } from '@akhatmirzo/core';

<BarChart valueFormat={(v) => formatMoney(v)} indexFormat={(d) => d.slice(0, 3)} … />

States

loading shows a Skeleton in place of the chart (aria-busy); empty data shows an EmptyState ("Ma'lumot yo'q"). Pass your own empty state with emptyState and change the texts with labels.

Primitives: build your own chart

When a ready-made chart isn't enough (dual axes, mixed series, custom shapes), compose Recharts directly — the primitives give it the library look:

  • ChartContainer — a responsive wrapper: role="figure" + aria-label (required), description, and config → CSS variables (revenue → var(--chart-revenue)). Set the height with height or className="h-72" (default 280px).
  • ChartTooltip — <Tooltip content={<ChartTooltip format={formatMoney} />} />; takes series names from label in config.
  • ChartLegend — <Legend content={<ChartLegend />} />, or outside a chart with payload.
  • chartColors (5 series colors), axisProps, gridProps, cursorProps, resolveChartColor.

Props

Ready-made charts pass the remaining <div> attributes to the root (className, ref, id...). One of aria-label or title is required — TypeScript enforces it.

Shared (AreaChart, BarChart, LineChart)

PropTypeDefaultDescription
datarequiredreadonly T[]—The data
indexrequiredkeyof T—Category (x axis) field
seriesrequired{ key: keyof T; label?: string; color?: ChartColor }[]—Series to draw. Without a color, the next one from chartColors is used
aria-label / titlerequiredstring—Accessible name (either one)
descriptionReactNode—Short summary (aria-describedby)
valueFormat(value: number) => stringformatNumberTooltip and value axis
indexFormat(value: T[K]) => string—Category axis and tooltip title
heightnumber280Height in px
legendbooleantrue
gridbooleantrueDashed grid lines
tooltipbooleantrue
loadingbooleanfalseShows a Skeleton
emptyStateReactNode—Empty state. Defaults to EmptyState ("Ma'lumot yo'q")
labels{ empty?: string; loading?: string }{ empty: "Ma'lumot yo'q", loading: 'Yuklanmoqda' }

Extra

PropTypeDefaultDescription
stackedbooleanfalseAreaChart, BarChart — stack the series
curve'monotone' | 'linear' | 'step''monotone'AreaChart, LineChart
orientation'vertical' | 'horizontal''vertical'BarChart: vertical — upright columns, horizontal — horizontal bars

DonutChart

data, aria-label/title, description, valueFormat, indexFormat, height, legend, tooltip, loading, emptyState and labels work as above (there is no series or grid).

PropTypeDefaultDescription
indexrequiredkeyof T—Slice name field
valuerequiredkeyof T—Slice value field
colorsChartColor[]—Color sequence. Defaults to chartColors
centerLabelReactNode—Caption in the center ("Total")
centerValueReactNodevalueFormat(total)Value in the center; null hides it

Sparkline

PropTypeDefaultDescription
datarequiredreadonly number[]—
aria-label / title / aria-hiddenrequiredstring | true—A name, or mark it decorative
colorChartColor'primary'
variant'area' | 'line''area'
curve'monotone' | 'linear' | 'step''monotone'
heightnumber36Height in px

ChartContainer

PropTypeDefaultDescription
childrenrequiredReactNode—A Recharts chart
aria-label / titlerequiredstring—Accessible name
configRecord<string, { label?: ReactNode; color?: ChartColor }>—Key → var(--chart-<key>); label is used by the tooltip and legend
heightnumber | string—Defaults to 280px (h-70)
descriptionReactNode—Short summary (aria-describedby)

ChartColor is a token name (primary, success, warning, danger, info, neutral, sky, emerald, amber, rose) or any CSS value (var(--ak-indigo-400)). Hex values don't adapt to dark mode — prefer tokens.

Data attributes

On the root of ready-made charts: data-state (ready · loading · empty), data-loading.

Accessibility

  • A name is required — every chart gets role="figure" and an aria-label (or title) — not img, because the keyboard layer inside is interactive and img hides its children; Sparkline uses img. Say what is shown and for which period: "Monthly revenue, January–June".
  • Summary — put the key takeaway in description ("Revenue reached 63M so'm in June"); it is read through aria-describedby.
  • Keyboard — Recharts' accessibilityLayer is on: Tab into the chart and move between points with ← →; the tooltip follows. Sparkline has no tooltip, so it doesn't take focus.
  • Offer a table view too — charts are bad at conveying exact values. In important reports add a "Chart / Table" switch or a table below the chart:
  • Color is not the only signal — the legend and tooltip name each series in text.
  • Motion — with prefers-reduced-motion enabled, Recharts turns off its entry animation.

On this page