Визуализация круговых диаграмм в @nivo/pie предоставляет
гибкую систему настройки подсказок (tooltips), позволяющую управлять
тем, как отображается информация при наведении на сегменты. Кастомизация
tooltip — один из ключевых инструментов для повышения читаемости и
информативности диаграмм, особенно в аналитических интерфейсах, где
требуется точное представление долей, процентов и метаданных.
В @nivo/pie каждый элемент диаграммы (slice) передает в
tooltip следующие данные:
id — идентификатор сегментаvalue — числовое значениеformattedValue — форматированное значение (если задан
форматтер)color — цвет сегментаdatum — исходный объект данныхTooltip вызывается автоматически при наведении на сектор и получает объект с этими данными.
По умолчанию используется встроенный tooltip-компонент, который отображает:
Пример базовой конфигурации:
import { ResponsivePie } from '@nivo/pie';
const data = [
{ id: 'JavaScript', value: 40 },
{ id: 'Python', value: 25 },
{ id: 'Go', value: 15 },
{ id: 'C++', value: 20 }
];
export default function PieChart() {
return (
<ResponsivePie
data={data}
margin={{ top: 40, right: 80, bottom: 80, left: 80 }}
innerRadius={0.5}
padAngle={1}
cornerRadius={3}
/>
);
}
Кастомизация осуществляется через проп tooltip, который
принимает React-компонент или функцию.
Базовая форма:
tooltip: (props) => ReactNode
props содержит все данные текущего сегмента.
Наиболее распространённый вариант — замена стандартного вывода на более читаемый блок с акцентом на цвет и процент.
const CustomTooltip = ({ datum }) => {
return (
<div
style={{
padding: '10px 12px',
background: '#1e1e1e',
color: '#fff',
borderRadius: 6,
boxShadow: '0 2px 10px rgba(0,0,0,0.25)'
}}
>
<strong>{datum.id}</strong>
<div>Значение: {datum.value}</div>
</div>
);
};
Подключение:
<ResponsivePie
data={data}
innerRadius={0.6}
tooltip={CustomTooltip}
/>
Часто требуется отображать долю в процентах относительно суммы всех значений. Для этого вычисление выполняется внутри tooltip.
const CustomTooltip = ({ datum, value, allData }) => {
const total = allData.reduce((acc, item) => acc + item.value, 0);
const percent = ((datum.value / total) * 100).toFixed(1);
return (
<div style={{ padding: 10, background: '#222', color: '#fff' }}>
<div>{datum.id}</div>
<div>{datum.value} ({percent}%)</div>
</div>
);
};
В @nivo/pie доступ к полному набору данных может быть
организован через внешний scope или через кастомную обёртку над
компонентом.
Цвет сегмента можно использовать для визуального связывания tooltip с диаграммой.
const CustomTooltip = ({ datum }) => {
return (
<div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: 10 }}>
<span
style={{
width: 12,
height: 12,
backgroundColor: datum.color,
display: 'inline-block'
}}
/>
<div>
<div>{datum.id}</div>
<div>{datum.value}</div>
</div>
</div>
);
};
Такой подход улучшает визуальную связность между подсказкой и сегментом диаграммы.
Tooltip может быть адаптивным и менять структуру в зависимости от значения или категории данных.
const CustomTooltip = ({ datum }) => {
const isLarge = datum.value > 30;
return (
<div
style={{
padding: 10,
background: isLarge ? '#2e7d32' : '#424242',
color: '#fff'
}}
>
<div>{datum.id}</div>
<div>
{isLarge ? 'Высокое значение' : 'Обычное значение'}: {datum.value}
</div>
</div>
);
};
Если исходные данные содержат дополнительные поля, они могут быть использованы внутри tooltip без ограничений.
const data = [
{
id: 'React',
value: 45,
description: 'Frontend библиотека',
projects: 120
}
];
const CustomTooltip = ({ datum }) => {
return (
<div style={{ padding: 12, background: '#111', color: '#fff' }}>
<div>{datum.id}</div>
<div>{datum.data.description}</div>
<div>Проектов: {datum.data.projects}</div>
</div>
);
};
Хотя @nivo/pie не управляет анимацией tooltip напрямую,
можно использовать CSS для создания плавного появления.
.tooltip {
opacity: 0;
transform: translateY(5px);
animation: fadeIn 0.15s ease forwards;
}
@keyframes fadeIn {
to {
opacity: 1;
transform: translateY(0);
}
}
const CustomTooltip = ({ datum }) => {
return (
<div className="tooltip" style={{ padding: 10, background: '#000', color: '#fff' }}>
{datum.id}: {datum.value}
</div>
);
};
В некоторых интерфейсах требуется фиксированное отображение подсказки (например, для аналитических панелей). В этом случае tooltip можно комбинировать с состоянием React:
const [active, setActive] = useState(null);
<ResponsivePie
data={data}
tooltip={({ datum }) => {
setActive(datum);
return null;
}}
/>
{active && (
<div className="fixed-tooltip">
{active.id}: {active.value}
</div>
)}
Такой подход переносит контроль над отображением полностью в пользовательский слой.
Tooltip может использоваться не только как всплывающий элемент, но и как источник данных для внешних панелей.
const [info, setInfo] = useState(null);
<ResponsivePie
data={data}
tooltip={({ datum }) => {
setInfo(datum);
return <div />;
}}
/>
<Sidebar>
{info ? (
<>
<h3>{info.id}</h3>
<p>{info.value}</p>
</>
) : (
<p>Наведи на сектор</p>
)}
</Sidebar>
При использовании дизайн-системы tooltip обычно подстраивается под глобальную тему:
const theme = {
tooltip: {
container: {
background: '#0f172a',
color: '#e2e8f0',
fontSize: 12
}
}
};
<ResponsivePie data={data} theme={theme} />
При работе с диаграммами, содержащими десятки и сотни сегментов, важно минимизировать нагрузку:
React.memoTooltip должен учитывать возможные некорректные данные:
const CustomTooltip = ({ datum }) => {
if (!datum || typeof datum.value !== 'number') return null;
return (
<div>
<div>{datum.id ?? 'unknown'}</div>
<div>{datum.value ?? 0}</div>
</div>
);
};
В случае маленьких сегментов диаграммы tooltip может срабатывать нестабильно. В таких случаях применяется:
padAngleactiveOuterRadiusOffset<ResponsivePie
data={data}
padAngle={2}
activeOuterRadiusOffset={8}
/>