Diverging Bars
Two bars diverging from a centre line, each split into an accented sub-segment (e.g. shots -> on target). Widths scale to the larger total.
import * as React from "react";
export interface DivergingBarsProps {
/** left value + its split into a highlighted (e.g. on-target) sub-portion. */
left: { total: number; accent?: number; color: string };
right: { total: number; accent?: number; color: string };
/** dim opacity for the non-accent portion. */
dim?: number;
height?: number;
className?: string;
}
/**
* Two bars diverging from a centre line, each optionally split into an accented
* sub-segment (e.g. shots -> on-target). Widths scale to the larger total.
*/
export function DivergingBars({ left, right, dim = 0.32, height = 22, className }: DivergingBarsProps) {
const mx = Math.max(left.total, right.total, 1);
const seg = (w: number, color: string, op: number) => (
<div style={{ width: `${w}%`, height: "100%", background: color, opacity: op }} />
);
const la = left.accent ?? 0;
const ra = right.accent ?? 0;
return (
<div className={className} style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
<div style={{ display: "flex", justifyContent: "flex-end", height }}>
<div style={{ width: `${(left.total / mx) * 100}%`, height: "100%", display: "flex" }}>
{seg(left.total ? ((left.total - la) / left.total) * 100 : 0, left.color, dim)}
{seg(left.total ? (la / left.total) * 100 : 0, left.color, 1)}
</div>
</div>
<div style={{ display: "flex", justifyContent: "flex-start", height }}>
<div style={{ width: `${(right.total / mx) * 100}%`, height: "100%", display: "flex" }}>
{seg(right.total ? (ra / right.total) * 100 : 0, right.color, 1)}
{seg(right.total ? ((right.total - ra) / right.total) * 100 : 0, right.color, dim)}
</div>
</div>
</div>
);
}