Interactive

Dock

macOS-style dock with magnification effects and smooth animations.

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

Distance140
Panel Height64
Magnification80
VariantBottom
SizeMedium
BackgroundGlass

Props

Dock

Prop Type Default Description
distancenumber150How far the pointer travels from an item before its magnification falls back to normal, in pixels.
panelHeightnumber64Height of the dock panel in pixels.
magnificationnumber80Peak 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.
springSpringOptions{ 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.
ariaLabelstring'Application dock'Accessible name for the toolbar element.
showLabelsbooleantrueReserved 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.
classstring-Merged onto the dock panel.

DockItem

Prop Type Default Description
ariaLabelstring-Accessible name for the item.
classstring-Merged onto the item wrapper.

DockIcon

Prop Type Default Description
widthnumber48Current magnified width, supplied by the item. Icon size derives from it.
scalenumber1Current magnification scale.
namestring'i-lucide-home'Nuxt UI icon name.
classstring-Merged onto the icon.

DockLabel

Prop Type Default Description
isHoveredbooleanfalseWhether the tooltip is visible. Passed in by the item's scoped slot.
classstring-Merged onto the tooltip.

Events

Event Payload Description
click() => voidEmitted 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 mousemove handler is throttled to 16ms (one frame at 60fps), so magnification recomputes at most once per frame regardless of pointer event rate.
  • Each DockItem sizes itself inside its own requestAnimationFrame loop that starts when the pointer (or keyboard focus) reaches it and subscribes to the shared mouse-motion value — items outside distance settle at the minimum size without touching layout.
Copyright © 2026