Props & Reactivity
Control shader properties dynamically with reactive state and animations
Every shader component accepts props that control its appearance and behavior. These props are fully reactive-change a value in your component state, and the shader updates instantly.
Basic Props
Props work exactly like standard component props. Pass them directly to configure your shaders:
<Shader>
<Circle color="#ff0088" radius="0.5" />
</Shader>Static props like these are perfect for fixed effects. But the real power comes from reactive props.
Reactive Props
Bind props to your component's state, and the shader updates automatically when the state changes. This happens efficiently-prop changes update GPU uniforms directly without recompiling shaders.
<script setup>
import { ref } from 'vue'
import { Shader, LinearGradient, Circle } from 'shaders/vue'
const angle = ref(0)
</script>
<template>
<div>
<button @click="angle += 45">Rotate +45°</button>
<button @click="angle -= 45">Rotate -45°</button>
<button @click="angle = 0">Reset</button>
</div>
<Shader>
<Circle id="mask" radius="0.8" :visible="false" />
<LinearGradient :angle="angle" maskSource="mask" />
</Shader>
</template>Click the buttons, and the gradient rotates inside the circle instantly. No lag, no stutter-just smooth, real-time updates.
preset: components: - type: Circle id: "mask" props: radius: 0.8 visible: false - type: LinearGradient props: angle: 0 maskSource: "mask" controls:
- type: button label: Rotate +45° action: increment prop: angle value: 45
- type: button label: Rotate -45° action: increment prop: angle value: -45
- type: button label: Reset action: set prop: angle value: 0
The angle updates immediately because props are reactive. Change any prop-color, position, intensity-and the GPU responds instantly.
Common Reactive Props
Different components accept different props. Here are patterns you'll use frequently:
Position and Size:
<Circle :radius="size" :center="{ x: posX, y: posY }" />Colors:
<LinearGradient :colorA="startColor" :colorB="endColor" />Intensity and Strength:
<Blur :intensity="blurAmount" />
<Glow :strength="glowPower" />Angles and Rotation:
<LinearGradient :angle="rotation" />Every numerical prop, color prop, and position prop can be reactive. Bind them to sliders, scroll position, mouse coordinates, or any other dynamic value.
Animating Props
Props aren't just for user interactions-they're perfect for animations too. Animation libraries like Motion make it easy to create smooth, choreographed transitions.
Note: Motion supports React and Vue, as well as plain JavaScript. You can use any animation library you like for Svelte/Solid.
import { useState } from 'react'
import { animate } from 'motion'
import { Shader, LinearGradient, Circle } from 'shaders/react'
function MyComponent() {
const [radius, setRadius] = useState(0.6)
async function pulse() {
// Grow then shrink with smooth easing
await animate(radius, 1, {
duration: 0.5,
easing: 'ease-out',
onUpdate: (latest) => setRadius(latest)
})
await animate(1, 0.6, {
duration: 0.5,
easing: 'ease-in',
onUpdate: (latest) => setRadius(latest)
})
}
return (
<>
<button onClick={pulse}>Pulse</button>
<Shader>
<Circle id="mask" radius={radius} visible={false} />
<LinearGradient maskSource="mask" />
</Shader>
</>
)
}preset: components: - type: Circle id: "mask" props: radius: 0.6 visible: false - type: LinearGradient props: maskSource: "mask" controls:
- type: button
label: Pulse
action: sequence
sequence:
- prop: radius to: 1 duration: 500 easing: ease-out
- prop: radius to: 0.6 duration: 500 easing: ease-in
Motion handles the tweening automatically, giving you smooth animations with minimal code. Because prop updates are efficient, you can animate multiple properties simultaneously without performance concerns.
Performance Notes
Reactive props update GPU uniforms directly. This means:
- No shader recompilation: Changing a prop doesn't rebuild the shader
- GPU-efficient: Updates happen on the graphics card, not the CPU
- Frame-rate friendly: Animate as many props as you need
You can safely update props every frame, tie them to scroll position, or respond to mouse movement without worrying about performance.