Describe the bug
I have a component DonutChart
with defaultProps
and propTypes
defined (w/ comments).
This component has a story defined (index.stories.mdx). Despite this the prop table is not showing up...
Note: Another component RangeChart
composed very similarly has propTypes
and they ARE showing up in storybook.
Expected Behavior I expect the Props
table to show up for both components (RangeChart
and DonutChart
)
Actual Behavior DonutChart
component docs is missing the Props
table.
DonutChart/index.js
import React, { useState } from 'react';
import cn from 'classnames';
import moize from 'moize';
import PropTypes from 'prop-types';
import { scaleOrdinal as d3ScaleOrdinal } from 'd3-scale';
import { arc as d3Arc, pie as d3Pie } from 'd3-shape';
import style from './styles.css';
const pie = d3Pie().value(d => d.value);
const getCachedArc = moize.deep(
(width, height, anglePadding, ringWidth, cornerRadius, margin) => {
const radius = Math.min(width, height) / 2;
const outerRadius = radius - margin;
return d3Arc()
.padAngle(anglePadding)
.outerRadius(outerRadius)
.innerRadius(outerRadius - ringWidth)
.cornerRadius(cornerRadius);
}
);
const getCachedColor = moize.deep((data, colors) =>
d3ScaleOrdinal()
.domain(data.map(d => d.label))
.range(colors)
);
const getCachedPieData = moize.deep(data => pie(data));
/**
Donut Chart
*/
const DonutChart = props => {
const [activeSegment, activateSegment] = useState(null);
const getArc = () => {
return getCachedArc(
props.width,
props.height,
props.anglePadding,
props.ringWidth,
props.cornerRadius,
props.margin
);
};
const getColor = () => {
return getCachedColor(props.data, props.colors);
};
const getPieData = () => {
return getCachedPieData(props.data);
};
const {
data,
height,
margin,
ringWidth,
showActiveLabel,
showLabels,
title,
valueFormatter,
width
} = props;
const activeSegmentData =
activeSegment && data.find(d => d.label === activeSegment).value;
const showTitle = (!showActiveLabel || !activeSegment) && title;
const showActiveSegment = showActiveLabel && activeSegment;
return (
<div className={cn('pie-chart', { 'has-active': activeSegment })}>
<div
className="center-text"
style={{ width, height, padding: margin + ringWidth }}>
{showTitle && <span className="title">{title}</span>}
{showActiveSegment && (
<span className="active-segment-label">
{activeSegment}
<br />
<strong>{valueFormatter(activeSegmentData)}</strong>
</span>
)}
</div>
<svg width={width} height={height}>
<g transform={`translate(${width / 2},${height / 2})`}>
{getPieData().map(slice => (
<g
onMouseEnter={() => activateSegment(slice.data.label)}
onMouseLeave={() => activateSegment(null)}
key={`arc-${slice.data.label}`}
className={cn('arc', {
active: activeSegment === slice.data.label
})}>
<path d={getArc()(slice)} fill={getColor()(slice.data.label)} />
{showLabels && (
<text
transform={`translate(${getArc().centroid(slice)})`}
className="segment-label">
{slice.data.label}
</text>
)}
</g>
))}
</g>
</svg>
<style jsx>{style}</style>
</div>
);
};
DonutChart.defaultProps = {
anglePadding: 0.01,
width: 300,
height: 300,
valueFormatter: x => x,
colors: ['#004b71', '#ffdf00', '#e37a00', '#c03123', '#614a7a', '#7c993f'],
cornerRadius: 2,
margin: 10,
ringWidth: 10,
showActiveLabel: true,
showLabels: false
};
DonutChart.propTypes = {
/**
Padding of each slice angle
useful for adding space between
slices
*/
anglePadding: PropTypes.number,
/**
segment data needed to render
the chart
*/
data: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
value: PropTypes.number.isRequired
})
).isRequired,
/**
width of the pie chart
*/
width: PropTypes.number,
/**
height the pie chart
*/
height: PropTypes.number,
/**
function that formats the
value for display
*/
valueFormatter: PropTypes.func,
/**
array of colors in hex format
*/
colors: PropTypes.arrayOf(PropTypes.string),
/**
border/corner radius
of each arc segment
*/
cornerRadius: PropTypes.number,
/**
Margin from the exterior
of the svg chart to the ring
*/
margin: PropTypes.number,
/**
width in pixels of the ring
*/
ringWidth: PropTypes.number,
/**
boolean that represents
whether the active segment label
and value should be
seen in the center text
*/
showActiveLabel: PropTypes.bool,
/**
boolean which represents whether
arc segments should be labeled
*/
showLabels: PropTypes.bool
};
export default DonutChart;
DonutChart/index.stories.mdx
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
import * as knobs from '@storybook/addon-knobs';
import DonutChart from '.';
<Meta title="visualizations/DonutChart" component={DonutChart} />
# DonutChart
A Reusable Donut Chart Component
## Props
<Props of={DonutChart} />
## Examples
A basic example:
<Preview>
<Story name="basic example">
<DonutChart
title={knobs.text('Title: ', 'Asset Allocation')}
colors={knobs.object('Colors: ', DonutChart.defaultProps.colors)}
cornerRadius={knobs.number(
'Corner Radius: ',
DonutChart.defaultProps.cornerRadius
)}
height={knobs.number('Height: ', DonutChart.defaultProps.height)}
width={knobs.number('Width: ', DonutChart.defaultProps.width)}
margin={knobs.number('Margin: ', DonutChart.defaultProps.margin)}
ringWidth={knobs.number(
'Ring Width: ',
DonutChart.defaultProps.ringWidth
)}
showActiveLabel={knobs.boolean(
'Show Active Label: ',
DonutChart.defaultProps.showActiveLabel
)}
showLabels={knobs.boolean(
'Show Labels: ',
DonutChart.defaultProps.showLabels
)}
anglePadding={knobs.number(
'Angle Padding: ',
DonutChart.defaultProps.anglePadding
)}
data={knobs.object('Data:', [
{ label: 'Domestic Stock', value: 75 },
{ label: 'Foreign Stock', value: 19 },
{ label: 'Other', value: 6 }
])}
/>
</Story>
</Preview>
You can customize the title
<Preview>
<Story name="another example">
<DonutChart
title="Here is a custom title"
colors={[
'#004b71',
'#ffdf00',
'#e37a00',
'#c03123',
'#614a7a',
'#7c993f'
]}
cornerRadius={2}
height={300}
width={300}
margin={10}
ringWidth={10}
showActiveLabel
anglePadding={0.01}
data={[
{ label: 'Domestic Stock', value: 75 },
{ label: 'Foreign Stock', value: 19 },
{ label: 'Other', value: 6 }
]}
/>
</Story>
</Preview>
RangeChart/index.js
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import styles from './styles.css';
/**
Simple RangeChart component
Horizontal line with marker
indicating a percent 0 - 100
*/
const RangeChart = ({ barWidthPercent, valuePercent, markerClass, labels }) => {
const leftVal = (() => {
const left = valuePercent - barWidthPercent / 2;
if (left < barWidthPercent) {
return 0;
}
const maxLeft = 100 - barWidthPercent;
if (left > maxLeft) {
return maxLeft;
}
return left;
})();
const markerStyle = {
width: `${barWidthPercent}%`,
left: `${leftVal}%`
};
return (
<>
<div className="bar">
<div
className={cn(markerClass, 'marker', {
'default-bg': !markerClass
})}
style={markerStyle}
/>
</div>
<div className="labels">
{labels.map(l => (
<div key={`rp-l-${l}`}>{l}</div>
))}
</div>
<style jsx>{styles}</style>
</>
);
};
RangeChart.defaultProps = {
barWidthPercent: 10,
valuePercent: 0,
markerClass: '',
labels: []
};
RangeChart.propTypes = {
/**
width of the range marker
percent of parent contianer
(0 - 100)
*/
barWidthPercent: PropTypes.number,
/**
value percentage of data
(0 - 100)
*/
valuePercent: PropTypes.number,
/**
classname to give the marker
useful for different styling
*/
markerClass: PropTypes.string,
/**
a list of labels to evenly display below chart
*/
labels: PropTypes.arrayOf(PropTypes.string)
};
export default RangeChart;
RangeChart/index.stories.mdx
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
import * as knobs from '@storybook/addon-knobs';
import RangeChart from '.';
<Meta title="visualizations/RangeChart" component={RangeChart} />
# RangeChart
The range chart is used to visualize a value over a percentage of a horizontal bar.
## Props
<Props of={RangeChart} />
## Examples
A basic example:
<Preview>
<Story name="basic example (with knobs)">
<RangeChart
barWidthPercent={knobs.number('Bar Width Percent', 10)}
valuePercent={knobs.number('Value Percent', 25)}
labels={knobs.object('Labels', ['Low', 'Medium', 'High'])}
/>
</Story>
</Preview>
It allows the ability to add labels spaced evenly over the horizontal axis.
<Preview>
<Story name="many labels">
<RangeChart
barWidthPercent={10}
valuePercent={65}
labels={['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']}
/>
</Story>
</Preview>
Useful for showing hi-lo range (e.g. 52 week).
<Preview>
<Story name="52 week example">
<RangeChart
barWidthPercent={1}
valuePercent={100}
labels={['$9.94', '52 WEEK RANGE', '$10.25']}
/>
</Story>
</Preview>
The width of the bar can be customized
<Preview>
<Story name="custom bar width">
<RangeChart
barWidthPercent={50}
valuePercent={100}
labels={['LOW', 'MIDDLE', 'HIGH']}
/>
</Story>
</Preview>
I can try to give more details if needed.
NM I found what I did wrong.
@cphoover what was it? might help anybody who stumbles on this issue
@cphoover Could you share what fixed it for you? I have a similar issue in my project
Looks like they forgot to import Props
Most helpful comment
Looks like they forgot to import Props