JSFiddle - React, Tailwind, and code Playground
HTML
<div class="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
</div>
CSS
.container {
display: flex;
justify-content: space-between;
width: 700px;
}
.item {
font-size: 40px;
width: 100px;
height: 100px;
outline: 1px solid #ccc;
text-align: center;
line-height: 100px;
cursor: pointer;
transition: background-color 0.5s ease;
background-color: yellow;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.item:hover {
background-color: lightblue;
}
.item.active {
outline: 2px solid red;
}
Babel + JSX
const active = [];
const items = Array.from(document.querySelectorAll('.item'));
function activateRow (item1, item2) {
const a = items.indexOf(item1);
const b = items.indexOf(item2);
items
.slice( Math.min(a,b), Math.max(a,b)+1 )
.map( addActive );
}
function activateSingle (item, isForced) {
const isActive = active.indexOf( item ) >= 0;
if (isForced) deactivateAll();
isActive
? removeActive( item )
: addActive( item );
}
function addActive (item, isActive) {
item.classList.add('active');
active.push(item);
}
function removeActive (item) {
item.classList.remove('active');
active.splice( active.indexOf(item), 1 );
}
function deactivateAll () {
active.map( item => item.classList.remove('active') );
active.length = 0;
}
items.map(item => {
item.addEventListener('click', event => {
if (event.shiftKey && items.length) {
activateRow( active[active.length - 1], item );
} else {
activateSingle( item, !event.ctrlKey );
}
});
});