Gooey menu Pro

The actions are drops of the same liquid as the button. They pull away on the bounce spring, one after another, stretching a neck of goo until it snaps. Hover one and it swells. Close the menu and they fall back in, and the button bulges as it takes them. An SVG filter melts the blobs together. The icons ride a layer above it, so they stay sharp.

Press the button.

Pro preview

Installation

Terminalbash
npx @neelshha/ui@latest login
npx @neelshha/ui@latest add gooey-menu

Usage

page.tsxtsx
import { GooeyMenu } from "@/components/ui/gooey-menu";

<GooeyMenu
  label="Attach"
  actions={[
    { label: "Camera", icon: <Camera />, onSelect: openCamera },
    { label: "Voice note", icon: <Mic />, onSelect: record },
    { label: "File", icon: <Paperclip />, onSelect: pickFile },
    { label: "Location", icon: <MapPin />, onSelect: shareLocation },
  ]}
/>

In a line

A line keeps the gap between drops, however many there are. Set font-size on the menu to scale all of it.

Pro preview

The quick brown fox.

page.tsxtsx
<GooeyMenu
  label="Format"
  layout="line"
  direction="right"
  tone="key"
  actions={[
    { label: "Bold", icon: <Bold />, onSelect: bold },
    { label: "Italic", icon: <Italic />, onSelect: italic },
    { label: "Underline", icon: <Underline />, onSelect: underline },
  ]}
/>

Keyboard

The button is a disclosure. Enter or Space opens it, and Tab walks the actions in order. Escape closes the menu and puts focus back on the button. Choosing an action or clicking outside closes it too.

Source

API

Other props go to the outer div. With reduced motion, the actions appear in place without the flight.

PropTypeDefaultDescription
actionsGooeyAction[]Each action has a label, an icon, and onSelect. The label names it for screen readers and shows as a tooltip.
labelstring"Actions"Names the main button.
layout"fan" | "line""fan"An arc around the button, or a straight line away from it.
direction"up" | "down" | "left" | "right""up"Where the actions go. The fan centres on this direction.
tone"ink" | "key""ink"Solid ink, or the blue key.
open / defaultOpenbooleanfalseControlled or uncontrolled. onOpenChange fires with the next state.