Mouse Interactions
JavaScript components for drag-and-drop functionality.
Drag and Drop Manager
Comprehensive drag-and-drop with zones and callbacks.
⋮⋮
Draggable Item 1
⋮⋮
Draggable Item 2
⋮⋮
Draggable Item 3
Drop items here
HTML
<!-- Draggable items -->
<div
style="
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 24px;
"
>
<div
data-ss="draggable"
data-ss-draggable-handle=".drag-handle"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color_fill_secondary);
border-radius: 8px;
cursor: move;
"
>
<span class="ss-c-drag-handle" style="cursor: grab; opacity: 0.5">
⋮⋮
</span>
<span>Draggable Item 1</span>
</div>
<div
data-ss="draggable"
data-ss-draggable-handle=".drag-handle"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color_fill_secondary);
border-radius: 8px;
cursor: move;
"
>
<span class="ss-c-drag-handle" style="cursor: grab; opacity: 0.5">
⋮⋮
</span>
<span>Draggable Item 2</span>
</div>
<div
data-ss="draggable"
data-ss-draggable-handle=".drag-handle"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color_fill_secondary);
border-radius: 8px;
cursor: move;
"
>
<span class="ss-c-drag-handle" style="cursor: grab; opacity: 0.5">
⋮⋮
</span>
<span>Draggable Item 3</span>
</div>
</div>
<!-- Drop zone -->
<div
data-ss="dropzone"
data-ss-dropzone-accept=".task-card"
style="
min-height: 150px;
padding: 24px;
border: 2px dashed var(--color_line_secondary);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: var(--color_fill_secondary);
transition:
border-color 0.2s,
background 0.2s;
"
>
<span style="opacity: 0.6">Drop items here</span>
</div>
Kanban Board
Drag-and-drop kanban board implementation.
To Do
Design mockups
Due: Jan 25
Write documentation
Due: Jan 28
In Progress
Implement API
In progress...
Done
Setup project
Completed
HTML
<div
style="
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
"
>
<!-- To Do Column -->
<div
style="
background: var(--color_fill_secondary);
border-radius: 12px;
padding: 16px;
"
>
<h4
style="
margin: 0 0 16px;
font-size: 14px;
text-transform: uppercase;
opacity: 0.6;
"
>
To Do
</h4>
<div
data-ss="dropzone"
data-ss-dropzone-accept=".task-card"
style="
display: flex;
flex-direction: column;
gap: 8px;
min-height: 200px;
"
>
<div
class="ss-c-task-card"
data-ss="draggable"
style="
padding: 12px;
background: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
cursor: move;
"
>
<strong style="display: block; margin-bottom: 4px">
Design mockups
</strong>
<span style="font-size: 12px; opacity: 0.6">
Due: Jan 25
</span>
</div>
<div
class="ss-c-task-card"
data-ss="draggable"
style="
padding: 12px;
background: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
cursor: move;
"
>
<strong style="display: block; margin-bottom: 4px">
Write documentation
</strong>
<span style="font-size: 12px; opacity: 0.6">
Due: Jan 28
</span>
</div>
</div>
</div>
<!-- In Progress Column -->
<div
style="
background: var(--color_fill_secondary);
border-radius: 12px;
padding: 16px;
"
>
<h4
style="
margin: 0 0 16px;
font-size: 14px;
text-transform: uppercase;
opacity: 0.6;
"
>
In Progress
</h4>
<div
data-ss="dropzone"
data-ss-dropzone-accept=".task-card"
style="
display: flex;
flex-direction: column;
gap: 8px;
min-height: 200px;
"
>
<div
class="ss-c-task-card"
data-ss="draggable"
style="
padding: 12px;
background: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-left: 3px solid var(--color_state_warning);
cursor: move;
"
>
<strong style="display: block; margin-bottom: 4px">
Implement API
</strong>
<span style="font-size: 12px; opacity: 0.6">
In progress...
</span>
</div>
</div>
</div>
<!-- Done Column -->
<div
style="
background: var(--color_fill_secondary);
border-radius: 12px;
padding: 16px;
"
>
<h4
style="
margin: 0 0 16px;
font-size: 14px;
text-transform: uppercase;
opacity: 0.6;
"
>
Done
</h4>
<div
data-ss="dropzone"
data-ss-dropzone-accept=".task-card"
style="
display: flex;
flex-direction: column;
gap: 8px;
min-height: 200px;
"
>
<div
class="ss-c-task-card"
data-ss="draggable"
style="
padding: 12px;
background: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-left: 3px solid var(--color_state_success);
cursor: move;
opacity: 0.7;
"
>
<strong
style="
display: block;
margin-bottom: 4px;
text-decoration: line-through;
"
>
Setup project
</strong>
<span style="font-size: 12px; opacity: 0.6">
Completed
</span>
</div>
</div>
</div>
</div>
File Upload Drop Zone
Drag-and-drop file upload area.
▤
Drag & drop files here
or click to browse
⇩
Drop files to upload
▭
document.pdf
2.4 MB
✓
▭
image.jpg
1.8 MB - Uploading...
HTML
<!-- File drop zone -->
<div
data-ss="dropzone"
data-ss-dropzone-accept="*"
style="
padding: 48px;
border: 2px dashed var(--color_line_secondary);
border-radius: 16px;
text-align: center;
cursor: pointer;
transition: all 0.2s;
"
>
<div style="font-size: 48px; margin-bottom: 16px">▤</div>
<p style="margin: 0 0 8px; font-size: 18px; font-weight: 500">
Drag & drop files here
</p>
<p style="margin: 0; opacity: 0.6">or click to browse</p>
<input type="file" multiple style="display: none" />
</div>
<!-- Active drop state -->
<div
style="
margin-top: 16px;
padding: 48px;
border: 2px dashed var(--color_fill_primary);
border-radius: 16px;
text-align: center;
background: rgba(var(--color_fill_primary_rgb), 0.05);
"
>
<div style="font-size: 48px; margin-bottom: 16px">⇩</div>
<p
style="
margin: 0;
font-size: 18px;
font-weight: 500;
color: var(--color_fill_primary);
"
>
Drop files to upload
</p>
</div>
<!-- Uploaded files list -->
<div
style="
margin-top: 24px;
display: flex;
flex-direction: column;
gap: 8px;
"
>
<div
style="
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color_fill_secondary);
border-radius: 8px;
"
>
<span style="font-size: 24px">▭</span>
<div style="flex: 1">
<strong style="display: block">document.pdf</strong>
<span style="font-size: 12px; opacity: 0.6">2.4 MB</span>
</div>
<span style="color: var(--color_state_success)">✓</span>
</div>
<div
style="
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color_fill_secondary);
border-radius: 8px;
"
>
<span style="font-size: 24px">▭</span>
<div style="flex: 1">
<strong style="display: block">image.jpg</strong>
<span style="font-size: 12px; opacity: 0.6">
1.8 MB - Uploading...
</span>
</div>
<div
style="
width: 60px;
height: 4px;
background: var(--color_line_secondary);
border-radius: 2px;
overflow: hidden;
"
>
<div
style="
width: 60%;
height: 100%;
background: var(--color_fill_primary);
"
></div>
</div>
</div>
</div>
Sortable List
Reorderable list with drag-and-drop.
1
First item
⋮⋮
2
Second item
⋮⋮
3
Dragging this item
⋮⋮
4
Fourth item
⋮⋮
5
Fifth item
⋮⋮
HTML
<div
data-ss="sortable"
style="
max-width: 400px;
display: flex;
flex-direction: column;
gap: 4px;
"
>
<div
data-ss="draggable"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: white;
border: 1px solid var(--color_line_secondary);
border-radius: 8px;
cursor: move;
"
>
<span style="opacity: 0.4">1</span>
<span style="flex: 1">First item</span>
<span style="opacity: 0.3">⋮⋮</span>
</div>
<div
data-ss="draggable"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: white;
border: 1px solid var(--color_line_secondary);
border-radius: 8px;
cursor: move;
"
>
<span style="opacity: 0.4">2</span>
<span style="flex: 1">Second item</span>
<span style="opacity: 0.3">⋮⋮</span>
</div>
<div
data-ss="draggable"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: var(--color_fill_primary);
color: white;
border-radius: 8px;
cursor: move;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transform: scale(1.02);
"
>
<span style="opacity: 0.6">3</span>
<span style="flex: 1">Dragging this item</span>
<span style="opacity: 0.5">⋮⋮</span>
</div>
<div
style="
height: 52px;
border: 2px dashed var(--color_fill_primary);
border-radius: 8px;
background: rgba(var(--color_fill_primary_rgb), 0.05);
"
></div>
<div
data-ss="draggable"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: white;
border: 1px solid var(--color_line_secondary);
border-radius: 8px;
cursor: move;
"
>
<span style="opacity: 0.4">4</span>
<span style="flex: 1">Fourth item</span>
<span style="opacity: 0.3">⋮⋮</span>
</div>
<div
data-ss="draggable"
style="
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: white;
border: 1px solid var(--color_line_secondary);
border-radius: 8px;
cursor: move;
"
>
<span style="opacity: 0.4">5</span>
<span style="flex: 1">Fifth item</span>
<span style="opacity: 0.3">⋮⋮</span>
</div>
</div>
JavaScript API
Programmatic control of drag-and-drop components.
JavaScript
<script>
// DragAndDropManager
import { DragAndDropManager } from "stylescape";
const dnd = new DragAndDropManager({
draggableSelector: '[data-ss="draggable"]',
dropzoneSelector: '[data-ss="dropzone"]',
handleSelector: ".drag-handle",
ghostClass: "is-dragging",
dropIndicatorClass: "drop-indicator",
// Callbacks
onDragStart: (element, event) => {
console.log("Started dragging:", element);
},
onDragOver: (dropzone, draggable, event) => {
dropzone.classList.add("is-over");
},
onDragLeave: (dropzone, draggable, event) => {
dropzone.classList.remove("is-over");
},
onDrop: (dropzone, draggable, event) => {
console.log("Dropped:", draggable, "into:", dropzone);
// Update data/state
updateOrder(draggable, dropzone);
},
onDragEnd: (element, event) => {
console.log("Drag ended");
},
// Validation
canDrop: (dropzone, draggable) => {
const accepts = dropzone.dataset.ssDropzoneAccept;
return draggable.matches(accepts);
},
});
// Methods
dnd.enable();
dnd.disable();
dnd.destroy();
// Sortable list helper
import { SortableList } from "stylescape";
const sortable = new SortableList(listElement, {
handle: ".sort-handle",
animation: 150,
ghostClass: "sortable-ghost",
onSort: (oldIndex, newIndex, element) => {
console.log(`Moved from ${oldIndex} to ${newIndex}`);
// Save new order
saveOrder(sortable.getOrder());
},
});
sortable.getOrder(); // Get current order
sortable.setOrder([3, 1, 2, 4]); // Set specific order
</script>