The Proof is Live

The Proof is Live

See the Code. Feel the Motion. Live Performance, Guaranteed.

Sample: App.jsx

// =================================================================
// OMNI-FX: Live React Demo (v3 - Device-Aware Hover)
// This is the final, production-ready code. It detects touch
// devices to programmatically disable hover effects on mobile,
// preventing the "sticky hover" bug.
//
// Learn more at [www.omnifx.studio]
// =================================================================

import React, { useEffect, useState, useRef, useCallback } from "react";
import { useRive, useStateMachineInput } from "@rive-app/react-canvas";
import "./App.css";

// Import the Rive file directly for robust pathing.
import RiveFile from './assets/omnifx_starter.riv';

// --- Rive Configuration ---
const ARTBOARD = "OMNI_MagicBoard";
const STATE_MACHINE = "StateMachine";

// --- State Definitions ---
// Note: The hoverStyle is now controlled by the component's logic, not here.
const defaultState = {
  iconIndex: 2,
  colorStyle: 2,
  backgroundStyle: 0,
  gradientFill: 1,
  disabledState: 0,
};

const toggledState = {
  iconIndex: 3,
  colorStyle: 2,
  backgroundStyle: 0,
  gradientFill: 1,
  disabledState: 0,
};

// --- Device Detection Utility (Runs once) ---
// This simple function checks if the browser supports touch events.
const isTouchDevice = () => {
  if (typeof window === 'undefined') return false;
  return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
};


export default function App() {
  // --- Rive Setup ---
  const { rive, RiveComponent } = useRive({
    src: RiveFile,
    artboard: ARTBOARD,
    stateMachines: STATE_MACHINE,
    autoplay: true,
  });

  // --- State Machine Input Hooks ---
  const iconIndexInput = useStateMachineInput(rive, STATE_MACHINE, "IconIndex");
  const colorStyleInput = useStateMachineInput(rive, STATE_MACHINE, "ColorStyle");
  const backgroundStyleInput = useStateMachineInput(rive, STATE_MACHINE, "BackgroundStyle");
  const hoverStyleInput = useStateMachineInput(rive, STATE_MACHINE, "HoverStyle");
  const gradientFillInput = useStateMachineInput(rive, STATE_MACHINE, "GradientFill");
  const disabledStateInput = useStateMachineInput(rive, STATE_MACHINE, "DisabledState");
  const clickTriggerInput = useStateMachineInput(rive, STATE_MACHINE, "ClickTrigger");

  // --- React State & Refs ---
  const [toggled, setToggled] = useState(false);
  const isInitialMount = useRef(true);
  // This ref stores the result of our device check so it only runs once.
  const isMobileDevice = useRef(isTouchDevice());

  // --- Core Logic: Applying State to Rive ---
  const applyState = useCallback((state) => {
    if (!rive || !iconIndexInput || !colorStyleInput || !backgroundStyleInput || !hoverStyleInput || !gradientFillInput || !disabledStateInput) return;
    
    iconIndexInput.value = state.iconIndex;
    colorStyleInput.value = state.colorStyle;
    backgroundStyleInput.value = state.backgroundStyle;
    // We no longer set hoverStyle here, it's set once on initialization.
    gradientFillInput.value = state.gradientFill;
    disabledStateInput.value = state.disabledState;
  }, [rive, iconIndexInput, colorStyleInput, backgroundStyleInput, hoverStyleInput, gradientFillInput, disabledStateInput]);
  
  useEffect(() => {
    if (rive && clickTriggerInput && hoverStyleInput) { 
      if (isInitialMount.current) {
        // THE CRITICAL FIX IS HERE:
        // On initial mount, we set the hover style based on the device type.
        // If it's a mobile device, disable hover animations (set to 0).
        // If it's a desktop device, enable them (set to 1).
        hoverStyleInput.value = isMobileDevice.current ? 0 : 1;

        applyState(defaultState);
        clickTriggerInput.fire();
        isInitialMount.current = false;
      } else {
        applyState(toggled ? toggledState : defaultState);
        clickTriggerInput.fire();
      }
    }
  }, [toggled, rive, clickTriggerInput, applyState, hoverStyleInput]);

  const handleRiveClick = () => setToggled(!toggled);

  // --- Render ---
  return (
    <div className="page-wrapper">
      <header className="page-header">
        <h1 className="title">OMNI-FX</h1>
        <p className="subtitle">
          Interactive icon preview — click on the icon tile
        </p>
      </header>

      <div className="app-container">
        {/* Left Panel: UI Mockup */}
        <main className="left-panel">
          <div className="placeholder header">
            <div className="mock-ui-label">Display Settings</div>
          </div>
          <div className="placeholder subheader">
            <div className="mock-ui-label">Appearance</div>
          </div>
          <div className="placeholder line">
             <div className="mock-ui-label">Theme</div>
          </div>
          <div className="placeholder line short">
             <div className="mock-ui-label">Accent Color</div>
          </div>
          <div className="placeholder line">
             <div className="mock-ui-label">Icon Style</div>
          </div>
          <div className="placeholder image-box">
             <div className="mock-ui-label">Theme Preview</div>
          </div>
          <div className="placeholder line">
            <div className="mock-ui-button">Save Changes</div>
          </div>
        </main>

        {/* Right Panel: Live Rive Component */}
        <aside className="right-panel">
          <div className="sidebar-title">Live Rive Component</div>
          <div
            className="rive-container"
            role="button"
            tabIndex={0}
            onClick={handleRiveClick}
            onTouchStart={handleRiveClick}
            onKeyDown={(e) => (e.key === "Enter" || e.key === " ") ? handleRiveClick(e) : null}
            aria-label="Omni icon preview (click to toggle)"
          >
            <RiveComponent />
          </div>
          <p className="sidebar-caption">This is not a GIF or a video. It's a real-time, state-aware component you can control with code.</p>
        </aside>
      </div>
    </div>
  );
}

