Back to gallery

A macOS style dock, keyboard included

A macOS inspired dock component. Icons are from beam, a browser with a first-class note taking experience. This is an exploration made for fun. The dock is accessible to mouse and keyboard users, try alternating between mouse and keyboard to see the difference. This is a desktop-only component (for now).

The magnification curve

Every icon measures how far the pointer is from it and scales between a minimum and a maximum, which is the obvious part. The part that decides whether it feels right is what counts as zero distance. If you measure to the centre of the icon, the icon reaches full size at exactly one pixel and starts shrinking again the moment you move past it, which reads as nervous.

So there is a dead zone. Distance is measured to the edges of a band across the middle of each icon rather than to its centre, and anywhere inside that band the distance is zero. The icon under the pointer stays at full size while you cross it, and only starts falling away once you have actually left. The falloff itself is linear, over a radius derived from the icon sizes rather than a fixed number of pixels, so the whole thing keeps its proportions if the dock is rendered at another size.

The keyboard is a different curve

A pointer has a position and a keyboard does not, so reusing the same maths for focus would mean inventing a fake cursor somewhere. Instead the component tracks whether the last interaction came from the pointer or from the keyboard, and when it came from the keyboard the scale is driven by distance in the list rather than distance on screen: the focused icon is the peak, its neighbours fall off by how many positions away they are.

The two modes have to be kept apart, or moving the mouse a pixel while tabbing would yank the magnification away from the icon you just focused. There is a guard for exactly that, which is why alternating between mouse and keyboard in the demo above is worth trying: the shape of the bump is the same, and what it is following is not.

Up next

A carousel component
-->
<--

Right before

A publish button