/Navigation
Navigation • React
Preview Hover Toolbar
A thin empty pill that grows wider and taller off its fixed bottom edge when the surrounding preview is hovered, scaling its actions in one after another with a label above each.
Installation
Requires lucide-react for its icons. The shadcn CLI installs it for you; copying the code by hand means installing it yourself.
Terminal
npx shadcn@latest add @microkit/preview-hover-toolbarCode
1"use client";23import { Expand, MoreHorizontal, Split } from "lucide-react";45const actions = [6{ id: "view", label: "View All", icon: Expand },7{ id: "branch", label: "Branch", icon: Split },8{ id: "more", label: "More", icon: MoreHorizontal },9];1011export function PreviewHoverToolbar() {12return (13<div className="group/preview flex h-full min-h-[140px] w-full items-center justify-center font-[Arial,Helvetica,sans-serif] text-[11px] text-[light-dark(#262d38,#dfe2e5)]">14<div className="flex h-[34px] items-end">15<div className="relative h-[16px] w-[44px] rounded-full border border-[light-dark(#c9d0da,#2e3238)] bg-[light-dark(rgba(255, 255, 255, .55), rgba(14,16,19,.55))] [transition:width_170ms_cubic-bezier(.5,0,.66,.2),height_170ms_cubic-bezier(.5,0,.66,.2),background-color_170ms_cubic-bezier(.5,0,.66,.2),border-color_170ms_cubic-bezier(.5,0,.66,.2)] group-hover/preview:h-[34px] group-hover/preview:w-[104px] group-hover/preview:border-[light-dark(#cbd2dc,#3a4048)] group-hover/preview:bg-[light-dark(#ffffff,#15181c)] group-hover/preview:[transition:width_170ms_cubic-bezier(.34,.8,.5,1),height_170ms_cubic-bezier(.34,.8,.5,1),background-color_170ms_cubic-bezier(.34,.8,.5,1),border-color_170ms_cubic-bezier(.34,.8,.5,1)] group-focus-within/preview:h-[34px] group-focus-within/preview:w-[104px] group-focus-within/preview:border-[light-dark(#cbd2dc,#3a4048)] group-focus-within/preview:bg-[light-dark(#ffffff,#15181c)] group-focus-within/preview:[transition:width_170ms_cubic-bezier(.34,.8,.5,1),height_170ms_cubic-bezier(.34,.8,.5,1),background-color_170ms_cubic-bezier(.34,.8,.5,1),border-color_170ms_cubic-bezier(.34,.8,.5,1)] motion-reduce:transition-none motion-reduce:group-hover/preview:transition-none motion-reduce:group-focus-within/preview:transition-none">16<div17className="absolute left-1/2 top-1/2 flex items-center gap-[4px] [transform:translate(-50%,-50%)]"18role="toolbar"19aria-label="Preview actions"20>21{actions.map((action) => (22<button23key={action.id}24type="button"25className="group/action pointer-events-none relative grid size-[28px] flex-none cursor-pointer place-items-center rounded-full border-0 bg-transparent p-0 font-[inherit] text-[light-dark(#69727f,#868d97)] opacity-0 [transform:scale(.55)] [transition:opacity_70ms_ease,transform_90ms_cubic-bezier(.64,0,.78,0),background-color_150ms_ease,color_150ms_ease] hover:bg-[light-dark(#c9d0da,#2a2f36)] hover:text-[light-dark(#14181e,#f4f5f7)] focus-visible:outline-[1.5px] focus-visible:outline-offset-1 focus-visible:outline-[#86b6ff] group-hover/preview:pointer-events-auto group-hover/preview:opacity-100 group-hover/preview:[transform:scale(1)] group-hover/preview:[transition:opacity_70ms_ease_80ms,transform_90ms_cubic-bezier(.22,1,.36,1)_80ms,background-color_150ms_ease,color_150ms_ease] group-focus-within/preview:pointer-events-auto group-focus-within/preview:opacity-100 group-focus-within/preview:[transform:scale(1)] group-focus-within/preview:[transition:opacity_70ms_ease_80ms,transform_90ms_cubic-bezier(.22,1,.36,1)_80ms,background-color_150ms_ease,color_150ms_ease] motion-reduce:transition-none motion-reduce:group-hover/preview:transition-none motion-reduce:group-focus-within/preview:transition-none"26aria-label={action.label}27>28<span29className="pointer-events-none absolute bottom-[calc(100%+12px)] left-1/2 whitespace-nowrap rounded-[8px] border border-[light-dark(#c9d0da,#2e3238)] bg-[light-dark(#ffffff,#1c1f24)] px-[9px] py-[5px] text-[11px] leading-none text-[light-dark(#262d38,#e7e9ec)] opacity-0 shadow-[0_10px_20px_rgba(0,0,0,.45)] [transform:translate(-50%,5px)_scale(.94)] [transition:opacity_.18s_ease,transform_.3s_cubic-bezier(.22,1,.36,1)] group-hover/action:opacity-100 group-hover/action:[transform:translate(-50%,0)_scale(1)] group-focus-visible/action:opacity-100 group-focus-visible/action:[transform:translate(-50%,0)_scale(1)] motion-reduce:transition-none"30aria-hidden="true"31>32{action.label}33</span>34<action.icon size={15} strokeWidth={1.8} aria-hidden="true" />35</button>36))}37</div>38</div>39</div>40</div>41);42}