JSFiddle - React, Tailwind, and code Playground

by Margus Martsepp

HTML

<script src="http://d3js.org/d3.v3.min.js"></script>

CSS

@import url(//fonts.googleapis.com/css?family=Open+Sans:400,700);

svg {
  font: 14px 'Open Sans';
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.axis text {
  fill: #000;
}

.axis .tick line {
  stroke: rgba(0, 0, 0, 0.1);
}

.area {
  stroke-width: 1;
}

.area.outer,
.legend .outer {
  fill: rgba(230, 230, 255, 0.8);
  stroke: rgba(216, 216, 255, 0.8);
}

.area.inner,
.legend .inner {
  fill: rgba(127, 127, 255, 0.8);
  stroke: rgba(96, 96, 255, 0.8);
}

.median-line,
.legend .median-line {
  fill: none;
  stroke: #000;
  stroke-width: 3;
}

.legend .legend-bg {
  fill: rgba(0, 0, 0, 0.5);
  stroke: rgba(0, 0, 0, 0.5);
}

.marker.client .marker-bg,
.marker.client path {
  fill: rgba(255, 127, 0, 0.8);
  stroke: rgba(255, 127, 0, 0.8);
  stroke-width: 3;
}

.marker.server .marker-bg,
.marker.server path {
  fill: rgba(0, 153, 51, 0.8);
  stroke: rgba(0, 153, 51, 0.8);
  stroke-width: 3;
}

.marker path {
  fill: none;
}

.legend text,
.marker text {
  fill: #fff;
  font-weight: bold;
}

.marker text {
  text-anchor: middle;
}

JavaScript

function addAxesAndLegend (svg, xAxis, yAxis, margin, chartWidth, chartHeight) {
  var legendWidth  = 200,
      legendHeight = 100;

  // clipping to make sure nothing appears behind legend
  svg.append('clipPath')
    .attr('id', 'axes-clip')
    .append('polygon')
      .attr('points', (-margin.left)                 + ',' + (-margin.top)                 + ' ' +
                      (chartWidth - legendWidth - 1) + ',' + (-margin.top)                 + ' ' +
                      (chartWidth - legendWidth - 1) + ',' + legendHeight                  + ' ' +
                      (chartWidth + margin.right)    + ',' + legendHeight                  + ' ' +
                      (chartWidth + margin.right)    + ',' + (chartHeight + margin.bottom) + ' ' +
                      (-margin.left)                 + ',' + (chartHeight + margin.bottom));

  var axes = svg.append('g')
    .attr('clip-path', 'url(#axes-clip)');

  axes.append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + chartHeight + ')')
    .call(xAxis);

  axes.append('g')
    .attr('class', 'y axis')
    .call(yAxis)
    .append('text')
      .attr('transform', 'rotate(-90)')
      .attr('y', 6)
      .attr('dy', '.71em')
      .style('text-anchor', 'end')
      .text('Time (s)');

  var legend = svg.append('g')
    .attr('class', 'legend')
    .attr('transform', 'translate(' + (chartWidth - legendWidth) + ', 0)');

  legend.append('rect')
    .attr('class', 'legend-bg')
    .attr('width',  legendWidth)
    .attr('height', legendHeight);

  legend.append('rect')
    .attr('class', 'outer')
    .attr('width',  75)
    .attr('height', 20)
    .attr('x', 10)
    .attr('y', 10);

  legend.append('text')
    .attr('x', 115)
    .attr('y', 25)
    .text('5% - 95%');

  legend.append('rect')
    .attr('class', 'inner')
    .attr('width',  75)
    .attr('height', 20)
    .attr('x', 10)
    .attr('y', 40);

  legend.append('text')
    .attr('x', 115)
    .attr('y', 55)
    .text('25% -...