JSFiddle - React, Tailwind, and code Playground

by Nivaldo

HTML

<button id="update">Update</button>
<div id="graphArea"></div>

CSS

.bar-outer {
    fill: green;
}
.bar-inner {
    fill: red;
}

JavaScript

var labels = ['Opens', 'Clicks', 'Unsubscribe'],
    data = [4, 8, 15],
    chart,
    x,
    y,
    gap = 2,
    width = 450,
    leftWidth = 100,
    barHeight = 40,
    barHeightInner = (barHeight / 2),
    barTopMargin = (barHeight - barHeightInner) / 2,
    height = (barHeight + gap * 2) * labels.length + 30;

/*  SET SVG + LEFT MARGIN       */
chart = d3.select("#graphArea")
    .append('svg')
    .attr('class', 'chart')
    .attr('width', leftWidth + width + 20)
    .attr('height', height)
    .append("g")
    .attr("transform", "translate(10, 20");

x = d3.scale.linear()
    .domain([0, d3.max(data)])
    .range([0, width]);

y = d3.scale.ordinal()
    .domain(data)
    .rangeBands([0, (barHeight + 2 * gap) * labels.length], 0.05);

/* CREATE BARS  */
chart.selectAll(".bar-outer")
    .data(data)
    .enter().append("rect")
    .attr("x", leftWidth)
    .attr("y", y)
    .attr("width", x)
    .attr("height", y.rangeBand())
    .attr('class', 'bar-outer');

/* INNER BARS   */
chart.selectAll(".bar-inner")
    .data(data)
    .enter().append("rect")
    .attr("x", leftWidth)
    .attr("y", function (d) {
    return y(d) + barTopMargin
})
    .attr("width", function (d) {
    return x(d) / 2;
})
    .attr("height", barHeightInner)
    .attr('class', 'bar-inner');



/* SET NAMED LABELS    */
chart.selectAll("text.label")
    .data(labels)
    .enter().append("text")
    .attr("x", leftWidth / 2 + 40)
    .attr("y", function (d, i) {
    return i * y.rangeBand() + 20;
})
    .attr("dy", ".35em")
    .attr("text-anchor", "end")
    .attr('class', 'label')
    .text(String);

function update() {
    data = [20, 10, 3];
    
    // must re-set scale domains with the new data
    x.domain([0, d3.max(data)]);
    y.domain(data);

    var outer = chart.selectAll(".bar-outer")
        .data(data);
    
    // exit selection
    outer
        .exit()
        .remove();
    
    // enter selection
    outer
      .enter()
      .append("rect")
        .attr('class',...