JSFiddle - React, Tailwind, and code Playground
by muter
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.min.js"></script>
<div class="drag-container">
<ul class="drag-list">
<li class="drag-column drag-column-to-do">
<span class="drag-column-header">
<h2>待辦 / To Do</h2>
<svg class="drag-header-more" data-target="options1" fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /</svg>
</span>
<div class="drag-options" id="options1"></div>
<ul class="drag-inner-list" id="1">
<li class="drag-item"><p>[頻道] 開放投稿功能</p></li>
<li class="drag-item"><p>[機械人] 增加投稿功能</p></li>
<li class="drag-item"><p>[模板] 提升特殊樣式兼容性</p></li>
</ul>
</li>
<li class="drag-column drag-column-in-progress">
<span class="drag-column-header">
<h2>進行中 / In Progress</h2>
<svg class="drag-header-more" data-target="options2" fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /</svg>
</span>
<div class="drag-options" id="options2"></div>
<ul class="drag-inner-list" id="2">
<li class="drag-item"><p>[模板] 適配關聯文章</p></li>
<li class="drag-item"><p>[機械人] 支援Inline模式</p></li>
<li class="drag-item"><p>[機械人] 支援解析通過Matters PWA直接分享的文章連結</p></li>
</ul>
</li>
<!--
<li class="drag-column drag-column-needs-review">
<span class="drag-column-header">
<h2>Needs Review</h2>
<svg data-target="options3" class="drag-header-more" fill="#FFFFFF"...
SCSS
$ease-out: all .3s cubic-bezier(0.23, 1, 0.32, 1);
$to-do: #4A9FF9;
$in-progress: #f9944a;
$needs-review: #F4CE46;
$approved: #2ac06d;
* {
box-sizing: border-box;
}
body {
background: #FFFFFF;
color: white;
font-family: 'Noto San TC, Muli';
font-weight: 300;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.drag-container {
max-width: 1000px;
margin: 20px auto;
}
.drag-list {
display: flex;
align-items: flex-start;
@media (max-width: 690px) {
display: block;
}
}
.drag-column {
flex: 1;
margin: 0 10px;
position: relative;
background: rgba(black, 0.2);
overflow: hidden;
@media (max-width: 690px) {
margin-bottom: 30px;
}
h2 {
font-size: 0.8rem;
margin: 0;
color: white;
text-transform: uppercase;
font-weight: 600;
}
&-to-do {
.drag-column-header,
.is-moved,
.drag-options {
background: $to-do;
}
}
&-in-progress {
.drag-column-header,
.is-moved,
.drag-options {
background: $in-progress;
}
}
&-needs-review {
.drag-column-header,
.is-moved,
.drag-options {
background: $needs-review;
}
}
&-approved {
.drag-column-header,
.is-moved,
.drag-options {
background: $approved;
}
}
}
.drag-column-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
}
.drag-inner-list {
position: relative;
border: 5px solid transparent;
min-height: 95px;
}
.drag-item {
margin: 5px;
position: relative;
padding: 10px;
background: #fff;
border-radius: 4px;
cursor: pointer;
-webkit-box-shadow: 0px 1px 3px 0 rgba(0, 0, 0, 0.2);
box-shadow: 0px 1px 3px 0 rgba(0, 0, 0, 0.2);
transition: $ease-out;
&.is-moving {
transform: scale(1.1);
background: rgba(black, 0.2);
}
p {
display: block;
color: black;
margin-block-start: 0px;
margin-block-end:...
JavaScript
dragula([
document.getElementById('1'),
document.getElementById('2'),
document.getElementById('3'),
document.getElementById('4'),
document.getElementById('5')
])
.on('drag', function(el) {
// add 'is-moving' class to element being dragged
el.classList.add('is-moving');
})
.on('dragend', function(el) {
// remove 'is-moving' class from element after dragging has stopped
el.classList.remove('is-moving');
// add the 'is-moved' class for 600ms then remove it
window.setTimeout(function() {
el.classList.add('is-moved');
window.setTimeout(function() {
el.classList.remove('is-moved');
}, 600);
}, 100);
});
var createOptions = (function() {
var dragOptions = document.querySelectorAll('.drag-options');
// these strings are used for the checkbox labels
var options = ['模板', '頻道', '機械人'];
// create the checkbox and labels here, just to keep the html clean. append the <label> to '.drag-options'
function create() {
for (var i = 0; i < dragOptions.length; i++) {
options.forEach(function(item) {
var checkbox = document.createElement('input');
var label = document.createElement('label');
var span = document.createElement('span');
checkbox.setAttribute('type', 'checkbox');
span.innerHTML = item;
label.appendChild(span);
label.insertBefore(checkbox, label.firstChild);
label.classList.add('drag-options-label');
dragOptions[i].appendChild(label);
});
}
}
return {
create: create
}
}());
var showOptions = (function() {
// the 3 dot icon
var more = document.querySelectorAll('.drag-header-more');
function show() {
// show 'drag-options' div when the more icon is clicked
var target = this.getAttribute('data-target');
var options = document.getElementById(target);
options.classList.toggle('active');
}
function init() {
for (i = 0; i < more.length; i++)...