Step Histogram — MUI X Charts

A histogram displayed as step lines (outline only) without filled bars. The distribution is shown as connected horizontal and vertical line segments, creating a step function appearance.

Step Histogram rendered with MUI X Charts

Renders

JavaScript source (MUI X Charts)

// anyplot.ai
// histogram-stepwise: Step Histogram
// Library: muix 7.29.1 | JavaScript 22.23.2
// Quality: 91/100 | Created: 2026-09-05
import { LineChart } from "@mui/x-charts/LineChart";
import { ChartsReferenceLine } from "@mui/x-charts/ChartsReferenceLine";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";

const t = window.ANYPLOT_TOKENS;

// --- Data (in-memory, deterministic) ---------------------------------------
// Tiny fixed-seed LCG — the browser has no seeded RNG.
function makeLcg(seed: number) {
  let state = seed >>> 0;
  return function next() {
    state = (Math.imul(state, 1664525) + 1013904223) >>> 0;
    return state / 4294967296;
  };
}

function randNormal(rng: () => number) {
  const u1 = Math.max(rng(), 1e-9);
  const u2 = rng();
  return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
}

const rng = makeLcg(42);
const SAMPLE_SIZE = 800;

// API response latency (ms) before / after an optimization pass.
const latencyV1 = Array.from({ length: SAMPLE_SIZE }, () =>
  Math.max(8, 118 + randNormal(rng) * 22),
);
const latencyV2 = Array.from({ length: SAMPLE_SIZE }, () =>
  Math.max(8, 92 + randNormal(rng) * 16),
);

const BIN_COUNT = 26;
const allValues = latencyV1.concat(latencyV2);
const minValue = Math.min(...allValues);
const maxValue = Math.max(...allValues);
const binWidth = (maxValue - minValue) / BIN_COUNT;
const binEdges = Array.from({ length: BIN_COUNT + 1 }, (_, i) => minValue + i * binWidth);

function binCounts(values: number[]) {
  const counts = new Array(BIN_COUNT).fill(0);
  for (const value of values) {
    const index = Math.min(BIN_COUNT - 1, Math.floor((value - minValue) / binWidth));
    counts[index] += 1;
  }
  return counts;
}

// One x-point per bin edge (not per corner) — MUI X's native `curve="stepAfter"`
// draws the horizontal/vertical step segments itself. The leading edge is
// duplicated once (0 -> count[0]) so the outline rises from zero, and a
// trailing 0 closes it back to the axis at the final edge.
const stepX = [binEdges[0], binEdges[0], ...binEdges.slice(1)];
const countsV1 = binCounts(latencyV1);
const countsV2 = binCounts(latencyV2);
const stepV1 = [0, ...countsV1, 0];
const stepV2 = [0, ...countsV2, 0];

// Bin-center of each distribution's tallest bar — used to call out the
// before/after latency shift with reference lines.
function peakCenter(counts: number[]) {
  const peakIndex = counts.indexOf(Math.max(...counts));
  return (binEdges[peakIndex] + binEdges[peakIndex + 1]) / 2;
}

const peakV1 = peakCenter(countsV1);
const peakV2 = peakCenter(countsV2);

// --- Chart (default-exported component — the harness mounts it) -------------
export default function Chart() {
  const W = window.ANYPLOT_SIZE.width;
  const H = window.ANYPLOT_SIZE.height;
  const CHART_TOP = 64;

  const title = "histogram-stepwise · javascript · muix · anyplot.ai";
  const titleSize = title.length > 67 ? Math.round((22 * 67) / title.length) : 22;

  return (
    <Box sx={{ position: "relative", width: W, height: H, bgcolor: t.pageBg }}>
      <Box sx={{ position: "absolute", top: 20, left: 56, right: 56 }}>
        <Typography sx={{ color: t.ink, fontSize: titleSize, fontWeight: 500 }}>{title}</Typography>
      </Box>
      <Box sx={{ position: "absolute", top: CHART_TOP, left: 0, right: 0, bottom: 0 }}>
        <LineChart
          width={W}
          height={H - CHART_TOP}
          skipAnimation
          series={[
            {
              data: stepV1,
              label: "API v1 latency",
              color: t.palette[0],
              curve: "stepAfter",
              area: false,
              showMark: false,
            },
            {
              data: stepV2,
              label: "API v2 latency",
              color: t.palette[1],
              curve: "stepAfter",
              area: false,
              showMark: false,
            },
          ]}
          xAxis={[
            {
              data: stepX,
              scaleType: "linear",
              label: "Response latency (ms)",
              labelStyle: { fontSize: 16 },
              tickLabelStyle: { fontSize: 14 },
              valueFormatter: (value: number) => value.toFixed(0),
            },
          ]}
          yAxis={[
            {
              label: "Count",
              labelStyle: { fontSize: 16 },
              tickLabelStyle: { fontSize: 14 },
            },
          ]}
          grid={{ horizontal: true }}
          slotProps={{ legend: { labelStyle: { fontSize: 14 } } }}
          sx={{ "& .MuiLineElement-root": { strokeWidth: 3 } }}
        >
          <ChartsReferenceLine
            x={peakV1}
            label={`v1 peak ~${peakV1.toFixed(0)}ms`}
            labelStyle={{ fontSize: 13, fill: t.palette[0] }}
            lineStyle={{ stroke: t.palette[0], strokeDasharray: "6 4" }}
          />
          <ChartsReferenceLine
            x={peakV2}
            label={`v2 peak ~${peakV2.toFixed(0)}ms`}
            labelStyle={{ fontSize: 13, fill: t.palette[1] }}
            lineStyle={{ stroke: t.palette[1], strokeDasharray: "6 4" }}
          />
        </LineChart>
      </Box>
    </Box>
  );
}

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/histogram-stepwise/muix/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "histogram-stepwise",
  "language": "javascript",
  "library": "muix",
  "page": "https://anyplot.ai/histogram-stepwise/javascript/muix",
  "hub": "https://anyplot.ai/histogram-stepwise",
  "code_json": "https://api.anyplot.ai/specs/histogram-stepwise/muix/code",
  "spec_json": "https://api.anyplot.ai/specs/histogram-stepwise",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/histogram-stepwise/javascript/muix/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/histogram-stepwise/javascript/muix/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/histogram-stepwise/javascript/muix/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/histogram-stepwise/javascript/muix/plot-dark.html",
  "quality_score": 91.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Step Histogram on anyplot.ai.

Other implementations