Your Animation Workflow, Simplified

Old Way

New OMNI Way

How It Works

From Import to Motion — in 3 Steps

1

Import once

Add OMNI’s .riv file to your project and initialize Rive’s official runtime.

2

Set Once

Define your State Machine inputs just once — hover, tap, or toggle. Connect them with your UI logic, apply your CSS or layout settings, and you’re ready for interaction.

3

Animate Instantly

Adjust input values, switch states, or trigger transitions — and watch OMNI respond in real time. No extra code. No delay. Pure motion on command.

The Production-Ready Handoff

When you purchase any OMNI-FX pack (Core, Creator, or Studio), you instantly receive a structured .zip archive containing everything needed to deploy motion-native UI immediately.

What You Receive

[PackName].riv

Your core Rive animation file.

[PackName].riv

Your core Rive animation file.

[PackName].riv

Your core Rive animation file.

README.md

Quick start & integration overview.

README.md

Quick start & integration overview.

README.md

Quick start & integration overview.

LICENSE.md

The chosen license (Personal or Commercial).

LICENSE.md

The chosen license (Personal or Commercial).

LICENSE.md

The chosen license (Personal or Commercial).

FEATURES.md

Complete feature & hover breakdown.

FEATURES.md

Complete feature & hover breakdown.

FEATURES.md

Complete feature & hover breakdown.

NAMING.md

Input mapping for developer reference.

NAMING.md

Input mapping for developer reference.

NAMING.md

Input mapping for developer reference.

DOCS.md

Full documentation for advanced usage.

DOCS.md

Full documentation for advanced usage.

DOCS.md

Full documentation for advanced usage.

EULA.md

End-user agreement for compliance.

EULA.md

End-user agreement for compliance.

EULA.md

End-user agreement for compliance.

CUSTOMIZATIONS.md

Guide for brand adaptation.

CUSTOMIZATIONS.md

Guide for brand adaptation.

CUSTOMIZATIONS.md

Guide for brand adaptation.

Implementation Notes & Performance Assurance

Seamless Integration and Performance

OMNI-FX files are built on Rive’s vector-based, high-performance C++ runtime. They are not heavy static SVGs but live motion systems requiring Rive runtime support.


Performance Assurance: Even the largest Studio Pack (.riv file is approximately 1.29 MB) is highly efficient. Rive is optimized for instancing, meaning you can run many icons simultaneously on a single page by reusing the same file blueprint without significant CPU/GPU strain. The icons are designed for a smooth 60 FPS experience.

The 400ms Transition Restriction (Intentional Design)

The main limitation you may encounter is that you cannot trigger a state change faster than 400ms.


  • The Logic: Every smooth transition must pass through the Zero Junction State (Cross → Zero State in ~200ms, then Zero State → Add in ~200ms).


The Intentional Decision: This restriction is required to allow the "matter to morph completely". If you click again before the morph is finished, the next smooth transition cannot begin, which prevents chaotic or choppy animation states. We prioritize smooth, fluid motion over instantaneous, jarring state changes, upholding the OMNI philosophy.

