Skip to content

Dock

A row of icon buttons that grow toward the pointer, like an app launcher. Every item is a real button or link with a visible label (a tooltip) that is also its accessible name. Magnification is off on touch and for reduced motion.

Motionv0.1.0experimentalWCAG 2.2 AAView spec

Optional, and kept apart.

Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.

import { CalendarIcon, ChartIcon, Dock, DockItem, HomeIcon, InboxIcon, SearchIcon, SettingsIcon } from "@rdloom/react";

// Move the pointer along the dock: the icons grow toward it and their neighbours move aside.
export default function DockBasicExample() {
  return (
    <div className="flex w-full justify-center py-12">
      <Dock label="Applications">
        <DockItem label="Home"><HomeIcon className="size-5" /></DockItem>
        <DockItem label="Search"><SearchIcon className="size-5" /></DockItem>
        <DockItem label="Inbox"><InboxIcon className="size-5" /></DockItem>
        <DockItem label="Calendar"><CalendarIcon className="size-5" /></DockItem>
        <DockItem label="Reports"><ChartIcon className="size-5" /></DockItem>
        <DockItem label="Settings"><SettingsIcon className="size-5" /></DockItem>
      </Dock>
    </div>
  );
}

Installation

npx rdloom add dock

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.

It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/dock.json

Works, but without upgrade tracking, and you import the motion CSS yourself.

Usage

import { CalendarIcon, ChartIcon, Dock, DockItem, HomeIcon, InboxIcon, SearchIcon, SettingsIcon } from "@rdloom/react";

<div className="flex w-full justify-center py-12">
  <Dock label="Applications">
    <DockItem label="Home"><HomeIcon className="size-5" /></DockItem>
    <DockItem label="Search"><SearchIcon className="size-5" /></DockItem>
    <DockItem label="Inbox"><InboxIcon className="size-5" /></DockItem>
    <DockItem label="Calendar"><CalendarIcon className="size-5" /></DockItem>
    <DockItem label="Reports"><ChartIcon className="size-5" /></DockItem>
    <DockItem label="Settings"><SettingsIcon className="size-5" /></DockItem>
  </Dock>
</div>

Vertical

import { CalendarIcon, ChartIcon, Dock, DockItem, UsersIcon } from "@rdloom/react";

export default function DockVerticalExample() {
  return (
    <div className="flex w-full justify-center py-4">
      <Dock label="Workspace tools" orientation="vertical">
        <DockItem label="Calendar"><CalendarIcon className="size-5" /></DockItem>
        <DockItem label="Reports"><ChartIcon className="size-5" /></DockItem>
        <DockItem label="Team"><UsersIcon className="size-5" /></DockItem>
      </Dock>
    </div>
  );
}
import { Dock, DockItem, FileIcon, GlobeIcon, HomeIcon } from "@rdloom/react";

export default function DockLinksExample() {
  return (
    <div className="flex w-full justify-center py-6">
      <Dock label="Quick links" magnification={1.4}>
        <DockItem label="Home page" href="#home"><HomeIcon className="size-5" /></DockItem>
        <DockItem label="Documents" href="#documents"><FileIcon className="size-5" /></DockItem>
        <DockItem label="Website" href="#website"><GlobeIcon className="size-5" /></DockItem>
      </Dock>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
childrenrequired

DockItem elements.

nodenone
labelrequired

Accessible name of the toolbar, for example Applications.

stringnone
orientation

Layout direction and which arrow keys move focus.

"horizontal" | "vertical""horizontal"
magnification

Scale of the item directly under the pointer. 1 turns magnification off.

number1.6
distance

Pixels from the pointer within which items grow.

number120
isPaused

Turns magnification off. Items still enlarge slightly on focus.

booleanfalse

Accessibility

Role toolbar, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

  • Tab moves into the dock on one item and out again (roving focus)
  • Left and Right arrows (Up and Down when vertical) move between items, swapped in right-to-left layouts
  • Home and End jump to the first and last item
  • Enter or Space activates the focused item

Screen readers announce

  • Announced as a toolbar with its label; each item as a button or link with its label

What your code must do

  • Each item is a real button (or a link when it has an href) named by its label
  • The label also shows as a tooltip on hover and keyboard focus
  • Focus enlarges the focused item too, so keyboard users get the same feedback
  • Magnification does not run on touch, for prefers-reduced-motion, in a .rdm-still container or when isPaused is set
  • Scaling is visual only: layout does not shift and hit areas stay at least 24px
  • Forced colors: items keep a visible border and focus ring

Guidelines

Use it when

  • A small set of app-level shortcuts or tools

Avoid it when

  • Primary site navigation: use NavigationMenu
  • More than about ten items

Don't

  • Icon items without a label
  • Hiding essential actions only in the dock

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-surface-raised
  • --rd-color-border-default
  • --rd-color-text-default
  • --rd-color-focus-ring
  • --rd-radius-overlay
  • --rd-radius-control
  • --rd-elevation-raised