draggable
Drag me this text is also draggable
Drag with custom callbacks
this text is not draggablelast pointer: —
svelte<script lang="ts">
import { draggable } from 'svelte-widgets/attachments'
let last_drag: string = $state('')
</script>
<div class="drag-area">
<!-- Absolute positioned box → default handle is the node itself -->
<div
class="drag-box"
style="position: absolute; left: 1rem; top: 1rem"
{@attach draggable({
bounds: `parent`,
on_drag: (event: PointerEvent) =>
(last_drag = `${event.clientX}, ${event.clientY}`),
})}
>
Drag me
<small style="display: block; opacity: 0.7">this text is also draggable</small>
</div>
<!-- Second draggable with custom handle and callbacks -->
<div
class="drag-box"
style="position: absolute; left: 12rem; top: 8rem; width: 14rem"
{@attach draggable({
handle_selector: `.drag-handle`,
axis: `x`,
bounds: `parent`,
on_drag_start: () => (last_drag = `start`),
on_drag: (event: PointerEvent) =>
(last_drag = `${event.clientX}, ${event.clientY}`),
on_drag_end: () => (last_drag = `end`),
})}
>
<div class="drag-handle">Drag with custom callbacks</div>
<small style="display: block; opacity: 0.7">this text is not draggable</small>
</div>
</div>
<p>last pointer: {last_drag || '—'}</p>
<style>
.drag-area {
position: relative;
height: 40vh;
border: 1px dashed rgba(255, 255, 255, 0.2);
margin: 1rem 0;
overflow: hidden;
}
.drag-box {
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 8px;
padding: 0.6em 0.8em;
width: max-content;
}
</style>axis defaults to both; use x or y to lock movement. bounds is sampled when dragging starts and clamps the node to its parent’s or another element’s border box, or to a viewport-coordinate { top, right, bottom, left } rectangle. A node larger than its bounds pins its top-left edge.