The 8 State Machine Inputs: Your Control Knobs

The entire system is controlled by 8 inputs in the State Machine named StateMachine. You gain programmatic control over the icon's state, colour, hover effects, and visibility by changing the values of these inputs and firing the ClickTrigger.


Input Name

Type

Significance & Playfulness

Use Case & Logic

IconIndex

Number

The Identity Switch. This controls which icon is displayed. Inputting 0 selects the invisible/Zero State, which is crucial for internal morphing logic.

Usage: Set the number corresponding to your desired icon (e.g., 5 for 'Home'). Must be paired with ClickTrigger to execute the animation.


ColorStyle

Number

The Palette Switch. Controls the primary color of the icon. Inputs range from 1 to 15 (depending on your pack), with 0 being invisible/off.


Usage: Use 0 for no invisible, or inputs 1-15 for a solid color. to ensure the icon morphs with the new color.

BackgroundStyle

Number

The Bounding Box Toggle. Controls the background fill behind the icon.

Usage: Use 0 for no background (invisible), or inputs 1-10 for a solid background color.


HoverStyle

Number

The Interaction Feel. Determines the type of visual feedback when the cursor is over the icon. Crucial for device-aware design.


Usage: 0 disables hover (ideal for touch/mobile devices). 1 (Wake Effect), 2 (Scale), and 3 (Heartbeat) are the available effects.

GradientFill

Number

The Futuristic Toggle. A subtle effect to differentiate your UI from generic designs.

Usage: 0 is Off; 1 is On (True). When set to 1, it applies a subtle gradient overlay to the icon using the selected ColorStyle.


DisabledState

Number

The Dead Zone. Provides a one-click solution for the disabled visual state.

Usage: 0 is Off (Normal); 1 is On (True). When enabled, the icon enters a desaturated/sleep state, and hover effects are disabled.


Hover

Boolean

The Listener. An automatic listener used internally by Rive.

Usage: Auto-triggers on mouse-over on desktop. Programmatic control is usually focused on setting HoverStyle.


ClickTrigger

Trigger

The State Commit. This is the most critical input. Changing a Number input only prepares the state; firing the trigger commits the change and executes the 400ms morph animation.

Usage: Must be called programmatically on initial component load (to solve the Zero State issue) and after changing the

IconIndex.

Icon Breakdown (Included in Creator and Studio Packs)

The higher-tier packs unlock specialized icon sets, giving your application a unique edge:


Set Name

Icon Count

Typical Use Cases

Sample Icons Included

Essential Set

20 Icons (in Core/Creator/Studio)

Universal interface actions, navigation, settings, profiles, and basic feedback.



Home, Search, Heart, Close, Plus, Trash.

Creative Spark

10 Icons (in Creator/Studio)

Design tools, media playback, portfolios, art, and visual-first products.



Pencil, Play,Pause, Star, Share, chat.

Business Core

20 Icons (in Studio Only)

Commerce, payments, finance, marketplaces, and data visualization.

Credit Card, Wallet, Dollar Coin, Calender, Shopping Bag, Key.

Your Motion Design Teammate

The system is built on the concept of OMNI: One Matter Neural Interaction. This means interfaces should feel less like code and more like life. Our goal is to make every icon feel like a living organism, moving, adapting, and responding to user interaction with fluid expressiveness.


We designed the logic specifically for developers: we use Number inputs where 0 and 1 clearly represent the false or true state (off/on), a pattern developers use daily. The result is FX: Fluid Experience.


The Core Problem We Solve

Standard icons switch jarringly, forcing the user's brain to process two separate, static states. OMNI-FX solves this by providing seamless state transitions where icons fluidly morph from one shape to the next (e.g., a menu icon elegantly animates into a close 'X'). This radically reduces cognitive load and creates moments of user delight.

Transparency Matters to Us.

OMNI-FX focuses on quality over quantity — OMNI-FX is a powerful, technical asset requiring knowledge of the Rive platform and your specific environment (React, Flutter, etc.). Built to do the essentials, elegantly.
There are a few limits and decisions we made intentionally, and we want you to know all of them. Visit our documentations for a complete, honest overview.

Try Before You Buy

Your Path to Absolute Confidence.

We proudly provide a comprehensive Free Starter Pack so you can thoroughly test the system's functionality and verify full compatibility with your technology stack and skills.

We’re here as your motion design teammate — ready to make your brand move. 🚀