Bloom

An iOS inspired pull down menu for the web, by Josh Puckett.

Want to build components and animations like Bloom? I'd highly recommend taking Emil Kowalski's animations.dev course — the definitive guide on the subject.

Take the course

Installation

npm install bloom-menu framer-motion

Anatomy

import { Menu } from 'bloom-menu'
 
const itemClass = "flex items-center gap-2 rounded-lg px-2 py-2 text-sm text-neutral-900 hover:bg-neutral-100"
 
export default () => (
<Menu.Root direction="top" anchor="start">
<Menu.Container
buttonSize={40}
menuWidth={160}
menuRadius={12}
className="bg-white shadow-lg ring-1 ring-black/5"
>
<Menu.Trigger>
<div className="flex h-10 w-10 items-center justify-center">
<MoreIcon />
</div>
</Menu.Trigger>
<Menu.Content className="p-2">
<Menu.Item className={itemClass} onSelect={() => {}}>
<PencilIcon /> Edit
</Menu.Item>
<Menu.Item className={itemClass} onSelect={() => {}}>
<CopyIcon /> Copy
</Menu.Item>
<Menu.Item className={itemClass} onSelect={() => {}}>
<ShareIcon /> Share
</Menu.Item>
<Menu.Item className={itemClass} onSelect={() => {}}>
<ArchiveIcon /> Archive
</Menu.Item>
</Menu.Content>
</Menu.Container>
</Menu.Root>
)

API Reference

Root

Provides state and configuration context.

PropTypeDescription
openbooleanControlled open state
onOpenChange(open: boolean) => voidOpen state callback
direction"top" | "bottom" | "left" | "right"Menu expansion direction (default: "top")
anchor"start" | "center" | "end"Anchor alignment (default: "start"). For left/right directions, only "center" is supported.

Container

The morphing element. Automatically sizes to fit the trigger content, then animates to the menu dimensions.

PropTypeDescription
buttonSizenumber | { width, height }Closed button size (default: 40)
menuWidthnumberOpen menu width (default: 200)
menuRadiusnumberOpen menu border-radius (default: 24)
buttonRadiusnumberClosed button border-radius (defaults to pill shape)

Item

Individual menu items with hover highlighting.

PropTypeDescription
onSelect() => voidSelection callback
disabledbooleanDisable the item
closeOnSelectbooleanClose menu on select (default: true)

SubMenu

Wrapper for nested submenu functionality.

PropTypeDescription
idstringUnique identifier for this submenu

SubMenuTrigger

The item that opens the submenu. Supports render prop for active state.

PropTypeDescription
childrenReactNode | (isActive: boolean) => ReactNodeContent or render prop
disabledbooleanDisable the trigger

SubMenuContent

Container for submenu items. Morphs from the trigger.