JSFiddle - React, Tailwind, and code Playground

by lchau

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.js"></script>

SCSS

.etch-donut-chart__legend {
  font-family: sans-serif;
}
.etch-donut-chart__legend--title {
  font-weight: bold;
}
.etch-donut-chart__legend--category {
  text-anchor: start;
}
.etch-donut-chart__legend--count {
  text-anchor: end;
}

JavaScript

var options = {
  legend: {
    title: 'BREAKDOWN',
    color: true
  }
};

var DEFAULT_LEGEND_CONFIG = {
  sortDirection: 'ascending',
  width: 300,
  height: 300,
  color: true
};

options = _.merge({
  legend: DEFAULT_LEGEND_CONFIG
}, options);

var getCssValue = function(element, cssProperty) {
  var style = window.getComputedStyle(element);
  var value = style.getPropertyValue(cssProperty);
  return parseFloat(value, 10);
};

var data = [{
  "count": 1,
  "category": "High"
}, {
  "count": 15,
  "category": "Low"
}, {
  "count": 40,
  "category": "Everything else"
}, {
  "count": 20,
  "category": "Medium"
}, {
  "count": 5,
  "category": "Critical"
}, {
  "count": 10,
  "category": "Fatal"
}];

var sortDirection = _.get(options, 'legend.sortDirection');
sortDirection = sortDirection === 'ascending' ? sortDirection : 'descending';
var comparator = d3[sortDirection];

data = data.sort(function(a, b) {
  return comparator.call(null, a.count, b.count);
});

var width = 500,
  height = 300;

var svg = d3.select('body')
  .append('svg').attr({
    width: width,
    height: height
  });

var colors = d3.scale.category10();
var textHeight = 20;
var boxWidth = 5;
var boxHeight = 5;
var boxPadding = 5;

var x = 50,
  y = 10;

// templates
var translate = _.wrap(_.template('translate(${x}, ${y})'), function(template, x, y) {
  return template.call(null, {
    x: x,
    y: y
  });
});

var ROOT_STYLE = 'etch-donut-chart__legend';
var bemClassName = _.memoize(function(modifier) {
  return ROOT_STYLE + '--' + modifier;
});

var legend = svg.append('g')
  .classed(ROOT_STYLE, true)
  .attr('transform', translate(x, y));

if (_.get(options, 'legend.title')) {
  var title = legend
    .append('text')
    .classed(bemClassName('title'), true)
    .attr('display', 'none')
    .attr('dy', '0.35em')
    .text(_.get(options, 'legend.title'))
    .attr('text-anchor', 'start');


  var key = legend.append('g')
    .classed(bemClassName('key'), true)
    .attr('transform',...