Rive animation

The rive component plays a Rive animation inside a cell: a bell that rings when the count goes up, a spinner, a small character that reacts to the pointer. The Designer calls it Rive. The animation's state machine inputs can follow fields of the notification and the position of the pointer, and a click on it can run an action.

This page is the property reference. Preparing the file in the Rive editor, getting it into Herald, and troubleshooting are in Rive in Herald.

Look at the inspector fields, which set the properties below. The animation does not draw in this capture, so the cell shows a placeholder.
The Designer with a Rive cell selected and its settings in the inspector: Asset, Artboard, State machine, Inputs, Loop, Ratio, Height and Runs

Look at the inspector fields, which set the properties below. The animation does not draw in this capture, so the cell shows a placeholder.

Minimal exampleJSON
{"type":"rive","asset":"bell"}

This plays the file that the app's manifest declares as the asset bell, using the asset's state machine or the file's default.

Realistic example

A bell next to a title and a count. The bell rings when count changes, reacts when the pointer is over it, and marks the message read when it is clicked.

JSON
{"name":"rive-demo","app":"example.bidbot","layoutVersion":2,"collapseEmpty":true,
 "grid":{"rows":2,"cols":3,"rowSizes":["auto","auto"],"colSizes":[48,"fill","auto"],"gap":8,"padding":14,"width":400},
 "cells":[
  {"id":"bell","row":0,"col":0,"rowSpan":2,"align":"topLeading",
   "component":{"type":"rive","asset":"bell","stateMachine":"Main","height":40,
                "inputBindings":{"count":"{count}","hover":"hover"},"actionRef":"markRead"}},
  {"id":"title","row":0,"col":1,"component":{"type":"text","binding":"{title}","style":"title","maxLines":2}},
  {"id":"badge","row":0,"col":2,"align":"topTrailing","component":{"type":"badge","binding":"{count}","color":"#FF3B30"}},
  {"id":"sub","row":1,"col":1,"colSpan":2,"component":{"type":"text","binding":"{subject}","style":"subtitle"}}]}

Properties

PropertyTypeDefaultDescription
typestringrequiredAlways "rive".
assetstringnoneThe id of an asset that the app's manifest declares, or of a stored copy. It wins over path when both are set.
pathstringnoneA .riv file instead of an asset. The accepted forms are listed under the table.
stateMachinestringthe asset's, else the file's default, else its firstThe name of the state machine to play.
artboardstringthe file's defaultThe name of the artboard to draw.
inputBindingsobjectnoneMaps the name of a state machine input to a {token}, a literal, or the keyword hover or pressed. See Inputs.
actionobjectnoneAn inline action that a click on the animation runs.
actionRefstringnoneThe id of a resolved action that a click on the animation runs.
loopbooleanthe animation's ownFor a file with no state machine only: true loops the animation and false plays it once.
aspectRationumberthe artboard's ownWidth divided by height of the box, above 0.
heightnumberderivedA fixed height in points, above 0.
emptyBehaviorstringtemplate defaultcollapse or keep. See Empty animations.

path accepts these forms:

  • An absolute path.
  • ~/....
  • A file: URL.
  • A name relative to the app's assets folder. A relative path cannot contain ...

Remote URLs are refused.

The component needs an asset or a path. Without one the validator reports an error. When a manifest is given, two cases are a warning:

  • An asset that the manifest does not declare.
  • An input name that the asset's inputs list does not contain.

What plays#

Herald loads the file, checks that it is a .riv file of at most 10 MB, and plays it with the whole artboard visible and centred in its box. The state machine is the first of these that exists: stateMachine, the manifest asset's state machine, the file's default, then the file's first. A file with no state machine plays its first animation, and loop chooses between looping and playing once.

If the file cannot be found, is too large, is not a Rive file, or names an artboard or state machine that does not exist, the cell shows a dashed placeholder that gives the reason, for example no state machine "main" (available: Main). The banner is not affected otherwise.

Inputs#

Each entry of inputBindings connects one input of the state machine to a value. Herald tells number, boolean and trigger inputs apart by asking the state machine.

ValueMeaning
"{count}"One token. The field's own value is used, so a number stays a number.
"3" or "{count} new"A literal or mixed text. The substituted text is the value.
"hover" or "pressed", in any caseThe pointer drives the input and data never does.

How a value is applied depends on the input:

Input kindA field value is applied ashover and pressed
NumberThe number. A list gives its length, a boolean gives 1 or 0, and text is read as a number when it can be.1 while active, else 0.
BooleanIts truthiness. false, no, off, 0, an empty text and an empty list are false.True while active.
TriggerIt fires when the value changes to something true. A bell can ring when {count} goes up.It fires when the pointer becomes active.

A token that is absent leaves its input alone. An input name the state machine does not have is ignored without an error. Names are case-sensitive.

The two keywords are:

  • hover is true while the pointer is over the animation.
  • pressed is true while the mouse button is held down on it.

Herald does not pass pointer movement to the file, so a Rive "pointer enter", "exit" or "move" listener does not fire. Use a boolean input bound to hover instead. Mouse down, drag and up are passed on, but only when the animation takes clicks, which it does when it has an action or actionRef or a pressed binding.

Clicking#

With an action or actionRef, a click on the animation runs that action. A click is a press and release inside the animation. The pointer becomes a pointing hand over it and VoiceOver treats it as a button. Without either, clicks fall through to the banner, which still tracks hover. The action runs with the same gates as for a button.

Sizing and alignment#

  • height fixes the height. The width then follows from aspectRatio, or from the artboard's proportions.
  • Without height, the box takes the width of its cell and a height from the aspect ratio: yours, else the artboard's, else 4 to 1.
  • Each side is limited to 1 through 2000 points. A placeholder for a failed load is 44 points high.
  • The box fills the cell width. Alignment only positions it when the cell is larger than the box, for example in a fixed-height row.

Light and dark#

Herald draws exactly what is in the file, on a transparent background over the translucent banner. Design with a transparent artboard and colours that work on both appearances. Herald does not switch Rive themes on its own. To react to the appearance, add a boolean input and bind it to a field.

Empty animations#

The component is empty only when neither asset nor path is set, which the validator rejects anyway. Tokens in inputBindings do not make it empty: an animation with absent fields still plays.

Static previews#

The preview endpoint, the MCP tool render_preview and History thumbnails draw a dashed placeholder with the asset name at the right size, not the animation. To check the animation without a window, use the Rive check described in Testing without a window, or look at a live banner.

Accepted older forms#

Older formCurrent form
"action": "markRead" (a string)"actionRef": "markRead"

Common mistakes#

MistakeWhat happensFix
A state machine name with the wrong case.The placeholder reads no state machine "main" (available: Main).Copy the names from POST /v1/rive/check.
An input name with the wrong case.The input is ignored without an error.Copy the names from POST /v1/rive/check.
Binding a text value to a number input.Text that is not a number is ignored.Bind a numeric field, or a list, which gives its length.
Expecting a Rive hover listener to fire.Pointer movement is not passed to the file.Use a boolean input and "hover":"hover".
Checking the animation with render_preview.It shows a placeholder.Use POST /v1/rive/check, or look at a live banner.

Edit this page on GitHub

Esc
Getting started
Guides