navigation
Morph Menu
A compact trigger that expands into a spatially continuous menu surface.
- navigation
- menu
- overlay
- mobile
Live preview
Quick usage
import { MorphMenu } from "@pinky-ui/experiences";
<MorphMenu items={items} label="Site navigation" />Presets
Default
The restrained Pinky production default.
Default behaviour
Quiet
A flatter or lower-intensity treatment for dense pages.
disabled={true}
Install
Add @pinky-ui/experiences as a dependency, or use the CLI to copy this component's source directly into your project — no dependency to manage, fully editable.
npm install @pinky-ui/experiencespnpm add @pinky-ui/experiencesyarn add @pinky-ui/experiencesnpx pinky-ui add morph-menuPrefer to run the whole repository locally instead?
git clone https://github.com/florash/Pinky-UI.git
cd Pinky-UI
npm install
npm run devProps
| Prop | Type | Default | Description |
|---|---|---|---|
| items | MorphMenuItem[] | — | Semantic navigation destinations. |
| className | string | — | Styles the outer composition without changing its behaviour. |
| disabled | boolean | false | Uses the static, readable composition. |
Accessibility
- Escape closes the menu and focus is trapped while open.
- Closing restores trigger focus and releases body scroll.
Performance
- Reuses the existing shared-layout Morph primitive.
- No pointer or scroll loop is mounted.
Reduced motion
Spatial or continuous movement is removed while content, selection and controls remain available.
When to use
- Compact editorial and mobile navigation
When not to use
- Links that should remain visible at all times
Skill
What it does
Morph Menu turns a compact trigger into a short navigation surface with the same object continuity as the trigger. It is Pinky’s canonical compact navigation pattern.
Interaction anatomy
- Trigger: one labelled menu button.
- State: closed, opening, open and closing.
- Motion: the trigger surface expands into the menu instead of being replaced by a card.
- Surface: a short ordered list of semantic links plus an explicit close action.
- Feedback: focus enters the menu and returns to the trigger on close.
Good for
- Mobile headers with a small destination set.
- Sparse editorial or portfolio navigation.
- A compact index where the expanded list needs a little more room.
Avoid for
- Permanent desktop navigation or a long information architecture.
- A native disclosure that already communicates the relationship clearly.
- Mixing it with another modal or hiding heavy media behind the trigger.
Live example
Open the live menu above, move through its links with Tab, and close with Escape. The links remain real links; the morph is only the handoff.
Usage
<MorphMenu
trigger="Index"
items={sections.map((section) => ({
id: section.id,
label: section.label,
href: section.href,
}))}
/>Tune
- Keep the list short enough to scan without scrolling.
- Use
maxWidthfor the reading width, not for visual drama. - Give each item a stable label and a useful optional description.
- Keep the trigger surface and panel in the same material family.
Accessibility
- Preserve semantic links, an accessible menu label and a visible close button.
- Escape, focus trapping, focus restoration and body-scroll handling are part of the pattern.
- Keyboard users must reach every destination without a pointer.
- Touch users get the same explicit trigger and link targets.
Reduced motion
The menu opens and closes immediately while focus order, link semantics and the close path remain unchanged.