recharts#LegendProps TypeScript Examples
The following examples show how to use
recharts#LegendProps.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: stage-chart.tsx From backstage with Apache License 2.0 | 4 votes |
export function StageChart(props: StageChartProps) {
const { stage, ...chartOptions } = props;
const {
chartTypes,
defaultCollapsed = 0,
defaultHidden = 0,
zeroYAxis = false,
} = chartOptions;
const { zoomFilterValues } = useZoom();
const { zoomProps, getZoomArea } = useZoomArea();
const ticks = useMemo(
() => pickElements(stage.values, 8).map(val => val.__epoch),
[stage.values],
);
const domainY = useMemo(
() => [zeroYAxis ? 0 : 'auto', 'auto'] as YAxisProps['domain'],
[zeroYAxis],
);
const statuses = useMemo(
() => statusTypes.filter(status => stage.statusSet.has(status)),
[stage.statusSet],
);
const legendPayload = useMemo(
(): LegendProps['payload'] =>
statuses.map(status => ({
value: capitalize(status),
type: 'line',
id: status,
color: statusColorMap[status],
})),
[statuses],
);
const subStages = useMemo(
() =>
new Map<string, ChartableStage>(
[...stage.stages.entries()].filter(
([_name, subStage]) => subStage.combinedAnalysis.max > defaultHidden,
),
),
[stage.stages, defaultHidden],
);
const zoomFilteredValues = useMemo(
() => zoomFilterValues(stage.values),
[stage.values, zoomFilterValues],
);
return stage.combinedAnalysis.max < defaultHidden ? null : (
<Accordion
defaultExpanded={stage.combinedAnalysis.max > defaultCollapsed}
TransitionProps={transitionProps}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>
{stage.name} (med {formatDuration(stage.combinedAnalysis.med)}, avg{' '}
{formatDuration(stage.combinedAnalysis.avg)})
</Typography>
</AccordionSummary>
<AccordionDetails>
{stage.values.length === 0 ? (
<Alert severity="info">No data</Alert>
) : (
<Grid container direction="column">
<Grid item style={noUserSelect}>
<ResponsiveContainer width="100%" height={140}>
<ComposedChart data={zoomFilteredValues} {...zoomProps}>
<defs>
<linearGradient id="colorDur" x1="0" y1="0" x2="0" y2="1">
{fireColors.map(([percent, color]) => (
<stop
key={percent}
offset={percent}
stopColor={color}
stopOpacity={0.8}
/>
))}
</linearGradient>
</defs>
{statuses.length > 1 && <Legend payload={legendPayload} />}
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="__epoch"
type="category"
ticks={ticks}
tickFormatter={tickFormatterX}
/>
<YAxis
yAxisId={1}
tickFormatter={tickFormatterY}
type="number"
tickCount={5}
name="Duration"
domain={domainY}
/>
<YAxis
yAxisId={2}
orientation="right"
type="number"
tickCount={5}
name="Count"
/>
<Tooltip
formatter={tooltipValueFormatter}
labelFormatter={labelFormatter}
/>
{statuses.reverse().map(status => (
<Fragment key={status}>
{!chartTypes[status].includes('duration') ? null : (
<>
<Area
isAnimationActive={false}
yAxisId={1}
type="monotone"
dataKey={status}
stackId={status}
stroke={
statuses.length > 1
? statusColorMap[status]
: colorStroke
}
fillOpacity={statuses.length > 1 ? 0.5 : 1}
fill={
statuses.length > 1
? statusColorMap[status]
: 'url(#colorDur)'
}
connectNulls
/>
<Line
isAnimationActive={false}
yAxisId={1}
type="monotone"
dataKey={`${status} avg`}
stroke={
statuses.length > 1
? statusColorMap[status]
: colorStrokeAvg
}
opacity={0.8}
strokeWidth={2}
dot={false}
connectNulls
/>
</>
)}
{!chartTypes[status].includes('count') ? null : (
<Bar
isAnimationActive={false}
yAxisId={2}
type="monotone"
dataKey={`${status} count`}
stackId="1"
stroke={statusColorMap[status] ?? ''}
fillOpacity={0.5}
fill={statusColorMap[status] ?? ''}
/>
)}
</Fragment>
))}
{getZoomArea({ yAxisId: 1 })}
</ComposedChart>
</ResponsiveContainer>
</Grid>
{subStages.size === 0 ? null : (
<Grid item>
<Accordion
defaultExpanded={false}
TransitionProps={transitionProps}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>Sub stages ({subStages.size})</Typography>
</AccordionSummary>
<AccordionDetails>
<div style={fullWidth}>
{[...subStages.values()].map(subStage => (
<StageChart
key={subStage.name}
{...chartOptions}
stage={subStage}
/>
))}
</div>
</AccordionDetails>
</Accordion>
</Grid>
)}
</Grid>
)}
</AccordionDetails>
</Accordion>
);
}
Example #2
Source File: status-chart.tsx From backstage with Apache License 2.0 | 4 votes |
export function StatusChart(props: StatusChartProps) {
const { analysis } = props;
const { zoomFilterValues } = useZoom();
const { zoomProps, getZoomArea } = useZoomArea();
const values = useMemo(() => {
return analysis.daily.values.map(value => {
const totTriggers = analysis.daily.triggerReasons.reduce(
(prev, cur) => prev + (value[cur as TriggerReason] ?? 0),
0,
);
if (!totTriggers) {
return value;
}
return {
...value,
...Object.fromEntries(
analysis.daily.triggerReasons.map(reason => [
reason,
(value[reason as TriggerReason] ?? 0) / totTriggers,
]),
),
};
});
}, [analysis.daily]);
const triggerReasonLegendPayload = useMemo(
(): NonNullable<LegendProps['payload']> =>
analysis.daily.triggerReasons.map(reason => ({
value: humanTriggerReason(reason),
type: 'line',
id: reason,
color: triggerColorMap[reason as TriggerReason] ?? '',
})),
[analysis.daily.triggerReasons],
);
const statusesLegendPayload = useMemo(
(): NonNullable<LegendProps['payload']> =>
analysis.daily.statuses.map(status => ({
value: capitalize(status),
type: 'line',
id: status,
color: statusColorMap[status as FilterStatusType] ?? '',
})),
[analysis.daily.statuses],
);
const legendPayload = useMemo(
(): NonNullable<LegendProps['payload']> => [
...triggerReasonLegendPayload,
...statusesLegendPayload,
],
[statusesLegendPayload, triggerReasonLegendPayload],
);
const tooltipFormatter = useMemo(() => {
const reasonSet = new Set(analysis.daily.triggerReasons);
return (percentOrCount: number, name: string) => {
const label = reasonSet.has(name)
? humanTriggerReason(name)
: capitalize(name);
const valueText = reasonSet.has(name)
? `${(percentOrCount * 100).toFixed(0)}%`
: percentOrCount;
return [
<span>
{label}: {valueText}
</span>,
null,
];
};
}, [analysis.daily.triggerReasons]);
const zoomFilteredValues = useMemo(
() => zoomFilterValues(values),
[values, zoomFilterValues],
);
const barSize = getBarSize(analysis.daily.values.length);
return (
<Accordion defaultExpanded={analysis.daily.statuses.length > 1}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>
Build count per status over build trigger reason
</Typography>
</AccordionSummary>
<AccordionDetails>
{values.length === 0 ? (
<Alert severity="info">No data</Alert>
) : (
<ResponsiveContainer width="100%" height={140}>
<ComposedChart data={zoomFilteredValues} {...zoomProps}>
<Legend payload={legendPayload} />
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="__epoch"
type="category"
tickFormatter={tickFormatterX}
/>
<YAxis yAxisId={1} type="number" tickCount={5} name="Count" />
<YAxis yAxisId={2} type="number" name="Triggers" hide />
<Tooltip
labelFormatter={labelFormatterWithoutTime}
formatter={tooltipFormatter}
/>
{triggerReasonLegendPayload.map(reason => (
<Fragment key={reason.id}>
<Area
isAnimationActive={false}
type="monotone"
dataKey={reason.id!}
stackId="triggers"
yAxisId={2}
stroke={triggerColorMap[reason.id as TriggerReason] ?? ''}
fillOpacity={0.5}
fill={triggerColorMap[reason.id as TriggerReason] ?? ''}
/>
</Fragment>
))}
{[...analysis.daily.statuses].reverse().map(status => (
<Fragment key={status}>
<Bar
isAnimationActive={false}
type="monotone"
barSize={barSize}
dataKey={status}
stackId="statuses"
yAxisId={1}
stroke={statusColorMap[status as FilterStatusType] ?? ''}
fillOpacity={0.8}
fill={statusColorMap[status as FilterStatusType] ?? ''}
/>
</Fragment>
))}
{getZoomArea({ yAxisId: 1 })}
</ComposedChart>
</ResponsiveContainer>
)}
</AccordionDetails>
</Accordion>
);
}