Guide
Vue and other frameworks
The Vue plugin and directive, and patterns for React, Svelte, and server rendering.
Kinesis works in any framework in one of two ways:
- CSS. Call
initKinesis()once in the browser. Kinesis watches the page, so components that mount, change classes, or unmount need nothing else. - JavaScript. Call
kinesis(element, props)on mount,set()when state changes, anddestroy()on unmount.
Vue
// main.js
import { createApp } from "vue"
import { KinesisPlugin } from "@amineyarman/kinesis/vue"
import App from "./App.vue"
createApp(App).use(KinesisPlugin).mount("#app")
The plugin starts CSS discovery and registers a v-kinesis directive. The directive takes the same props as kinesis() and updates with your data:
<script setup>
import { ref } from "vue"
const selected = ref(false)
</script>
<template>
<article
v-kinesis="{ tilt: selected ? 14 : 6, area: 'self', when: 'hover', y: -6 }"
@click="selected = !selected"
>
…
</article>
</template>
Props removed from the object go back to CSS. Everything is cleaned up on unmount.
Plugin options go in the second argument: app.use(KinesisPlugin, { reducedMotion: "user", debug: true }). { auto: false } skips CSS discovery.
Nuxt
Register the directive in a client plugin, and start discovery after hydration so Kinesis never changes markup before Vue checks it:
// plugins/kinesis.client.ts
import { initKinesis } from "@amineyarman/kinesis"
import { KinesisPlugin } from "@amineyarman/kinesis/vue"
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(KinesisPlugin, { auto: false })
onNuxtReady(() => initKinesis())
})
Server-rendered pages already contain your CSS. Elements sit at rest until Kinesis starts, so nothing flashes.
Coming from vue-kinesis
The component wrappers are gone. A container and its elements become a scope with CSS properties, or the directive:
<!-- vue-kinesis -->
<kinesis-container>
<kinesis-element :strength="10" type="depth">…</kinesis-element>
</kinesis-container>
<!-- Kinesis 2 -->
<div data-kinesis>
<div v-kinesis="{ parallax: 10 }">…</div>
</div>
The migration guide maps every old option.
React
Start discovery once, then write CSS:
// main.jsx
import { initKinesis } from "@amineyarman/kinesis"
initKinesis()
For motion driven by state, keep a handle in an effect and call set(). It's cheap enough to call on every render:
import { useEffect, useRef } from "react"
import { kinesis } from "@amineyarman/kinesis"
function Card({ selected }) {
const ref = useRef(null)
const handle = useRef(null)
useEffect(() => {
handle.current = kinesis(ref.current, { area: "self", when: "hover", y: -6 })
return () => handle.current.destroy()
}, [])
useEffect(() => {
handle.current.set({ tilt: selected ? 14 : 6 })
}, [selected])
return <article ref={ref} className="card">…</article>
}
Inline --k-* styles also work, but each change costs a style recalculation that set() avoids.
Svelte
Use an action:
<script>
import { kinesis } from "@amineyarman/kinesis"
function motion(node, props) {
const handle = kinesis(node, props)
return {
update: (next) => handle.reset().set(next),
destroy: () => handle.destroy(),
}
}
</script>
<div use:motion={{ magnetic: 0.3, radius: 140 }}>…</div>
Server rendering
Importing Kinesis on the server is safe. It does nothing until called in the browser, and initKinesis() returns without a document.