All skills
freshtechbro avatar

/rive-interactive

@1da73fe

State machine-based vector animation with runtime interactivity and web integration. Use this skill when creating interactive animations, state-driven UI, animated components with logic, or designer-created animations with runtime control. Triggers on tasks involving Rive, state machines, interactive vector animations, animation with input handling, ViewModel data binding, or React Rive integration. Alternative to Lottie for animations requiring state machines and two-way interactivity.

Use this Skill: https://skilld.dev/gh/freshtechbro/claudedesignskills/rive-interactive

This session only. Nothing lands on disk.

referencesapi_reference.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Rive React API Reference

Complete API reference for rive-react library.

Installation

npm install rive-react

Hooks

useRive

Main hook for initializing Rive animations.

const { rive, RiveComponent } = useRive(options);

Options:

  • src (string): Path to .riv file
  • riveFile (File): Preloaded Rive file
  • artboard (string): Artboard name
  • animations (string | string[]): Animations to play
  • stateMachines (string | string[]): State machines to activate
  • layout (Layout): Fit and alignment options
  • autoplay (boolean): Auto-play animations (default: true)
  • autoBind (boolean): Auto-bind ViewModels (default: true)
  • automaticallyHandleEvents (boolean): Handle Rive events
  • useOffscreenRenderer (boolean): Use off-screen renderer
  • shouldResizeCanvasToContainer (boolean): Auto-resize canvas

useStateMachineInput

Get state machine input reference.

const input = useStateMachineInput(rive, stateMachineName, inputName, initialValue);

Input Types:

  • Boolean: input.value = true/false
  • Number: input.value = 50
  • Trigger: input.fire()

useViewModel

Get ViewModel reference.

const viewModel = useViewModel(rive, { name: 'ViewModelName' });
// Or use default ViewModel
const viewModel = useViewModel(rive, { useDefault: true });

useViewModelInstance

Get or create ViewModel instance.

// Get default instance
const instance = useViewModelInstance(viewModel, { rive });

// Get named instance
const instance = useViewModelInstance(viewModel, { name: 'Instance1' });

// Create new instance
const instance = useViewModelInstance(viewModel, { useNew: true, rive });

useViewModelInstanceString

Bind string property.

const { value, setValue } = useViewModelInstanceString('propertyName', instance);

useViewModelInstanceNumber

Bind number property.

const { value, setValue } = useViewModelInstanceNumber('propertyName', instance);

useViewModelInstanceColor

Bind color property (hex number).

const { value, setValue } = useViewModelInstanceColor('propertyName', instance);

// Set color
setValue(0xff6b6b); // Hex number, no #

useViewModelInstanceEnum

Bind enum property.

const { value, setValue } = useViewModelInstanceEnum('propertyName', instance);

useViewModelInstanceTrigger

Fire or listen to trigger events.

// Fire trigger
const { trigger } = useViewModelInstanceTrigger('triggerName', instance);
trigger();

// Listen to trigger
useViewModelInstanceTrigger('triggerName', instance, {
  onTrigger: () => console.log('Triggered!')
});

useRiveFile

Preload Rive file.

const { riveFile, status } = useRiveFile({ src: 'animation.riv' });
// status: 'loading' | 'success' | 'failed'

Components

Rive Component

Declarative component for simple use cases.

import Rive from 'rive-react';

<Rive
  src="animation.riv"
  artboard="Main"
  animations="idle"
  stateMachines="State Machine 1"
  layout={{ fit: "contain", alignment: "center" }}
  useOffscreenRenderer={true}
  shouldResizeCanvasToContainer={true}
  automaticallyHandleEvents={false}
  style={{ width: '400px', height: '400px' }}
/>

RiveComponent (from useRive)

Component returned by useRive hook.

const { RiveComponent } = useRive({ src: 'animation.riv' });

<RiveComponent style={{ width: '400px', height: '400px' }} />

Events

EventType

import { EventType } from 'rive-react';

EventType.Load          // Rive file loaded
EventType.Play          // Animation started
EventType.Pause         // Animation paused
EventType.Stop          // Animation stopped
EventType.Loop          // Animation looped
EventType.Draw          // Frame drawn
EventType.RiveEvent     // Custom Rive event

RiveEventType

import { RiveEventType } from 'rive-react';

RiveEventType.General   // General custom event
RiveEventType.OpenUrl   // Open URL event

Event Listening

useEffect(() => {
  if (!rive) return;

  const onRiveEvent = (event) => {
    const eventData = event.data;

    if (eventData.type === RiveEventType.General) {
      console.log('Event:', eventData.name);
      console.log('Properties:', eventData.properties);
    }
  };

  rive.on(EventType.RiveEvent, onRiveEvent);

  return () => {
    rive.off(EventType.RiveEvent, onRiveEvent);
  };
}, [rive]);

Layout Options

interface Layout {
  fit?: 'contain' | 'cover' | 'fill' | 'fitWidth' | 'fitHeight' | 'none' | 'scaleDown';
  alignment?: 'center' | 'topLeft' | 'topCenter' | 'topRight' | 'centerLeft' |
              'centerRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight';
}

Rive Instance Methods

From useRive hook:

rive.play()                          // Play animation
rive.pause()                         // Pause animation
rive.stop()                          // Stop animation
rive.reset()                         // Reset animation
rive.cleanup()                       // Cleanup resources
rive.resizeDrawingSurfaceToCanvas()  // Resize canvas

TypeScript Support

import { useRive, useStateMachineInput, Layout } from 'rive-react';

interface Props {
  animationSrc: string;
}

const MyComponent: React.FC<Props> = ({ animationSrc }) => {
  const { rive, RiveComponent } = useRive({
    src: animationSrc,
    autoplay: true,
  });

  const hoverInput = useStateMachineInput(
    rive,
    'State Machine',
    'isHovered',
    false
  );

  return <RiveComponent />;
};

Common Patterns

Dynamic Animation Switching

const [animation, setAnimation] = useState('idle');

const { RiveComponent } = useRive({
  src: 'character.riv',
  animations: animation,
  autoplay: true,
});

// Change animation
<button onClick={() => setAnimation('walk')}>Walk</button>

Multiple State Machines

const { rive, RiveComponent } = useRive({
  src: 'animation.riv',
  stateMachines: ['State Machine 1', 'State Machine 2'],
  autoplay: true,
});

Responsive Layout

const layout = {
  fit: window.innerWidth < 768 ? 'fitWidth' : 'contain',
  alignment: 'center'
};

<Rive src="animation.riv" layout={layout} />

Error Handling

const { rive, RiveComponent } = useRive({
  src: 'animation.riv',
  autoplay: true,
});

if (!rive) {
  return <div>Loading animation...</div>;
}

return <RiveComponent />;

Performance Tips

  1. Use Off-Screen Renderer:

    <Rive useOffscreenRenderer={true} />
  2. Preload Files:

    const { riveFile } = useRiveFile({ src: 'animation.riv' });
  3. Disable Auto-Resize:

    <Rive shouldResizeCanvasToContainer={false} />
  4. Manual Event Handling:

    <Rive automaticallyHandleEvents={false} />

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides comprehensive instructions and boilerplate for integrating Rive animations into React applications. It is generally safe; however, it documents patterns for handling external data from Rive events which represents a surface for indirect prompt injection if the agent processes that data without sanitization.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    5 files scanned · No issues

  • ZeroLeaks5mo

    1 finding · Score: 86/100

Signed by skilld at 1da73fe. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 11 months ago

README badge

README badge for freshtechbro/claudedesignskills/rive-interactive