An interactive button with states
Build a pay button that goes Default → Hover → Pressed → Loading → Done, try it on the stage and export a React component.
A button that feels right answers every input: it lifts on hover, gives on press, shows progress and confirms. In EaseKit you build that with states (named looks) and triggers (events that switch between them). In this walkthrough you build a pay button by hand, try it on the stage, and export a working React component. About twenty minutes.
1. Make the button
- Press ⌘N and send: “A pay button, 240 × 56, fully rounded, accent color, label ‘Pay now’, a hidden spinner and a hidden check icon centered on it, grouped as ‘Pay button’. Short entrance: fade and rise 12 pt.”
- The AI builds a group with a background, a label, a spinner path and a check path. The timeline only holds the entrance.
- Open the Interactions tab in the inspector (or Stage → Show interactions).
2. Add hover and press
- Select the Pay button group on the stage.
- Click Add hover in the Interactions tab. EaseKit creates a Hover state (scale 1.03, 2 pt up) with a gentle spring, plus two triggers: Hover → go to Hover, and Hover end → go to Default.
- Click Add tap. EaseKit creates a Pressed state (scale 0.96) and a trigger Tap → Toggle Pressed.
- Click Try it on the stage, or Interactive in the transport bar. Hover and click the button. A small pill at the top of the stage shows the current state.
- Click Interactive in the bar at the bottom to return to editing.
3. Refine the states by recording
Recording is the easiest way to set a state's values: you just change things on the stage.
- Click the record dot next to Hover. The stage shows Editing state: Hover.
- In the selection bar, click Scale and set 104 %. Nudge the group up with ↑ twice.
- Click Done in the pill or press ⇧⌘↩ to stop recording. The row now reads “2 values”.
- Record Pressed the same way with scale 97 %.
- Click the Pressed row to open its details and set the curve to Spring · snappy, so a press answers at once.
4. Add Loading and Done
- Click Add state. A state named State is created and starts recording right away.
- Shrink the background: select it and drag a corner handle inward, sideways only, until the pill becomes a 56 pt circle around the spinner. Fade the label out (opacity 0, scale 80 %) and fade the spinner in (opacity 1). Stop recording with ⇧⌘↩.
- Right-click the new state → Rename… and call it
Loading. - Add another state, record the check at opacity 1 and the spinner at 0 (keep the circle), and rename it
Done. - Click Loading to open its details. In the second menu (“Stays”), pick Done, then After 1.5 s. Loading now moves on by itself.
- Open Done and set it to Default after 1.5 s, so the button resets.
5. Wire the triggers
Each trigger reads like a sentence: When an event happens on a target, do an action, optionally with a state and a gate. The finished set looks like the table below.
- Take the tap trigger from step 2 and change its event to Press, its action from Toggle to Go to, and its state to Pressed.
- With the group still selected, click Add tap again. Pressed already exists, so only a new trigger is added. Set its action to Go to and its state to Loading.
- Open that trigger's gate menu (In any state) and pick Only in Pressed, so a tap only starts loading from the pressed look.
- Gate the Hover trigger with Only in Default, so hovering doesn't interrupt Loading or Done. Gate Hover end and Press with Only in Hover.
- Check the list under the triggers. EaseKit flags triggers that point at missing layers or states.
| When | on | Action | State | Only in |
|---|---|---|---|---|
| Hover | Pay button | Go to | Hover | Default |
| Hover end | Pay button | Go to | Default | Hover |
| Press | Pay button | Go to | Pressed | Hover |
| Tap | Pay button | Go to | Loading | Pressed |
6. Try it
- Turn on Interactive. Hover, press and release.
- Interrupt it: move the pointer away mid-transition. Transitions play from wherever the scene is, like real UI.
- Watch Loading turn into Done and back to Default on its own.
- Click the restart button in the bar to start over (load triggers fire again).
7. Export to React
- Press ⌘E. Under Other formats, Motion (React) now reads “.tsx · interactive component”.
- Click it and save
PayButton.tsx. - In your project, install Motion and use the component:
npm i motionimport PayButton from "./PayButton";
export default function Checkout() {
return <PayButton />;
}The component uses Motion variants per layer, gesture handlers and useState for the current state; simple cases become whileHover and whileTap. The automatic Loading → Done → Default steps run inside it.
Variations
- Disabled state: ask the AI “Add a Disabled state at 40 % opacity and a shake when it's tapped while disabled.”
- Color and text: record Done with a green background fill and the label reading “Paid” (keep the label visible there). Colors blend over the transition and the text swaps halfway.
- A slower way back: ask the AI to give the Hover end trigger its own, calmer transition; every interactive export keeps per-trigger transitions.
- Hover a card instead: make the card a component with a
hovervariant and use the Set variant action. - Load trigger: Load fires when the page appears, for an entrance that only plays once.