Easing Picker
CSS easing function picker — bezier canvas, spring/bounce/wiggle physics baked to linear(), polynomial preset gallery, 6-property animation preview, 3-format output (CSS/Tailwind v3/v4).
Easing Picker
cubic-bezier(0.65, 0, 0.35, 1)
Type-Locked
Setting basis narrows the value and onChange types at compile time. Each picker below emits a different literal-string flavor.
BezierCanvas (standalone)
Drop just the bezier editor into your own UI. Drag the handles; the component owns nothing — you bring the state.
cubic-bezier(0.42, 0.00, 0.58, 1.00)Spring physics (standalone)
Compose SpringControls + sampleSpring + bakeLinear to roll your own spring picker. The picker baking happens client-side; no runtime physics in production.
linear(0, 0.2537 1.6949%, 0.6959 3.3898%, 1.0234 5.0847%, 1.1553 6.7797%, 1.1435 8.4746%, 1.0114 11.8644%, 0.9789 13.5593%, 0.9742 15.2542%, 1.0022 20.339%, 1)API
Public surface — component props, runtime helpers, and the type exports.
§ EasingPicker
<EasingPicker
value: EasingString | (string & {})
onChange: (next: EasingString | string) => void
basis?: EasingBasis
output?: 'css' | 'tailwind-v3' | 'tailwind-v4'
className?: string
aria-label?: string
/>Popover-wrapped composed wizard.
| Prop | Type | Description |
|---|---|---|
| value | EasingString | (string & {}) | Current CSS easing function or keyword. Required. |
| onChange | (next) => void | Called when the easing changes. Return type narrows by `basis`. |
| basis | EasingBasis? | Lock the wizard to "bezier" | "spring" | "bounce" | "wiggle" | "steps". Narrows onChange. |
| output | 'css' | 'tailwind-v3' | 'tailwind-v4' | Default snippet format in the OutputPanel. |
| className | string | Applied to the trigger button wrapper. |
| aria-label | string | Required when no visible label is associated externally. |
§ EasingPanel
<EasingPanel /* same props as EasingPicker */ />
Renders the wizard inline without a popover wrapper. Same prop surface as EasingPicker.
§ Sub-components
All controlled-only — value + onChange required.
- BezierCanvas
- Draggable P1/P2 SVG canvas.
- PresetGallery
- 39-preset card grid.
- EasingPreview
- CSS-animated preview with 6 property options.
- StepsControls
- n + position editor.
- SpringControls
- Stiffness / damping / mass sliders.
- BounceControls
- Bounces / stiffness sliders.
- WiggleControls
- Wiggles / damping sliders.
§ Runtime helpers
easing<S extends string>(value: S & EasingLiteral<S>): S
Call-site validator. Mirrors color() and gradient().
parseEasing(s: string): EasingState | null
String → EasingState, or null when unrecognized.
formatEasing(state: EasingState): string
EasingState → CSS-valid string.
bezierFromPreset(name: PresetName): string
Preset name → cubic-bezier(...) literal.
matchPreset(x1, y1, x2, y2): PresetName | null
Reverse lookup by coords with tolerance 0.005.
sampleSpring(k, c, m, n) / sampleBounce(n, k) / sampleWiggle(n, d)
Physics samplers — emit sample arrays for baking.
bakeLinear(samples): string
Sample array → linear(...) string with collinear-prune pass.
§ Types
- EasingString
- Union of all valid output strings.
- EasingLiteral<S>
- Strict literal validator for call-site validation.
- EasingBasis
- "bezier" | "spring" | "bounce" | "wiggle" | "steps".
- EasingStringMap
- Basis → output-string map for type narrowing.
- PresetName
- Named preset union (39 entries).
- EasingState
- Internal discriminated union (exported for advanced use).
§ Limitations
- Round-trip from
linear()back to physics params is lossy — the baked output erases the source{stiffness, damping, mass}. - Preset selection emits the underlying
cubic-bezier(...)literal, never the keyword form. LinearLiteral<S>does weak validation (variadic stop ranges not checked at type level); the runtime parser is authoritative.
Drop it in
One command via the shadcn CLI.
$ pnpm dlx shadcn@latest add https://turtiesocks.github.io/ridiculous/r/easing-picker.json