JSFiddle - React, Tailwind, and code Playground

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/sortable/0.8.0/css/sortable-theme-bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/sortable/0.8.0/js/sortable.js"></script>
<table class="sortable-theme-bootstrap" id="test">
  <thead>
    <tr>
      <th>Browser</th>
      <th>Usage</th>
      <th>Initial release</th>
      <th data-sortable-type="version">Stable version</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Opera</td>
      <td>1.03%</td>
      <td data-value="1994">Late 1994</td>
      <td>1.9.2.0</td>
    </tr>
    <tr>
      <td>Firefox</td>
      <td>20.01%</td>
      <td data-value="2002">September 23, 2002</td>
      <td>1.8.0.1</td>
    </tr>
    <tr>
      <td>Chrome</td>
      <td>42.68%</td>
      <td data-value="2008">September 2, 2008</td>
      <td>1.14.2.0</td>
    </tr>
  </tbody>
</table>

JavaScript

var customTypes = [{
  name: 'version',
  defaultSortDirection: 'descending',
  match: function(a) {
    return a.match(/([1-9]+\.?)+/g);
  },
  compare: function (a, b) {
    console.log('running');
    var i, cmp, len, re = /(\.0)+[^\.]*$/;
    a = (a + '').replace(re, '').split('.');
    b = (b + '').replace(re, '').split('.');
    len = Math.min(a.length, b.length);
    for( i = 0; i < len; i++ ) {
      cmp = parseInt(a[i], 10) - parseInt(b[i], 10);
      if( cmp !== 0 ) {
        return cmp;
      }
    }
    return a.length - b.length;
  }
}];

var customAndOriginalTypes = Sortable.types.concat(customTypes);
Sortable.setupTypes(customAndOriginalTypes);

// We can't initialise the sorting first with data-sortable or the new type doesn't exist when it gets initialised. Might just be something to do with jsfiddle, but it works
exampleTable = document.querySelector('#test');
Sortable.initTable(exampleTable);