solidjs-motion 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +291 -0
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to `solidjs-motion` / `@solidjs-motion/motion` are documente
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.1] — 2026-05-20
9
+
10
+ ### Docs
11
+
12
+ - Expanded README with a 12-recipe "Recipes" section covering the full v0.1
13
+ surface: reactive `useMotion`, `<motion.X>` proxy + variant cascade,
14
+ `motion.create` HOC, MotionValues + `createTransform`/`createSpring`,
15
+ `createScroll`/`createInView`/`createTemplate`, `<Presence>` (single +
16
+ list + `mode="wait"`), drag with constraints, `<MotionConfig>` +
17
+ `createReducedMotion`.
18
+
8
19
  ## [0.1.0] — 2026-05-20
9
20
 
10
21
  First public release. Five phases of the port plan land together: the canonical
package/README.md CHANGED
@@ -46,6 +46,297 @@ export function Card() {
46
46
  with motion's initial styles; user refs and motion's ref both fire; the initial style is
47
47
  serialized into SSR HTML so the first paint is flicker-free.
48
48
 
49
+ ## Recipes
50
+
51
+ ### 1. Reactive options
52
+
53
+ Pass a function to `useMotion` to track Solid signals inside the target.
54
+
55
+ ```tsx
56
+ import { useMotion } from "solidjs-motion"
57
+ import { createSignal } from "solid-js"
58
+
59
+ export function Toggle() {
60
+ const [open, setOpen] = createSignal(false)
61
+ const motion = useMotion(() => ({
62
+ animate: { rotate: open() ? 180 : 0 },
63
+ transition: { duration: 0.3 },
64
+ }))
65
+ return (
66
+ <button onClick={() => setOpen((p) => !p)} {...motion()}>
67
+
68
+ </button>
69
+ )
70
+ }
71
+ ```
72
+
73
+ ### 2. `<motion.X>` proxy with variants
74
+
75
+ Every HTML/SVG tag is reachable off `motion`. Variant labels on the parent cascade to
76
+ descendants through `m.Provider` (auto-installed by the proxy).
77
+
78
+ ```tsx
79
+ import { motion } from "solidjs-motion"
80
+
81
+ const variants = {
82
+ rest: { y: 0, scale: 1 },
83
+ lift: { y: -8, scale: 1.04 },
84
+ }
85
+
86
+ export function Card() {
87
+ return (
88
+ <motion.article animate="rest" hover="lift" variants={variants}>
89
+ <motion.h2 variants={variants}>Inherits lift on hover</motion.h2>
90
+ </motion.article>
91
+ )
92
+ }
93
+ ```
94
+
95
+ ### 3. `motion.create(Component)` HOC
96
+
97
+ Wrap a custom component to make it motion-aware. The wrapped component must spread its
98
+ props (including `ref`) onto a single DOM-element root.
99
+
100
+ ```tsx
101
+ import { motion } from "solidjs-motion"
102
+ import type { ComponentProps } from "solid-js"
103
+
104
+ function Button(props: ComponentProps<"button">) {
105
+ return <button {...props} class={`btn ${props.class ?? ""}`} />
106
+ }
107
+
108
+ const MotionButton = motion.create(Button)
109
+
110
+ export function Stage() {
111
+ return (
112
+ <MotionButton hover={{ scale: 1.05 }} press={{ scale: 0.95 }}>
113
+ Press me
114
+ </MotionButton>
115
+ )
116
+ }
117
+ ```
118
+
119
+ ### 4. MotionValues + `createTransform`
120
+
121
+ MotionValues are the source of truth for animated state. They're both Solid Accessors and
122
+ upstream `MotionValue`s — drop them straight into `style`.
123
+
124
+ ```tsx
125
+ import { motion, createMotionValue, createTransform } from "solidjs-motion"
126
+
127
+ export function FadeSlider() {
128
+ const x = createMotionValue(0)
129
+ const opacity = createTransform(x, [-100, 0, 100], [0, 1, 0])
130
+ return (
131
+ <motion.div
132
+ drag="x"
133
+ dragConstraints={{ left: -100, right: 100 }}
134
+ style={{ x, opacity }}
135
+ >
136
+ Drag me
137
+ </motion.div>
138
+ )
139
+ }
140
+ ```
141
+
142
+ ### 5. Spring-smoothed pointer
143
+
144
+ `createSpring` mirrors any numeric input with physics smoothing.
145
+
146
+ ```tsx
147
+ import { motion, createMotionValue, createSpring } from "solidjs-motion"
148
+ import { onCleanup, onMount } from "solid-js"
149
+
150
+ export function Cursor() {
151
+ const x = createMotionValue(0)
152
+ const y = createMotionValue(0)
153
+ const sx = createSpring(x, { stiffness: 200, damping: 30 })
154
+ const sy = createSpring(y, { stiffness: 200, damping: 30 })
155
+
156
+ onMount(() => {
157
+ const move = (e: PointerEvent) => {
158
+ x.set(e.clientX)
159
+ y.set(e.clientY)
160
+ }
161
+ window.addEventListener("pointermove", move)
162
+ onCleanup(() => window.removeEventListener("pointermove", move))
163
+ })
164
+
165
+ return <motion.div class="cursor" style={{ x: sx, y: sy }} />
166
+ }
167
+ ```
168
+
169
+ ### 6. Scroll-linked progress bar
170
+
171
+ ```tsx
172
+ import { motion, createScroll, createTransform } from "solidjs-motion"
173
+
174
+ export function ProgressBar() {
175
+ const { scrollYProgress } = createScroll()
176
+ const width = createTransform(scrollYProgress, [0, 1], ["0%", "100%"])
177
+ return <motion.div class="progress" style={{ width }} />
178
+ }
179
+ ```
180
+
181
+ ### 7. Viewport-triggered fade-in
182
+
183
+ ```tsx
184
+ import { motion } from "solidjs-motion"
185
+
186
+ export function FadeInOnce() {
187
+ return (
188
+ <motion.section
189
+ initial={{ opacity: 0, y: 40 }}
190
+ inView={{ opacity: 1, y: 0 }}
191
+ inViewOptions={{ once: true, margin: "0px 0px -10% 0px" }}
192
+ >
193
+ Comes in once, stays.
194
+ </motion.section>
195
+ )
196
+ }
197
+ ```
198
+
199
+ ### 8. `createTemplate` for interpolated strings
200
+
201
+ Build a `MotionValue<string>` from interpolated MVs/Accessors — feed it to any string-valued
202
+ CSS property.
203
+
204
+ ```tsx
205
+ import { motion, createMotionValue, createTemplate } from "solidjs-motion"
206
+
207
+ export function GradientBox() {
208
+ const angle = createMotionValue(0)
209
+ const background = createTemplate`linear-gradient(${angle}deg, #f0f, #0ff)`
210
+ return (
211
+ <motion.div
212
+ hover={{ rotate: 360 }}
213
+ transition={{ duration: 2 }}
214
+ style={{ background }}
215
+ />
216
+ )
217
+ }
218
+ ```
219
+
220
+ ### 9. `<Presence>` for exit animations
221
+
222
+ Wrap a conditionally-rendered child to animate its exit before unmount.
223
+
224
+ ```tsx
225
+ import { motion, Presence } from "solidjs-motion"
226
+ import { Show, createSignal } from "solid-js"
227
+
228
+ export function Drawer() {
229
+ const [open, setOpen] = createSignal(false)
230
+ return (
231
+ <>
232
+ <button onClick={() => setOpen((p) => !p)}>Toggle</button>
233
+ <Presence>
234
+ <Show when={open()}>
235
+ <motion.aside
236
+ initial={{ x: -300 }}
237
+ animate={{ x: 0 }}
238
+ exit={{ x: -300 }}
239
+ transition={{ duration: 0.25 }}
240
+ >
241
+ Drawer content
242
+ </motion.aside>
243
+ </Show>
244
+ </Presence>
245
+ </>
246
+ )
247
+ }
248
+ ```
249
+
250
+ ### 10. `mode="wait"` + list exits
251
+
252
+ `mode="wait"` plays the outgoing child's `exit` fully before the incoming child enters.
253
+ For lists, `Presence` wraps a `<For>` and animates add/remove together.
254
+
255
+ ```tsx
256
+ import { motion, Presence } from "solidjs-motion"
257
+ import { For, Show, createSignal } from "solid-js"
258
+
259
+ export function Tabs() {
260
+ const [tab, setTab] = createSignal("a")
261
+ return (
262
+ <Presence mode="wait">
263
+ <Show when={tab()} keyed>
264
+ {(t) => (
265
+ <motion.div
266
+ initial={{ opacity: 0, y: 8 }}
267
+ animate={{ opacity: 1, y: 0 }}
268
+ exit={{ opacity: 0, y: -8 }}
269
+ >
270
+ Tab {t}
271
+ </motion.div>
272
+ )}
273
+ </Show>
274
+ </Presence>
275
+ )
276
+ }
277
+
278
+ export function Notifications(props: { items: () => string[] }) {
279
+ return (
280
+ <Presence>
281
+ <For each={props.items()}>
282
+ {(msg) => (
283
+ <motion.li
284
+ initial={{ opacity: 0, x: -16 }}
285
+ animate={{ opacity: 1, x: 0 }}
286
+ exit={{ opacity: 0, x: 16 }}
287
+ >
288
+ {msg}
289
+ </motion.li>
290
+ )}
291
+ </For>
292
+ </Presence>
293
+ )
294
+ }
295
+ ```
296
+
297
+ ### 11. Drag with constraints
298
+
299
+ `dragConstraints` accepts numeric bounds or a parent ref. `dragElastic` controls overshoot.
300
+
301
+ ```tsx
302
+ import { motion } from "solidjs-motion"
303
+
304
+ export function DraggableCard() {
305
+ let bounds!: HTMLDivElement
306
+ return (
307
+ <div ref={bounds} class="bounds">
308
+ <motion.div
309
+ drag
310
+ dragConstraints={bounds}
311
+ dragElastic={0.2}
312
+ whileDrag={{ scale: 1.05 }}
313
+ >
314
+ Drag inside
315
+ </motion.div>
316
+ </div>
317
+ )
318
+ }
319
+ ```
320
+
321
+ ### 12. `<MotionConfig>` + reduced motion
322
+
323
+ `<MotionConfig>` flows defaults (transition, reduced-motion mode, CSP nonce) to descendants.
324
+ `createReducedMotion()` reads the system preference directly.
325
+
326
+ ```tsx
327
+ import { MotionConfig, createReducedMotion, motion } from "solidjs-motion"
328
+
329
+ export function App() {
330
+ const reduced = createReducedMotion()
331
+ return (
332
+ <MotionConfig reducedMotion="user" transition={{ duration: 0.4, ease: "easeOut" }}>
333
+ <motion.div animate={{ x: 100 }}>Honors `prefers-reduced-motion`</motion.div>
334
+ <p>System reduced-motion: {String(reduced())}</p>
335
+ </MotionConfig>
336
+ )
337
+ }
338
+ ```
339
+
49
340
  ## Roadmap
50
341
 
51
342
  ### Shipped
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solidjs-motion",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "An animation library for SolidJS — port of motion/react patterns built on the framework-agnostic motion package",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -32,7 +32,7 @@
32
32
  "typecheck": "tsc --noEmit",
33
33
  "clean": "rm -rf dist node_modules",
34
34
  "publish:npm": "bun run build && npm publish --access public",
35
- "publish:jsr": "bunx jsr publish"
35
+ "publish:jsr": "bunx jsr publish --token $JSR_TOKEN"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "solid-js": "^1.9.0",