diff --git a/apps/mantine.dev/src/pages/charts/bar-chart.mdx b/apps/mantine.dev/src/pages/charts/bar-chart.mdx index 43b75611bb..67546588c7 100644 --- a/apps/mantine.dev/src/pages/charts/bar-chart.mdx +++ b/apps/mantine.dev/src/pages/charts/bar-chart.mdx @@ -237,3 +237,12 @@ rendered behind the chart. To display value above each bar, set `withBarValueLabel`: + +## Bar value label props + +You can pass props down to recharts [LabelList](https://recharts.org/en-US/api/LabelList) +component with `valueLabelProps` prop. `valueLabelProps` accepts either an object with props +or a function that receives series data as an argument and returns an object with +props. + + diff --git a/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demo.valueLabelProps.tsx b/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demo.valueLabelProps.tsx new file mode 100644 index 0000000000..002b8fe05f --- /dev/null +++ b/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demo.valueLabelProps.tsx @@ -0,0 +1,53 @@ +import { BarChart } from '@mantine/charts'; +import { MantineDemo } from '@mantinex/demo'; +import { data, dataCode } from './_data'; + +const code = ` +import { BarChart } from '@mantine/charts'; +import { data } from './data'; + +function Demo() { + return ( + new Intl.NumberFormat('en-US').format(value)} + withBarValueLabel + valueLabelProps={{ position: 'inside', fill: 'white' }} + series={[ + { name: 'Smartphones', color: 'violet.6' }, + { name: 'Laptops', color: 'blue.6' }, + { name: 'Tablets', color: 'teal.6' }, + ]} + /> + ); +} +`; + +function Demo() { + return ( + new Intl.NumberFormat('en-US').format(value)} + withBarValueLabel + valueLabelProps={{ position: 'inside', fill: 'white' }} + series={[ + { name: 'Smartphones', color: 'violet.6' }, + { name: 'Laptops', color: 'blue.6' }, + { name: 'Tablets', color: 'teal.6' }, + ]} + /> + ); +} + +export const valueLabelProps: MantineDemo = { + type: 'code', + component: Demo, + code: [ + { code, language: 'tsx', fileName: 'Demo.tsx' }, + { code: dataCode, language: 'tsx', fileName: 'data.ts' }, + ], +}; diff --git a/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demos.story.tsx b/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demos.story.tsx index 282c46773e..c796617200 100644 --- a/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demos.story.tsx +++ b/packages/@docs/demos/src/demos/charts/BarChart/BarChart.demos.story.tsx @@ -128,6 +128,11 @@ export const Demo_barValueLabel = { render: renderDemo(demos.barValueLabel), }; +export const Demo_valueLabelProps = { + name: '⭐ Demo: valueLabelProps', + render: renderDemo(demos.valueLabelProps), +}; + export const Demo_minBarSize = { name: '⭐ Demo: minBarSize', render: renderDemo(demos.minBarSize), diff --git a/packages/@docs/demos/src/demos/charts/BarChart/index.ts b/packages/@docs/demos/src/demos/charts/BarChart/index.ts index dc1b258fc3..999eb3ce02 100644 --- a/packages/@docs/demos/src/demos/charts/BarChart/index.ts +++ b/packages/@docs/demos/src/demos/charts/BarChart/index.ts @@ -26,3 +26,4 @@ export { barValueLabel } from './BarChart.demo.barValueLabel'; export { minBarSize } from './BarChart.demo.minBarSize'; export { mixedStack } from './BarChart.demo.mixedStack'; export { stripes } from './BarChart.demo.stripes'; +export { valueLabelProps } from './BarChart.demo.valueLabelProps'; diff --git a/packages/@mantine/charts/src/BarChart/BarChart.tsx b/packages/@mantine/charts/src/BarChart/BarChart.tsx index ebe2e552e7..6de3605b6d 100644 --- a/packages/@mantine/charts/src/BarChart/BarChart.tsx +++ b/packages/@mantine/charts/src/BarChart/BarChart.tsx @@ -5,6 +5,8 @@ import { CartesianGrid, Cell, Label, + LabelList, + LabelListProps, Legend, BarChart as ReChartsBarChart, ReferenceLine, @@ -31,7 +33,6 @@ import { import { ChartLegend, ChartLegendStylesNames } from '../ChartLegend'; import { ChartTooltip, ChartTooltipStylesNames } from '../ChartTooltip'; import type { BaseChartStylesNames, ChartSeries, GridChartBaseProps } from '../types'; -import { BarLabel } from './BarLabel'; import classes from '../grid-chart.module.css'; function valueToPercent(value: number) { @@ -92,6 +93,11 @@ export interface BarChartProps /** Determines whether a label with bar value should be displayed on top of each bar, incompatible with `type="stacked"` and `type="percent"`, `false` by default */ withBarValueLabel?: boolean; + /** Props passed down to recharts `LabelList` component */ + valueLabelProps?: + | ((series: BarChartSeries) => Partial>, 'ref'>>) + | Partial>>; + /** Sets minimum height of the bar in px, `0` by default */ minBarSize?: number; @@ -202,6 +208,7 @@ export const BarChart = factory((_props, ref) => { xAxisLabel, yAxisLabel, withBarValueLabel, + valueLabelProps, withRightYAxis, rightYAxisLabel, rightYAxisProps, @@ -217,6 +224,8 @@ export const BarChart = factory((_props, ref) => { const [highlightedArea, setHighlightedArea] = useState(null); const shouldHighlight = highlightedArea !== null; const stacked = type === 'stacked' || type === 'percent'; + const tickFormatter = type === 'percent' ? valueToPercent : valueFormatter; + const handleMouseLeave = (event: React.MouseEvent) => { setHighlightedArea(null); onMouseLeave?.(event); @@ -258,11 +267,6 @@ export const BarChart = factory((_props, ref) => { fillOpacity={dimmed ? 0.1 : fillOpacity} strokeOpacity={dimmed ? 0.2 : 0} stackId={stacked ? 'stack' : item.stackId || undefined} - label={ - withBarValueLabel ? ( - - ) : undefined - } yAxisId={item.yAxisId || 'left'} minPointSize={minBarSize} {...(typeof barProps === 'function' ? barProps(item) : barProps)} @@ -275,6 +279,15 @@ export const BarChart = factory((_props, ref) => { } /> ))} + {withBarValueLabel && ( + + )} ); }); @@ -299,8 +312,6 @@ export const BarChart = factory((_props, ref) => { ); }); - const tickFormatter = type === 'percent' ? valueToPercent : valueFormatter; - const sharedYAxisProps = { axisLine: false, ...(orientation === 'vertical' diff --git a/packages/@mantine/charts/src/BarChart/BarLabel.tsx b/packages/@mantine/charts/src/BarChart/BarLabel.tsx deleted file mode 100644 index 1986569601..0000000000 --- a/packages/@mantine/charts/src/BarChart/BarLabel.tsx +++ /dev/null @@ -1,23 +0,0 @@ -export function BarLabel({ - value, - valueFormatter, - textBreakAll, - parentViewBox, - orientation, - viewBox, - width, - height, - ...others -}: Record) { - return ( - - {typeof valueFormatter === 'function' ? valueFormatter(value) : value} - - ); -} diff --git a/packages/@mantine/charts/src/CompositeChart/CompositeChart.tsx b/packages/@mantine/charts/src/CompositeChart/CompositeChart.tsx index f1e2b5ce73..d23f23f609 100644 --- a/packages/@mantine/charts/src/CompositeChart/CompositeChart.tsx +++ b/packages/@mantine/charts/src/CompositeChart/CompositeChart.tsx @@ -7,6 +7,7 @@ import { CartesianGrid, DotProps, Label, + LabelList, Legend, Line, LineProps, @@ -31,7 +32,6 @@ import { useResolvedStylesApi, useStyles, } from '@mantine/core'; -import { BarLabel } from '../BarChart/BarLabel'; import { ChartLegend, ChartLegendStylesNames } from '../ChartLegend'; import { ChartTooltip, ChartTooltipStylesNames } from '../ChartTooltip'; import { PointLabel } from '../PointLabel/PointLabel'; @@ -340,11 +340,19 @@ export const CompositeChart = factory((_props, ref) => { isAnimationActive={false} fillOpacity={dimmed ? 0.1 : 1} strokeOpacity={dimmed ? 0.2 : 0} - label={withBarValueLabel ? : undefined} yAxisId={item.yAxisId || 'left'} minPointSize={minBarSize} {...(typeof barProps === 'function' ? barProps(item) : barProps)} - /> + > + {withBarValueLabel && ( + + )} + ); } diff --git a/packages/@mantine/charts/src/grid-chart.module.css b/packages/@mantine/charts/src/grid-chart.module.css index 4cb85c31d5..9a0a40fd4e 100644 --- a/packages/@mantine/charts/src/grid-chart.module.css +++ b/packages/@mantine/charts/src/grid-chart.module.css @@ -22,10 +22,6 @@ font-family: var(--mantine-font-family); color: var(--chart-text-color, var(--mantine-color-dimmed)); } - - &:where([data-orientation='vertical']) { - --chart-bar-label-color: var(--mantine-color-white); - } } .container {