JSFiddle - React, Tailwind, and code Playground

HTML

<div style="overflow-x: hidden;">
        
        <div id="holder">
        
        <h1>Ristikko</h1>
        
        </div>
        </div>

CSS

#holder {
    transform: translateX(45%);
}

.pipe {
    text-align: left;
    white-space: nowrap;
    display: block;
}


.pipe div {
    display: inline-block;
    border: 1px solid black;
    min-width: 2.4em;
    min-height: 2.4em;
    line-height: 2.4em;
    font-size: 1.7em;
    text-align: center;
    user-select: none;
    pointer-events: none;
    font-family: monospace;
    font-variant-caps: all-petite-caps;
}



.pipe div.chosen {
    color: blue;
    background: lightgreen;
}

.pipe.arrow {
    pointer-events: none;
}

.pipe.arrow div {
    background: aliceblue;
}

JavaScript

class W {
    constructor(w) {
        this.w = w;
        this.n = w.length;
        this.element = document.createElement("div");
        this.element.classList.add("pipe");
        for (let c of w) {
            let box = document.createElement("div");
            box.innerHTML = c;
            this.element.appendChild(box);
            //box.onclick = function(e) {
            //    console.log(e);
            //};
        }
        this.element.children[0].classList.add("chosen");
        this.index = 0;
        this.isMoving = false;
        this.origP = null;
        this.element.onmousedown = (e) => {
            this.isMoving = true;
            this.origP = [e.clientX, e.clientY];
            //console.log(this.origP);
            Array.from(this.element.children).forEach((y)=>{y.classList.remove("chosen")});
            window.onmousemove = this.myMousemove;
            window.onmouseup = this.myMouseup;
        };
        this.myMousemove = (e) => {
            if (this.isMoving) {
                let diffX = e.clientX - this.origP[0];
                //let bW = +/[0-9]*/.exec(window.getComputedStyle(this.element.children[0]).width)[0];
                let bRect = this.element.children[0].getBoundingClientRect();
                let bW = bRect.right-bRect.left;
                this.element.style.transform = `translateX(${-bW*this.index+diffX}px)`;
            }
        };
        this.myMouseup = (e) => {
            this.isMoving = false;
            let diffX = e.clientX - this.origP[0];
            //let bW = +/[0-9]*/.exec(window.getComputedStyle(this.element.children[0]).width)[0];
            let bRect = this.element.children[0].getBoundingClientRect();
            let bW = bRect.right-bRect.left;
            //console.log("bw = ", bW);
            let indInc = Math.round(diffX/bW);
            this.index -= indInc;
            if (this.index<0) this.index = 0;
            if (this.index>=this.n) this.index = this.n-1;
           ...