MagicDraggable
MagicDraggable is a touch enabled, draggable component that can snap to configurable points inside its container.
<template>
<magic-draggable id="magic-draggable-demo" class="bg-surface-base rounded-md">
<div
class="bg-surface-high flex aspect-square w-32 items-center justify-center rounded-md"
>
<m-badge>Drag me</m-badge>
</div>
</magic-draggable>
</template>
<style>
[data-id='magic-draggable-demo'] {
--magic-draggable-position: relative;
--magic-draggable-z-index: 50;
--magic-draggable-height: 20rem;
}
</style>Overview
Anatomy
<template>
<magic-draggable id="your-draggable-id">
<!-- your content -->
</magic-draggable>
</template>
<script setup>
const { open } = useMagicDraggable('your-draggable-id')
</script>Installation
CLI
Add @maas/vue-equipment to your dependencies.
pnpm install @maas/vue-equipmentnpm install @maas/vue-equipmentyarn add @maas/vue-equipmentbun install @maas/vue-equipmentVue
If you are using Vue, import and add MagicDraggablePlugin to your app.
import { createApp } from 'vue'
import { MagicDraggablePlugin } from '@maas/vue-equipment/plugins/MagicDraggable'
const app = createApp({})
app.use(MagicDraggablePlugin)Nuxt
The component is available as a Nuxt module. In your Nuxt config file add @maas/vue-equipment/nuxt to your modules and add MagicDraggable to the plugins in your configuration.
export default defineNuxtConfig({
modules: ['@maas/vue-equipment/nuxt'],
vueEquipment: {
plugins: ['MagicDraggable'],
},
})Direct Import
If you prefer a more granular approach, the component can also be directly imported into any Vue component.
<script setup>
import { MagicDraggable } from '@maas/vue-equipment/plugins/MagicDraggable'
</script>
<template>
<magic-draggable id="your-draggable-id">
<!-- your content -->
</magic-draggable>
</template>Composable
In order to interact with the component from anywhere within your app, we provide a useMagicDraggable composable. Import it directly when needed.
import { useMagicDraggable } from '@maas/vue-equipment/plugins/MagicDraggable'
const { snapTo } = useMagicDraggable('your-draggable-id')
function handleClick() {
snapTo('top-right')
}TIP
If you have installed the component as a Nuxt module, the composable will be auto-imported and is automatically available in your Nuxt app.
Peer Dependencies
If you haven’t installed the required peer dependencies automatically, you’ll need to install the following packages manually.
| Package |
|---|
@nuxt/kit |
@vueuse/core |
defu |
Installation
pnpm install @nuxt/kit @vueuse/core defunpm install @nuxt/kit @vueuse/core defuyarn add @nuxt/kit @vueuse/core defubun install @nuxt/kit @vueuse/core defuAPI Reference
Props
The component comes with a simple set of props. Only the id is required.
| Prop | Type | Required |
|---|---|---|
MaybeRef<string> | true | |
MagicDraggableOptions | false |
Options
To customize the component override the necessary options. Any custom options will be merged with the default options.
| Option | Type | Default |
|---|---|---|
'div' | ||
number | 128 | |
number | 1.5 | |
number | 250 | |
number | 0 | |
number | 500 | |
'center' | ||
boolean | object | object | |
boolean | true | |
boolean | false |
CSS Variables
In order to provide its basic functionality the component comes with some CSS. To ensure that the component is customizable, relevant values are available as CSS variables.
| Variable | Default |
|---|---|
--magic-draggable-position | fixed |
--magic-draggable-width | 100% |
--magic-draggable-height | 100% |
--magic-draggable-z-index | 999 |
--magic-draggable-inset | 0 |
--magic-draggable-cursor | grab |
--magic-draggable-cursor-dragging | grabbing |
Errors
| Source | ErrorCode | Message |
|---|---|---|
MagicDraggable | missing_snap_point | MagicDraggable must have at least one snap point set |
Examples
Resize
<template>
<magic-draggable
id="magic-draggable-resize-demo"
class="bg-surface-base rounded-md"
:options="{
threshold: {
lock: 10,
},
}"
>
<div
:class="[
'bg-surface-high flex w-40 items-center justify-center rounded-md transition-all duration-150',
{
'aspect-square': square,
'aspect-[2/3]': !square,
},
]"
>
<m-button @click="toggle">Resize</m-button>
</div>
</magic-draggable>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { MButton } from '@maas/mirror/vue'
const square = ref(true)
function toggle() {
square.value = !square.value
}
</script>
<style>
[data-id='magic-draggable-resize-demo'] {
--magic-draggable-position: relative;
--magic-draggable-z-index: 50;
--magic-draggable-height: 20rem;
}
</style>Snap Points
<template>
<magic-draggable
id="magic-draggable-snap-points-demo"
:options="{
snapPoints: ['top', 'bottom', 'left', 'right'],
initial: { snapPoint: 'top' },
}"
class="bg-surface-base rounded-md"
>
<div
class="bg-surface-high flex aspect-square w-32 items-center justify-center rounded-md"
>
<m-badge>Drag me</m-badge>
</div>
</magic-draggable>
</template>
<style>
[data-id='magic-draggable-snap-points-demo'] {
--magic-draggable-position: relative;
--magic-draggable-z-index: 50;
--magic-draggable-height: 20rem;
}
</style>