The design tool for how your interface behaves
The design tool for how your interface behaves
Choreograph hover, press, focus and drag states on a canvas that is a real browser. You design the interaction by doing it.
Open ChoreoRead the docsFree · no account · files stay in your browser
The handoff problem
Designers describe motion in Loom recordings. Engineers reinterpret it by eye. What ships is an approximation of an approximation.
Motion tools think in linear timelines and export artefacts that don’t map to component states or respond to real events. Prototypes show intent and ship nothing.
Code gets it exactly right, and asks designers to think in keyframe syntax to get there. So the interaction is rebuilt by hand after handoff, lossily, every time.
Figma is the source of truth for structure. Choreo is the source of truth for behaviour, so the interaction you hand over is the one that ships.
Scrubbing is the whole idea
Drag a playhead and the component responds in the same frame. No render step, no preview mode. Scroll this section and you are the playhead.
You design the interaction by doing it
Nothing to declare up front. Choreo's canvas is a real browser, so the thing you drag is the thing your users will touch.
Bank App cardSaved
Compositor onlyLive Preview
BaseClicked410ms
View cards details \*\*7520
JANNET SMITH 2400 3256 2323 7619
EXP DATE 05/35
CVC 123
BANK
Lock your card
What is a virtual card
Your virtual card will have a different number than your physical card. This helps keep your information secure.
Direct deposit
Institution number 832
Transit/branch number 0055
Account number \\\\\\\\
Direct deposit details Void cheque
hover it · click to change state · flip the switch
HoverPressFocusIn-ViewToggleDragLoad
CardTRIGGERScale XScale YMove YOpacity
0ms100ms200ms300ms410ms
This is a real Choreo file, not a picture of one
The Bank App card template, dropped straight into this page. Hover it, click it to flip between its Base and Clicked states, flip the switch. There is no player in between that can drift from what the browser does.
New animationesc
Trigger
HoverPressFocusIn-ViewToggleDragLoad
Source element
Pricing cardbutton
Start recording
01
#### Arm a trigger
Pick one of seven triggers and the element that fires it. That is the whole setup.
Recording Hover · Pricing cardStop
Y −8px
0ms140ms400ms
02
#### Then just design
Drag it, restyle it, resize it. Every edit lands as a keyframe at the playhead.
Export
- Vanilla CSSstyles.css
- Web Animationsanimation.js
- ReactCard.tsx
- Motion Specspec.md
- Move Y0 → −8px240ms
- Shadowsoft → deep240ms
Zero dependencies
03
#### Copy the output
The code panel has been compiling the whole time. Take any of the four targets.
You already know how to animate. You just don't know the syntax.
There is no Animate tab and no property palette. Arm a trigger, make the change you want, and Choreo writes down what you did.
HoverPressFocusIn-ViewToggleDragLoad
CardLift on hover60fps
#### Hover
Enter and exit are edited apart, so a card can rise fast and settle slow instead of playing one curve backwards.
Recorded
Every trigger is authored the same way. Arm it, make the change you want, and Choreo writes down what you did.
Seven triggers, each owning its own timeline
A linear timeline is the wrong shape for interface motion. The unit of choreography here is a trigger state, and enter and exit are edited apart, so a card can rise fast and settle slow.
Vanilla CSSBehaviourWeb AnimationsReactMotion Spec
styles.css
Copy
.choreo-bank-app-card { position: relative; width: 411px; height: 530px; background-image: linear-gradient(0deg, #f7f5f5 0%, #efefef 100%); box-sizing: border-box; border: 1px solid #ffffff; overflow: hidden; border-radius: 31px;}.choreo-bank-app-card__frame-1686561429 { position: absolute; left: 23px; top: 27px; width: fit-content; height: fit-content; box-sizing: border-box; display: flex; gap: 10px; align-items: center; transform: translateX(0px) translateY(0px); opacity: 1; pointer-events: none;}.choreo-bank-app-card__visa-inc-logo-2005-2014-1 { width: 30px; height: 11px;}.choreo-bank-app-card__visa-inc-logo-2005-2014-1 svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__view-cards-details { width: 125px; height: 17px; color: #171717; font-size: 14px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__7520 { width: fit-content; height: fit-content; color: #969696; font-size: 14px; font-weight: 600; font-family: 'Inter', sans-serif; white-space: nowrap; overflow-wrap: break-word;}.choreo-bank-app-card__card { appearance: none; border: none; margin: 0; padding: 0; font: inherit; text-align: inherit; background: none; color: inherit; position: absolute; left: 22px; top: 20px; width: 367px; height: 210px; box-sizing: border-box; display: flex; flex-direction: column; gap: 72px; padding: 32px 0px; justify-content: center; background-image: radial-gradient(circle, #1b1c23 0%, #32343d 100%); box-shadow: 0px 11px 34px 0px rgba(0, 0, 0, 0.45); overflow: hidden; transform: rotateY(180deg); border-radius: 12px; opacity: 0; cursor: pointer;}.choreo-bank-app-card__frame-1686561438 { position: relative; align-self: stretch; height: 63px; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px; justify-content: flex-end;}.choreo-bank-app-card__frame-1686561432 { position: relative; align-self: stretch; height: 38px; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px; justify-content: center; background-color: #0000004a;}.choreo-bank-app-card__frame-1686561436 { position: relative; align-self: stretch; height: fit-content; box-sizing: border-box; display: flex; gap: 27px; padding: 0px 20px; justify-content: space-between; opacity: 0.5;}.choreo-bank-app-card__frame-1686561433 { position: relative; width: 152px; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px;}.choreo-bank-app-card__jannet-smith { width: 152px; height: 12px; color: #969696; font-size: 10px; font-weight: 600; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__2400-3256-2323-7619 { width: 152px; height: 17px; color: #969696; font-size: 14px; font-weight: 600; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__frame-1686561437 { position: relative; width: fit-content; height: fit-content; box-sizing: border-box; display: flex; gap: 27px; align-items: center;}.choreo-bank-app-card__frame-1686561434 { position: relative; width: 67px; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 11px;}.choreo-bank-app-card__exp-date { width: 67px; height: 17px; color: #969696; font-size: 14px; font-weight: 600; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__05-35 { width: 67px; height: 17px; color: #969696; font-size: 14px; font-weight: 600; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__frame-1686561435 { position: relative; width: 31px; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 11px;}.choreo-bank-app-card__cvc { width: 31px; height: 17px; color: #969696; font-size: 14px; font-weight: 600; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__123 { width: 31px; height: 17px; color: #969696; font-size: 14px; font-weight: 600; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__card-2 { appearance: none; border: none; margin: 0; padding: 0; font: inherit; text-align: inherit; background: none; color: inherit; position: absolute; left: 90px; top: 80px; width: 227px; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 28px; padding: 12px 16px; justify-content: flex-end; align-items: flex-end; background-image: radial-gradient(circle, #1b1c23 0%, #32343d 100%); box-shadow: 0px 11px 34px 0px rgba(0, 0, 0, 0.45); overflow: hidden; border-radius: 12px; transform: translateX(0px) translateY(0px) scaleX(1) scaleY(1); cursor: pointer;}.choreo-bank-app-card__frame-1686561427 { position: relative; align-self: stretch; height: fit-content; box-sizing: border-box; display: flex; gap: 137px; justify-content: space-between; align-items: center;}.choreo-bank-app-card__bank { width: 41px; height: 17px; color: #ffffff; font-size: 14px; font-weight: 800; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__mynaui-contactless { width: 18px; height: 18px;}.choreo-bank-app-card__mynaui-contactless svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__frame-1686561432-2 { position: relative; align-self: stretch; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px;}.choreo-bank-app-card__uit-sim-card { width: 27px; height: 21px;}.choreo-bank-app-card__uit-sim-card svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__g4158 { width: 30px; height: 11px;}.choreo-bank-app-card__g4158 svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__frame-1686561430 { position: absolute; left: 20px; top: 218px; width: 367px; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; justify-content: center; align-items: center;}.choreo-bank-app-card__card-details { position: relative; width: 367px; height: fit-content; box-sizing: border-box; display: flex; flex-direction: column; gap: 5px; align-items: center;}.choreo-bank-app-card__frame-1686561427-2 { position: relative; align-self: stretch; height: 108px; background-color: #ffffff; overflow: hidden; border-radius: 20px; opacity: 0; display: none;}.choreo-bank-app-card__frame-1686561422 { position: absolute; left: 22px; top: 18px; width: 323px; height: fit-content; box-sizing: border-box; display: flex; gap: 159px; justify-content: space-between; align-items: flex-end;}.choreo-bank-app-card__lock-your-card { margin: 0; width: 114px; height: 19px; color: #979797; font-size: 16px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__switch { appearance: none; border: none; margin: 0; padding: 0; font: inherit; text-align: inherit; background: none; color: inherit; position: relative; width: 51px; height: 24px; box-sizing: border-box; display: flex; gap: 10px; padding: 0px 2px; justify-content: flex-end; align-items: center; border-radius: 30px; transform: translateX(0px) translateY(0px); background-color: #1cc24b; cursor: pointer;}.choreo-bank-app-card__rectangle-9 { position: relative; width: 27px; height: 20px; background-color: #ffffff; transform-origin: 51% 50%; border-radius: 30px; transform: translateX(0px) translateY(0px);}.choreo-bank-app-card__frame-1686561423 { position: absolute; left: 22px; top: 71px; width: 326px; height: 20px; box-sizing: border-box; display: flex; gap: 115px; justify-content: space-between; align-items: center;}.choreo-bank-app-card__what-is-a-virtual-card { width: 162px; height: 19px; color: #979797; font-size: 16px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__wordpress-external { position: relative; width: 20px; height: 20px; overflow: hidden;}.choreo-bank-app-card__wordpress-external-2 { position: absolute; left: 0px; top: 0px; width: 18px; height: 18px;}.choreo-bank-app-card__wordpress-external-2 svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__line-19 { position: absolute; left: 23px; top: 53px; width: 322px; height: 1px; fill: none; stroke: #efefef; stroke-width: 1px;}.choreo-bank-app-card__line-19 svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__line-19 svg, .choreo-bank-app-card__line-19 svg { stroke: inherit !important; fill: inherit !important; stroke-width: inherit !important;}.choreo-bank-app-card__your-virtual-card-will-have-a-different-number-than-your-physical-card-this-helps-keep-your-information-secure { width: 341px; height: 30px; display: none; color: #b4b4b4; font-size: 12px; font-weight: 500; font-family: 'Inter', sans-serif; text-align: center; overflow-wrap: break-word;}.choreo-bank-app-card__group { position: relative; align-self: stretch; height: 278px; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px;}.choreo-bank-app-card__direct-deposit { width: 367px; height: fit-content; color: #b0afaf; font-size: 13px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__frame-1686561421 { position: relative; align-self: stretch; height: 163px; background-color: #ffffff; overflow: hidden; border-radius: 20px;}.choreo-bank-app-card__frame-1686561422-2 { position: absolute; left: 22px; top: 18px; width: 323px; height: fit-content; box-sizing: border-box; display: flex; gap: 159px; justify-content: space-between; align-items: flex-end;}.choreo-bank-app-card__institution-number { width: 140px; height: 19px; color: #b5b5b5; font-size: 16px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__832 { width: 21px; height: 16px; color: #000000; font-size: 12px; font-weight: 500; font-family: 'Reddit Mono', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__frame-1686561423-2 { position: absolute; left: 22px; top: 71px; width: 323px; height: fit-content; box-sizing: border-box; display: flex; gap: 115px; justify-content: space-between; align-items: flex-end;}.choreo-bank-app-card__transit-branch-number { width: 176px; height: 19px; color: #b5b5b5; font-size: 16px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__0055 { width: 27px; height: 16px; color: #000000; font-size: 12px; font-weight: 500; font-family: 'Reddit Mono', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__frame-1686561424 { position: absolute; left: 22px; top: 126px; width: 323px; height: fit-content; box-sizing: border-box; display: flex; gap: 133px; justify-content: space-between; align-items: flex-end;}.choreo-bank-app-card__account-number { width: 127px; height: 19px; color: #b5b5b5; font-size: 16px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__node { width: fit-content; height: fit-content; color: #000000; font-size: 14px; font-weight: 500; font-family: 'Reddit Mono', sans-serif; white-space: nowrap; overflow-wrap: break-word;}.choreo-bank-app-card__line-19-2 { position: absolute; left: 23px; top: 53px; width: 322px; height: 1px; fill: none; stroke: #efefef; stroke-width: 1px;}.choreo-bank-app-card__line-19-2 svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__line-19-2 svg, .choreo-bank-app-card__line-19-2 svg { stroke: inherit !important; fill: inherit !important; stroke-width: inherit !important;}.choreo-bank-app-card__line-20 { position: absolute; left: 23px; top: 105px; width: 322px; height: 1px; fill: none; stroke: #efefef; stroke-width: 1px;}.choreo-bank-app-card__line-20 svg { display: block; width: 100%; height: 100%; overflow: visible;}.choreo-bank-app-card__line-20 svg, .choreo-bank-app-card__line-20 svg * { stroke: inherit !important; fill: inherit !important; stroke-width: inherit !important;}.choreo-bank-app-card__frame-1686561428 { position: relative; align-self: stretch; height: 51px; box-sizing: border-box; display: flex; gap: 10px; padding: 0px 24px; justify-content: space-between; align-items: center; background-color: #ffffff; overflow: hidden; border-radius: 20px;}.choreo-bank-app-card__direct-deposit-details { width: 163px; height: 19px; color: #b5b5b5; font-size: 16px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card__void-cheque { width: 72px; height: 15px; color: #b4b4b4; font-size: 12px; font-weight: 500; font-family: 'Inter', sans-serif; overflow-wrap: break-word;}.choreo-bank-app-card.is-bank-app-card__card-2-hover .choreo-bank-app-card__frame-1686561429 { transform: translateX(0px) translateY(16px); opacity: 0;}.choreo-bank-app-card.is-bank-app-card__card-2-hover .choreo-bank-app-card__card-2 { transform: translateX(0px) translateY(-28px) scaleX(1.55) scaleY(1.55);}.choreo-bank-app-card__switch.is-bank-app-card__switch-toggle { transform: translateX(0px) translateY(0px); background-color: #d8d8d8;}.choreo-bank-app-card__switch.is-bank-app-card__switch-toggle .choreo-bank-app-card__rectangle-9 { transform: translateX(-19px) translateY(0px);}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__card { transform: translateX(-9px) translateY(-9px) rotateY(0deg); border-radius: 23px; display: flex; height: 221px; opacity: 1; width: 386px;}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__card-2 { transform: translateX(2px) translateY(-23px) rotateY(-180deg) scaleX(1.7) scaleY(1.7); opacity: 0;}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__frame-1686561430 { transform: translateY(132px);}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__frame-1686561427-2 { transform: translateX(0px) translateY(0px); display: block; height: 106px; opacity: 1; width: 370px;}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__switch { transform: translateX(0px) translateY(0px);}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__your-virtual-card-will-have-a-different-number-than-your-physical-card-this-helps-keep-your-information-secure { display: block;}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__group { opacity: 0;}.choreo-bank-app-card[data-state="clicked"] .choreo-bank-app-card__direct-deposit { transform: translateX(0px) translateY(0px); opacity: 0.94;}@media (prefers-reduced-motion: no-preference) { .choreo-bank-app-card__frame-1686561429 { transition: transform 350ms cubic-bezier(0.25, 1, 0.5, 1), opacity 350ms cubic-bezier(0.25, 1, 0.5, 1); } .choreo-bank-app-card__card-2 { transition: transform 410ms cubic-bezier(0.34, 1.56, 0.64, 1), opacity 500ms cubic-bezier(0.33, 1, 0.68, 1); } .choreo-bank-app-card__switch { transition: transform 300ms cubic-bezier(0, 0, 0.58, 1), background-color 300ms cubic-bezier(0, 0, 0.58, 1); } .choreo-bank-app-card__rectangle-9 { transition: transform 300ms cubic-bezier(0, 0, 0.58, 1); } .choreo-bank-app-card__card { transition: transform 500ms cubic-bezier(0.33, 1, 0.68, 1), border-radius 500ms cubic-bezier(0.33, 1, 0.68, 1), height 500ms cubic-bezier(0.33, 1, 0.68, 1), opacity 500ms cubic-bezier(0.33, 1, 0.68, 1), width 500ms cubic-bezier(0.33, 1, 0.68, 1); } .choreo-bank-app-card__frame-1686561430 { transition: transform 500ms cubic-bezier(0.33, 1, 0.68, 1); } .choreo-bank-app-card__frame-1686561427-2 { transition: transform 500ms cubic-bezier(0.33, 1, 0.68, 1), height 500ms cubic-bezier(0.33, 1, 0.68, 1), opacity 500ms cubic-bezier(0.33, 1, 0.68, 1), width 500ms cubic-bezier(0.33, 1, 0.68, 1); } .choreo-bank-app-card__group { transition: opacity 500ms cubic-bezier(0.33, 1, 0.68, 1); } .choreo-bank-app-card__direct-deposit { transition: transform 500ms cubic-bezier(0.33, 1, 0.68, 1), opacity 500ms cubic-bezier(0.33, 1, 0.68, 1); } .choreo-bank-app-card__frame-1686561429 { will-change: opacity, transform; } .choreo-bank-app-card__card { will-change: opacity, transform; } .choreo-bank-app-card__card-2 { will-change: opacity, transform; } .choreo-bank-app-card__frame-1686561430 { will-change: transform; } .choreo-bank-app-card__frame-1686561427-2 { will-change: opacity, transform; } .choreo-bank-app-card__switch { will-change: transform; } .choreo-bank-app-card__rectangle-9 { will-change: transform; } .choreo-bank-app-card__group { will-change: opacity; } .choreo-bank-app-card__direct-deposit { will-change: opacity, transform; }}#### You never wrote it
No syntax, no coefficients, no class names to invent. All of it came from the layers you dragged.
#### Nothing to install
No Choreo runtime and no required library. Paste it into the project and it runs.
#### Reduced motion, handled
Every export honours a reduced-motion preference. You did not have to remember.
#### Or skip it entirely
Send a live link instead, and let the engineer lift these same files from the panel.
Then, at the very end, there's code
You never touched it while designing. These are the actual files Choreo emitted for the card you just used: 56 layers, three triggers and a state machine, in one pass.
Not just a timeline. A real editor.
Choreo opens your Figma frames but does not depend on them. Structure, style, states and motion are all editable in-tool.
Import report28 layersAuto layout → FlexboxexactIcons → inline SVGexactGradient text → solid colorapproximatedFigma import that tells you the truthThe bundled plugin walks a selected frame in, with layout, vectors and sizing intact. Anything that could not translate exactly is listed in the Import Report and linked to the layer, so an imperfect import is a task instead of a silent lie. Re-import later and your choreography survives.BaseOnLoading+SwitchclickOnBaseNamed component statesBase plus named states, Figma-variant style. Wire a click, double-click or hover to a state, then read the whole machine as a graph.cubic-bezier( 0.16, 1, 0.3, 1)Emphasized decelerateCurves the browser can drawA bezier editor with presets and springs that document their own fidelity. It cannot express a curve your export would have to fake.transform, opacitycompositorwidthlayoutNamed as you keyframe it, not in an audit later.Green until it isn'tA signal beside the timeline: green while the motion stays cheap, amber the moment it gets expensive, with the property named.?share=pricing-cardCopyLive, not a videoInspect modeShare the interaction itselfPublish a link where stakeholders hover, click and scroll the real component. Engineers take the export from the same page, no account needed.
Local-firstDocuments autosave to your browser and save out as portable files. Cloud sync is an optional layer you can switch on later.Motion pathsMove a layer along a curve with editable tangents, not just from one point to another in a straight line.Vector motionIcons animate as real vectors: stroke draw-on, path morphing, gradient fills, with engine differences stated where they exist.Presets and templatesCard float, jelly press, focus ring, toast slide-in. Drop one on and it stays fully editable, never a black box.
Why not just use Figma or Lottielab?
Because the three tools are different shapes. Figma owns structure, Lottielab owns illustrative motion, and neither is built to make a hover state behave in a browser.
| How Choreo compares with Figma Motion and Lottielab| | Choreo | Figma Motion | Lottielab | | ---------------------------------------------------- | ------------------------------------------------ | ------------------------------------ | ----------------------------------- | | Built for | Interface micro-interactions | Prototypes and design specs | Vector and illustrative animation | | The canvas is | Real DOM, styled with real CSS | The Figma design canvas | A vector animation canvas | | Time is organised by | One timeline per trigger state | Transitions between frames | A single linear timeline | | Real UI states | Seven triggers, enter and exit edited separately | Prototype interactions on frames | Whatever the Lottie player exposes | | What reaches production | CSS, Web Animations, React, or a written spec | An engineer rebuilds it by hand | A Lottie JSON file | | Runtime needed to play it | None | None; it stays a prototype | The Lottie player | | Handoff is | A live link stakeholders can interact with | A prototype link plus a written spec | A file plus the player that runs it |
Choreo is not trying to replace either one. It is for the layer in between, where a component has to respond to a real pointer. This comparison reflects how each tool positions itself today; all three keep moving.
Five commitments the tool holds
Each one is a constraint Choreo works within, and together they are the reason you can trust what comes out the other side.
1. 01
Predictable, never guessed
Nothing is generated for you. Every result comes from choreography you performed, so the same file always behaves the same way. 2. 02The canvas is the browser
Your component is live in the page, so nothing sits between the canvas and what your users see. What you scrub is what ships. 3. 03States, not seconds
The web is event-driven, so the unit of choreography is a trigger state, not a position on a linear timeline. 4. 04Honest about limits
When an import cannot be translated faithfully, or something cannot animate smoothly, the tool tells you and points at the layer. 5. 05Deletable
What you hand off needs no Choreo runtime and no account. Drop the tool tomorrow and nothing it produced breaks.Your next interaction starts here
Open a file, arm a hover, and drag something. Nothing to install, and nothing leaves your browser.
Open ChoreoStart from a template
Free to use · no account · files stay local