A collection of motion experiments with Rive and JavaScript. Some shipped, some scrapped, and some… just because they were fun to build
Motion in the
Margins
Motion in the
Margins
Like Reaction
A custom heart animation I built for my portfolio. Used Rive's layers, state machine, inputs, and listeners to create smooth, responsive interaction
A loader for Titan's Email Designer
A lightweight and playful loading animation built to add a bit of personality to wait times in the editor
Rive gives me a canvas to tinker, test, and bring ideas to life, right where code and creativity meet. Just me, Rive, a bit of JavaScript










const r = new rive.Rive({ src: 'color_mixing.riv', canvas: animationPattern, artboard: 'Pumpkin color mixing', stateMachines: ['Haloween pumpkin'], autoplay: true, onLoad: () => { const inputs = r.stateMachineInputs('Haloween pumpkin'); const redColor = inputs.find(input => input.name === 'Red'); const greenColor = inputs.find(input => input.name === 'Green'); const blueColor = inputs.find(input => input.name === 'Blue'); if (!redColor || !greenColor || !blueColor) { console.error("State machine inputs not found!"); return; } function calculate(){ const color = colorPicker.value; // Parse color values const red = parseInt(color.slice(1, 3), 16); const green = parseInt(color.slice(3, 5), 16); const blue = parseInt(color.slice(5, 7), 16); // Update Rive inputs redColor.value = red; greenColor.value = green; blueColor.value = blue;

Sajal Kumar
Product Designer
Motion Designer
Coder
Researcher
Maker
Motion in the
Margins
A collection of motion experiments with Rive and JavaScript.
Some shipped, some scrapped, and some… just because they were fun to build
Read receipts, with some personality
All your email tools, right where you need them





















Reusable blocks, ready for any email job
Ask away. Pulser never sleeps
Titan Email
10
Email Designer
If you liked it, put a heart on it
Rive gives me a canvas to tinker, test, and bring ideas to life, right where code and creativity meet. Just me, Rive, a bit of JavaScript





const r = new rive.Rive({ src: 'color_mixing.riv', canvas: animationPattern, artboard: 'Pumpkin color mixing', stateMachines: ['Haloween pumpkin'], autoplay: true, onLoad: () => { const inputs = r.stateMachineInputs('Haloween pumpkin'); const redColor = inputs.find(input => input.name === 'Red'); const greenColor = inputs.find(input => input.name === 'Green'); const blueColor = inputs.find(input => input.name === 'Blue'); if (!redColor || !greenColor || !blueColor) { console.error("State machine inputs not found!"); return; } function calculate(){ const color = colorPicker.value; // Parse color values const red = parseInt(color.slice(1, 3), 16); const green = parseInt(color.slice(3, 5), 16); const blue = parseInt(color.slice(5, 7), 16); // Update Rive inputs redColor.value = red; greenColor.value = green; blueColor.value = blue;