Skip to content

Commit e6bab88

Browse files
committedSep 11, 2021
feat(radial-bar): add support for labels
1 parent 5ec257f commit e6bab88

File tree

8 files changed

+130
-24
lines changed

8 files changed

+130
-24
lines changed
 

‎packages/radial-bar/src/RadialBar.tsx

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createElement, Fragment, ReactNode } from 'react'
22
import { Container, useDimensions, SvgWrapper } from '@nivo/core'
3-
import { RadialBarLayerId, RadialBarSvgProps } from './types'
3+
import { ArcLabelsLayer } from '@nivo/arcs'
4+
import { RadialBarLayerId, RadialBarSvgProps, ComputedBar } from './types'
45
import { svgDefaultProps } from './props'
56
import { useRadialBar } from './hooks'
67
import { RadialBarArcs } from './RadialBarArcs'
@@ -21,6 +22,11 @@ const InnerRadialBar = ({
2122
layers = svgDefaultProps.layers,
2223
colors = svgDefaultProps.colors,
2324
cornerRadius = svgDefaultProps.cornerRadius,
25+
enableLabels = svgDefaultProps.enableLabels,
26+
label = svgDefaultProps.label,
27+
labelsSkipAngle = svgDefaultProps.labelsSkipAngle,
28+
labelsRadiusOffset = svgDefaultProps.labelsRadiusOffset,
29+
labelsTextColor = svgDefaultProps.labelsTextColor,
2430
isInteractive = svgDefaultProps.isInteractive,
2531
tooltip = svgDefaultProps.tooltip,
2632
onClick,
@@ -52,6 +58,7 @@ const InnerRadialBar = ({
5258
const layerById: Record<RadialBarLayerId, ReactNode> = {
5359
grid: null,
5460
bars: null,
61+
labels: null,
5562
legends: null,
5663
}
5764

@@ -84,6 +91,21 @@ const InnerRadialBar = ({
8491
)
8592
}
8693

94+
if (layers.includes('labels') && enableLabels) {
95+
layerById.labels = (
96+
<ArcLabelsLayer<ComputedBar>
97+
key="labels"
98+
center={center}
99+
data={bars}
100+
label={label}
101+
radiusOffset={labelsRadiusOffset}
102+
skipAngle={labelsSkipAngle}
103+
textColor={labelsTextColor}
104+
transitionMode={transitionMode}
105+
/>
106+
)
107+
}
108+
87109
return (
88110
<SvgWrapper
89111
width={outerWidth}

‎packages/radial-bar/src/hooks.ts

+6-11
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@ import { degreesToRadians } from '@nivo/core'
55
import { Arc } from '@nivo/arcs'
66
import { useOrdinalColorScale } from '@nivo/colors'
77
import { svgDefaultProps } from './props'
8-
import {
9-
ComputedBar,
10-
RadialBarCommonProps,
11-
RadialBarDataProps,
12-
RadialBarSerie,
13-
} from './types'
8+
import { ComputedBar, RadialBarCommonProps, RadialBarDataProps, RadialBarSerie } from './types'
149

1510
interface RadialBarGroup {
1611
id: string
@@ -86,15 +81,15 @@ export const useRadialBar = ({
8681
scaleBand()
8782
.domain(serieIds)
8883
.range([outerRadius - 100, outerRadius])
89-
.padding(0.4),
84+
.padding(0.2),
9085
[serieIds, outerRadius]
9186
)
9287

9388
const arcGenerator = useMemo(
9489
() =>
9590
d3Arc<Arc>()
96-
.startAngle(d => degreesToRadians(d.startAngle))
97-
.endAngle(d => degreesToRadians(d.endAngle))
91+
.startAngle(d => d.startAngle)
92+
.endAngle(d => d.endAngle)
9893
.innerRadius(d => d.innerRadius)
9994
.outerRadius(d => d.outerRadius)
10095
.cornerRadius(cornerRadius),
@@ -121,8 +116,8 @@ export const useRadialBar = ({
121116
color: '',
122117
stackedValue,
123118
arc: {
124-
startAngle: valueScale(currentValue),
125-
endAngle: valueScale(stackedValue),
119+
startAngle: degreesToRadians(valueScale(currentValue)),
120+
endAngle: degreesToRadians(valueScale(stackedValue)),
126121
innerRadius,
127122
outerRadius,
128123
},

‎packages/radial-bar/src/props.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@ import { RadialBarLayerId } from './types'
22
import { RadialBarTooltip } from './RadialBarTooltip'
33

44
export const svgDefaultProps = {
5-
layers: ['grid', 'bars', 'legends'] as RadialBarLayerId[],
5+
layers: ['grid', 'bars', 'labels', 'legends'] as RadialBarLayerId[],
66

77
startAngle: 0,
88
endAngle: 270,
99

1010
colors: { scheme: 'nivo' as const },
1111
cornerRadius: 0,
1212

13+
enableLabels: true,
14+
label: 'value',
15+
labelsSkipAngle: 10,
16+
labelsRadiusOffset: 0.5,
17+
labelsTextColor: { theme: 'labels.text.fill' },
18+
1319
isInteractive: true,
1420
tooltip: RadialBarTooltip,
1521

‎packages/radial-bar/src/types.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AriaAttributes, FunctionComponent, MouseEvent } from 'react'
2-
import { Theme, Box, Dimensions, ModernMotionProps } from '@nivo/core'
3-
import { Arc, ArcTransitionMode } from '@nivo/arcs'
2+
import { Theme, Box, Dimensions, ModernMotionProps, PropertyAccessor } from '@nivo/core'
3+
import { Arc, ArcLabelsProps, ArcTransitionMode } from '@nivo/arcs'
44
import { OrdinalColorScaleConfig } from '@nivo/colors'
55

66
export interface RadialBarDatum {
@@ -28,14 +28,14 @@ export interface RadialBarDataProps {
2828
data: RadialBarSerie[]
2929
}
3030

31-
export type RadialBarLayerId = 'grid' | 'bars' | 'legends'
31+
export type RadialBarLayerId = 'grid' | 'bars' | 'labels' | 'legends'
3232

3333
export interface RadialBarTooltipProps {
3434
bar: ComputedBar
3535
}
3636
export type RadialBarTooltipComponent = FunctionComponent<RadialBarTooltipProps>
3737

38-
export interface RadialBarCommonProps {
38+
export type RadialBarCommonProps = {
3939
margin: Box
4040

4141
theme: Theme
@@ -47,6 +47,12 @@ export interface RadialBarCommonProps {
4747
startAngle: number
4848
endAngle: number
4949

50+
enableLabels: boolean
51+
label: PropertyAccessor<ComputedBar, string>
52+
labelsSkipAngle: ArcLabelsProps<ComputedBar>['arcLabelsSkipAngle']
53+
labelsRadiusOffset: ArcLabelsProps<ComputedBar>['arcLabelsRadiusOffset']
54+
labelsTextColor: ArcLabelsProps<ComputedBar>['arcLabelsTextColor']
55+
5056
isInteractive: boolean
5157
tooltip: RadialBarTooltipComponent
5258
onClick: (bar: ComputedBar, event: MouseEvent) => void

‎website/src/data/components/pie/props.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ const props: ChartProperty[] = [
521521
{
522522
key: 'activeInnerRadiusOffset',
523523
flavors: ['svg', 'canvas'],
524-
help: `Skip label if corresponding slice's angle is lower than provided value.`,
524+
help: `Extends active slice inner radius.`,
525525
type: 'number',
526526
required: false,
527527
defaultValue: defaultProps.activeInnerRadiusOffset,
@@ -536,7 +536,7 @@ const props: ChartProperty[] = [
536536
{
537537
key: 'activeOuterRadiusOffset',
538538
flavors: ['svg', 'canvas'],
539-
help: `Skip label if corresponding slice's angle is lower than provided value.`,
539+
help: `Extends active slice outer radius.`,
540540
type: 'number',
541541
required: false,
542542
defaultValue: defaultProps.activeOuterRadiusOffset,

‎website/src/data/components/radial-bar/meta.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ RadialBar:
1111
- isomorphic
1212
stories: []
1313
description: |
14-
Generates a radial bar chart from an array of data.
14+
A radial bar chart.
15+
1516
Note that margin object does not take grid labels into account,
1617
so you should adjust it to leave enough room for it.
1718

‎website/src/data/components/radial-bar/props.ts

+74-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { svgDefaultProps } from '@nivo/radial-bar'
2-
import { defaultProps } from '@nivo/pie'
32
import { arcTransitionModes } from '@nivo/arcs'
43
import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties'
54
import { ChartProperty } from '../../../types'
@@ -188,9 +187,82 @@ const props: ChartProperty[] = [
188187
step: 1,
189188
},
190189
},
190+
{
191+
key: 'enableLabels',
192+
group: 'Labels',
193+
type: 'boolean',
194+
required: false,
195+
help: 'Enable/disable labels.',
196+
flavors: ['svg'],
197+
defaultValue: svgDefaultProps.enableLabels,
198+
controlType: 'switch',
199+
},
200+
{
201+
key: 'label',
202+
group: 'Labels',
203+
type: 'string | (bar: ComputedBar) => string',
204+
required: false,
205+
help:
206+
'Defines how to get label text, can be a string (used to access current bar property) or a function which will receive the actual bar data.',
207+
flavors: ['svg'],
208+
defaultValue: svgDefaultProps.label,
209+
controlType: 'choices',
210+
controlOptions: {
211+
choices: ['category', 'groupId', 'value', 'formattedValue'].map(choice => ({
212+
label: choice,
213+
value: choice,
214+
})),
215+
},
216+
},
217+
{
218+
key: 'labelsSkipAngle',
219+
group: 'Labels',
220+
type: 'number',
221+
required: false,
222+
help: `Skip label if corresponding arc's angle is lower than provided value.`,
223+
flavors: ['svg'],
224+
defaultValue: svgDefaultProps.labelsSkipAngle,
225+
controlType: 'range',
226+
controlOptions: {
227+
unit: '°',
228+
min: 0,
229+
max: 45,
230+
step: 1,
231+
},
232+
},
233+
{
234+
key: 'labelsRadiusOffset',
235+
group: 'Labels',
236+
type: 'number',
237+
required: false,
238+
help: `
239+
Define the radius to use to determine the label position, starting from inner radius,
240+
this is expressed as a ratio. Centered at 0.5 by default.
241+
`,
242+
flavors: ['svg'],
243+
defaultValue: svgDefaultProps.labelsRadiusOffset,
244+
controlType: 'range',
245+
controlOptions: {
246+
min: 0,
247+
max: 2,
248+
step: 0.05,
249+
},
250+
},
251+
{
252+
key: 'labelsTextColor',
253+
group: 'Labels',
254+
help: 'Defines how to compute label text color.',
255+
type: 'string | object | Function',
256+
required: false,
257+
flavors: ['svg'],
258+
defaultValue: svgDefaultProps.labelsTextColor,
259+
controlType: 'inheritedColor',
260+
},
191261
{
192262
key: 'layers',
193263
group: 'Customization',
264+
type: '(RadialBarLayerId | RadialBarCustomLayer)[]',
265+
required: false,
194266
help: 'Defines the order of layers and add custom layers.',
195267
description: `
196268
You can also use this to insert extra layers
@@ -199,8 +271,6 @@ const props: ChartProperty[] = [
199271
The layer function which will receive the chart's
200272
context & computed data and must return a valid SVG element.
201273
`,
202-
required: false,
203-
type: '(RadarLayerId | FunctionComponent<RadarCustomLayerProps>)[]',
204274
flavors: ['svg'],
205275
defaultValue: svgDefaultProps.layers,
206276
},
@@ -293,7 +363,7 @@ const props: ChartProperty[] = [
293363
help: 'Define how transitions behave.',
294364
type: 'string',
295365
required: false,
296-
defaultValue: defaultProps.transitionMode,
366+
defaultValue: svgDefaultProps.transitionMode,
297367
controlType: 'choices',
298368
group: 'Motion',
299369
controlOptions: {

‎website/src/pages/radial-bar/index.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ const initialProperties: UnmappedRadarProps = {
2929
colors: svgDefaultProps.colors,
3030
cornerRadius: 2,
3131

32+
enableLabels: svgDefaultProps.enableLabels,
33+
label: svgDefaultProps.label,
34+
labelsSkipAngle: svgDefaultProps.labelsSkipAngle,
35+
labelsRadiusOffset: svgDefaultProps.labelsRadiusOffset,
36+
labelsTextColor: svgDefaultProps.labelsTextColor,
37+
3238
animate: true,
3339
motionConfig: 'gentle' as const,
3440
transitionMode: 'pushOut' as const,

0 commit comments

Comments
 (0)
Please sign in to comment.