The Kit/Components

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.

loading…
DivergingBars.tsx
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>
  );
}
← The whole kit