Action morphPro
A floating button that morphs into a quick-action menu, then an inline form, then back with a check.
Live · keyboard ready
Today
1 open task
- Review Emma’s onboarding flow
- Call Andre about the Q3 budget
- Send launch notes to Diane
- Pricing page: lead with the free tier
- Quick capture of tasks, notes, or comments without leaving the page.
- Apps with a few frequent create actions that deserve a persistent button.
- Mobile layouts where a corner button should expand into a small form.
- Use dialog or drawer for longer forms with several fields.
- Use dropdown-menu when actions run immediately and need no input.
- Use action-button for one async save on a button in place.
Installation
Pro source and install commands unlock with a Pro plan.
example.tsx
import { CheckSquare, StickyNote } from "lucide-react";import { ActionMorph } from "@/registry/components/action-morph/action-morph"; export function QuickCreate() { return ( <div style={{ position: "fixed", right: 24, bottom: 24 }}> <ActionMorph label="Create" actions={[ { id: "task", label: "New task", description: "Add to your list", icon: <CheckSquare strokeWidth={1.75} />, shortcut: "t", composer: { title: "New task", placeholder: "What needs doing?", choices: { label: "Due", options: ["Today", "Tomorrow", "Next week"] }, submitLabel: "Add", successLabel: "Task added", }, }, { id: "note", label: "New note", icon: <StickyNote strokeWidth={1.75} />, shortcut: "n", composer: { title: "New note", placeholder: "Write a note", multiline: true, submitLabel: "Save", successLabel: "Note saved" }, },ActionMorph
A floating action button that springs into a quick action menu, slides into an inline composer, and folds back with a check on success.
PropTypeDefaultDescription
actionsRequiredActionMorphAction[]–Actions: { id, label, description?, icon, shortcut?, composer }. composer is { title, placeholder, multiline?, choices?, submitLabel, successLabel, emptyHint? }.labelstring"Create"Accessible name of the button and the title of the menu.onSubmit(submission: ActionMorphSubmission) => void | Promise<unknown>–Receives { action, text, choice? }. Return a promise to hold the sending state; a rejection keeps the composer open with the draft and an error.corner"end" | "start""end"Which bottom corner the button sits in. The surface grows away from it.resetAfternumber1600Milliseconds the check stays before the button returns to its plus.classNamestring–Extra class on the root, for example to position it fixed.- EnterorSpace
- Opens the menu from the button and focuses the first action.
- ArrowDownorArrowUp
- Moves between menu actions, wrapping at the ends; Home and End jump to the first or last.
- Letter shortcut
- Opens that action's composer while the menu is open.
- Enter
- Submits a one line composer.
- Mod+Enter
- Submits a multiline composer.
- Arrow keys
- Move between choices in the composer's radio group.
- Escape
- Goes back from a composer to the menu, or closes the menu and returns focus to the button.
- The button has aria-haspopup="menu"; after success its label adds the success message.
- The menu is role="menu" labelled by its title, with role="menuitem" buttons and aria-keyshortcuts for letter shortcuts.
- Composer fields set aria-invalid and aria-describedby on an empty or failed submit; the form sets aria-busy while sending.
- A polite status region announces the success label, and focus moves into each new face and back to the button on close.
- One surface animates width, height, and corner radius on physical springs: growing carries a little bounce, folding settles without overshoot.
- Going deeper slides the new face in from the right and pushes the old one left; menu rows stagger in; a highlight glides between actions.
- Submitting folds the composer into the button, which tints to success while a check draws itself, then the plus rotates back in.
- Reduced motion jumps the size, swaps faces with fades, drops the press scale and shake, and slows the spinner.
- The menu is min(16rem, 100vw - 2rem) wide and the composer min(20rem, 100vw - 2rem), so both fit narrow phones.
- corner="start" grows the surface to the right for bottom-left placement.
- The button is 56px with touch-action: manipulation; hover styles apply only on hover-capable fine pointers.
- Each face reports its size through a ResizeObserver only while it is current; the shape animates from those sizes.
- Only the current face and the one leaving are mounted.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for the two or three things people create most often on a page, such as a task, note, or event.
- Return the real promise from onSubmit; on rejection the draft stays and a retry message shows.
- Drafts are kept per action while the component is mounted, so going back and forth does not lose text.
- The component does not position itself; wrap it in a fixed container at the matching corner.
- For a single async commit use action-button; for longer forms use dialog or drawer.
The full library index for assistants is at /llms.txt.