JSFiddle - React, Tailwind, and code Playground

HTML

<div id="container"></div>

CSS

#container {
   float: left;
}

.row {    
   height: 20px;
   margin: 3px;
   background: lightblue;
   clear: both;
   float: left;
} 
    
.col {
   float: left;
   height: 20px;
   width: 20px;
   margin-right: 5px;
}

.covered {
   color: blue;
   background-color: blue;
}
        
.covered-mine {
   color: blue;
   background-color: blue !important;
}
.mine {
   background-color: red;
}
.maybe-mine {
    color: orange;
    background-color: orange;
}

JavaScript

$(function() {

    var MinesweeperBoard = function(rows, cols, nmines) {
        var self = this;

        self.init = function(el) {
            var i, j, k, curNode, rowHtml = '<div class="row"></div>',
                colHtml = '<div class="col covered">0</div>';

            self.$rootEl = $(el);

            for (i = 0; i < rows; i++) {
                curNode = $(rowHtml).appendTo(self.$rootEl);
                for (j = 0; j < cols; j++) {
                    $(curNode).append(colHtml);
                }
            }

            for (k = 0; k < nmines; k++) {
                self.addMine();
            }

        }

        self.addMine = function() {
            // Get a random row# and col#
            var rRow = Math.floor(Math.random() * rows),
                rCol = Math.floor(Math.random() * cols),
                $el = self.$rootEl.children().eq(rRow).children().eq(rCol);

            // If it's not already a mine, add one
            // Todo: pick another site if there's already a mine.
            if (!$el.hasClass("mine")) {
                $el.addClass("mine covered-mine");
                $el.text("M");
                self.incrementNeighbors(rRow, rCol);
            }

        }
        self.incrementNeighbors = function(row, col) {
            $(".row").slice(Math.max(0, row - 1), row + 2).each(function() {
                $(this).children().slice(Math.max(0, col - 1), col + 2).each(function() {
                    self.incrementNode($(this));
                });
            });
        }
        self.incrementNode = function($el) {
            if (!$el.hasClass("mine")) {
                var eText = parseInt($el.text(), 10);
                $el.text(eText + 1);
            }
        }

        return self;
    }
    var board = new MinesweeperBoard(15, 15, 20);
    board.init("#container");

    $(".col").bind("contextmenu", function(e) {
        e.preventDefault();
        $(this).toggleClass("maybe-mine");
        return false;
    });
 ...