Dock
The Dock component provides a macOS-style dock with magnification effects and smooth animations. It's highly customizable and supports multiple orientations and sizes.
Usage
Hover to magnify, click to launch.
<template>
<div class="flex w-full flex-col items-center gap-6 py-10">
<MDock
position="inline"
variant="bottom"
:magnification="72"
:distance="140"
:panel-height="64"
>
<MDockItem
v-for="app in apps"
:key="app.name"
v-slot="{ width, isHovered, scale }"
:aria-label="app.name"
@click="lastOpened = app.name"
>
<MDockLabel :is-hovered="isHovered">
{{ app.name }}
</MDockLabel>
<MDockIcon
:width="width"
:scale="scale"
:name="app.icon"
class="text-highlighted"
/>
</MDockItem>
</MDock>
<p class="text-sm text-muted">
{{ lastOpened ? `Opening ${lastOpened}\u2026` : 'Hover to magnify, click to launch.' }}
</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const apps = [
{ name: 'Home', icon: 'i-lucide-home' },
{ name: 'Products', icon: 'i-lucide-package' },
{ name: 'Messages', icon: 'i-lucide-message-circle' },
{ name: 'Mail', icon: 'i-lucide-mail' },
{ name: 'Photos', icon: 'i-lucide-image' },
{ name: 'Music', icon: 'i-lucide-music' },
{ name: 'Settings', icon: 'i-lucide-settings' },
]
const lastOpened = ref<string | null>(null)
</script>
A macOS-style dock that magnifies items near the pointer.
Customize
Customize
Props
Dock
| Prop | Type | Default | Description |
|---|---|---|---|
distance | number | 150 | How far the pointer travels from an item before its magnification falls back to normal, in pixels. |
panelHeight | number | 64 | Height of the dock panel in pixels. |
magnification | number | 80 | Peak width, in pixels, an icon grows to as the pointer approaches. Icons rest at the base size and reach this width at the centre of the pointer's reach. |
spring | SpringOptions | { mass: 0.1, stiffness: 150, damping: 12 } | Spring options used when animation="spring". |
variant | 'bottom' | 'top' | 'left' | 'right' | 'floating' | 'compact' | 'bottom' | Where the dock is fixed and how it is laid out. left and right orient the
dock vertically; the rest are horizontal. |
size | 'sm' | 'md' | 'lg' | 'md' | Preset for the dock's gap and padding. |
position | 'fixed' | 'inline' | 'fixed' | Whether the dock is pinned to a viewport edge (fixed) or sits in normal
flow (inline). Use inline to embed it inside a page or container; the
variant then only sets the orientation. |
ariaLabel | string | 'Application dock' | Accessible name for the toolbar element. |
showLabels | boolean | true | Reserved for suppressing DockLabel tooltips; currently labels follow each
item's hover state regardless of this flag. |
background | 'glass' | 'solid' | 'none' | 'glass' | Panel background: frosted glass, opaque, or nothing. |
animation | 'spring' | 'ease' | 'none' | 'spring' | Declared for the resize behaviour, but sizing currently always runs through the rAF loop described under Performance. |
class | string | - | Merged onto the dock panel. |
DockItem
| Prop | Type | Default | Description |
|---|---|---|---|
ariaLabel | string | - | Accessible name for the item. |
class | string | - | Merged onto the item wrapper. |
DockIcon
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | 48 | Current magnified width, supplied by the item. Icon size derives from it. |
scale | number | 1 | Current magnification scale. |
name | string | 'i-lucide-home' | Nuxt UI icon name. |
class | string | - | Merged onto the icon. |
DockLabel
| Prop | Type | Default | Description |
|---|---|---|---|
isHovered | boolean | false | Whether the tooltip is visible. Passed in by the item's scoped slot. |
class | string | - | Merged onto the tooltip. |
Events
| Event | Payload | Description |
|---|---|---|
click | () => void | Emitted by DockItem when it is activated by pointer or keyboard. |
Slots
| Slot | Props | Description |
|---|---|---|
default | - | The dock's items — DockItem elements, each typically wrapping a
DockLabel and a DockIcon. |
default (DockItem) | { width: number, isHovered: boolean, scale: number } | Scoped slot on DockItem, exposing the live magnified width, isHovered
and scale so the label and icon can track the animation. |
Accessibility
The panel renders as role="toolbar" with aria-orientation derived from
variant. Arrow keys move focus between items (respecting orientation),
Home and End jump to the first and last item, and Escape clears the focused
item and blurs the dock — all through the shared useKeyboardNavigation
composable. Every DockItem should carry an ariaLabel.
Magnification is pointer-driven only: keyboard focus highlights an item without resizing the dock, so the interaction never depends on the animation.
Performance
- The dock's
mousemovehandler is throttled to 16ms (one frame at 60fps), so magnification recomputes at most once per frame regardless of pointer event rate. - Each
DockItemsizes itself inside its ownrequestAnimationFrameloop that starts when the pointer (or keyboard focus) reaches it and subscribes to the shared mouse-motion value — items outsidedistancesettle at the minimum size without touching layout.