Drag & Drop

by webgleb

HTML

<div class="row">
        <div class="placeholder">
            <div class="col-header start">Начать</div>
            <div class="item" draggable="true">Перетащи меня</div>
        </div>
        <div class="placeholder">
            <div class="col-header progress">В процессе</div>
        </div>
        <div class="placeholder">
            <div class="col-header done">Готовы</div>
        </div>
    </div>

CSS

@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');

* {
    box-sizing: border-box;
}

body {
    font-family: 'Roboto', sans-serif;
    background-color: #e5e5e5;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    overflow: hidden;
    width: 100%;

}

.row {
    margin-bottom: 1rem;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr 1fr;
    gap: 20px 20px;
}

.col-header {
    width: calc(100% + 20px);
    box-shadow: 4px 4px 9px rgba(198, 198, 198, 0.36);
    color: #fff;
    text-align: center;
    padding: 15px 0;
    margin: 0 -10px 15px -10px;
}

.item {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid #eee;
    box-shadow: 4px 4px 9px rgba(198, 198, 198, 0.36);
    border-radius: 10px;
    background: #f7f6f7;
    padding: 0.8rem 1rem;
    margin: 0 10px;
    color: #828282;
    text-align: center;
    cursor: grab;
}

.item:active {
    cursor: grabbing;
}

.placeholder {
    width: 270px;
    height: 80vh;
    min-height: 100px;
    box-sizing: border-box;
    border: 1px dashed #8a8a8a;
    border-radius: 5px;
    padding: 0 10px 10px 10px;
    background: #fff;
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.start {
    background: linear-gradient(90deg, #ff85e4 0%, #229efd 179.25%);
}

.progress {
    background: linear-gradient(90deg, #209cff 0%, #68e0cf 100%);
}

.done {
    background: linear-gradient(90deg, #84fab0 0%, #8fd3f4 100%);
}

.hold {
    border: 3px solid #eeeeee;
}

.hide {
    display: none;
}

.hovered {
    box-shadow: #9D9C9C 0 0 12px 6px;
}

JavaScript

const items = document.querySelectorAll('.item');
const placeholders = document.querySelectorAll('.placeholder');
let current = null

items.forEach((item) => {
    item.addEventListener('dragstart', event => {
        current = event.target
        event.target.classList.add('hold')
        setTimeout(() => {
            event.target.classList.add('hide')
        }, 0)
    })
    item.addEventListener('dragend', event => {
        event.target.className = 'item';
        current = null
    })
})

placeholders.forEach((placeholder) => {
    placeholder.addEventListener('dragover', event => {
        event.preventDefault();
        if (!event.target.classList.contains('placeholder')) return;
    })

    placeholder.addEventListener('dragenter', event => {
        console.log('dragenter')
        if (!event.target.classList.contains('placeholder')) return;
        event.target.classList.add('hovered')
    })

    placeholder.addEventListener('dragleave', event => {
        console.log('dragleave')
        if (!event.target.classList.contains('placeholder')) return;
        event.target.classList.remove('hovered')
    })

    placeholder.addEventListener('drop', event => {
        console.log('dragdrop')
        if (!event.target.classList.contains('placeholder')) return;
        event.target.classList.remove('hovered')
        event.target.append(current);
    })
})