JSFiddle - React, Tailwind, and code Playground

HTML

<!DOCTYPE html>
<html>

  <head>
    <meta charset="UTF-8">
  </head>

  <body>
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
    </svg>
  </body>

</html>

CSS

body {
  height: 100vh;
  margin: 0;
}

svg {
  pointer-events: none;
  user-select: none;
  vertical-align: bottom;
  /* fjern inline-baseline */
  font-family: serif;
  font-size: 14pt;
}

svg .lines,
svg .notches {
  fill: none;
  stroke: #999;
}

svg .border {
  fill: none;
  stroke: #999;
  stroke-width: 2;
}

svg .ring .highlight {
  stroke: none;
  fill: greenyellow;
  fill-opacity: 0.25;
}

svg .now {
  stroke: red;
  stroke-opacity: 0.3;
  stroke-width: 1;
  fill: none;
}

JavaScript

const tick = false; // tick every second (true) or move smoothly (false)
const monthnames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const daynames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
let numYears = 13;

// Segmented svg ring + static svg element creation helper function
class Ring {

  static generateId() {
    Ring.idCounter++;
    return 'ring' + Ring.idCounter;
  }

  static mkSvgElem(name, attrs, cssClass = null) {
    let elem = document.createElementNS('http://www.w3.org/2000/svg', name);
    for (let attr of Object.keys(attrs)) {
      elem.setAttribute(attr, attrs[attr]);
    }
    if (cssClass) {
      elem.classList.add(cssClass);
    }
    return elem;
  }

  constructor(parent, outerRadius, innerRadius, labels, baseline = 0.5, vert = false) {
    this.labels = labels;
    this.slices = labels.length;
    this.texts = [];
    this.g = Ring.mkSvgElem('g', {}, 'ring');

    const TWOPI = Math.PI + Math.PI;
    const arc = TWOPI / this.slices;
    const large = (arc > Math.PI ? '1' : '0');
    const notches = [];
    const radius = innerRadius + (outerRadius - innerRadius) * baseline; // middle
    this.g.appendChild(Ring.mkSvgElem('circle', {
      r: innerRadius
    }, 'lines'));
    this.g.appendChild(this.mkHighlight(innerRadius, outerRadius, arc, large));
    let i = 0;
    // generate arcs with text + notch lines
    for (let label of labels) {
      let angle = i / this.slices * TWOPI - Math.PI / 2;
      notches.push(
        'M', innerRadius * Math.cos(angle), innerRadius * Math.sin(angle),
        'L', outerRadius * Math.cos(angle), outerRadius * Math.sin(angle)
      );
      let d;
      if (vert) {
        let a2 = angle + arc / 2;
        d = [
          'M', innerRadius * Math.cos(a2), innerRadius * Math.sin(a2),
          'L', outerRadius * Math.cos(a2), outerRadius * Math.sin(a2)
        ]
      } else {
      ...