Skip to content
TrademarkTrademark
Docs
Components

Mascot

Updated: October 20, 2026
View on GitHub
Soon
Not released yet. The published package does not include this yet, so it will not install today.

Mascot is one soft, single-color shape with eyes. By default its eyes are the tiles of the Once UI mark, and they turn like the logo loader while it thinks. It takes the same props as the web Mascot, and a seed gives the same character on the phone as in the browser.

States and moods

state is what the assistant is doing: idle, listening, thinking, speaking or sleeping. Each one has its own pose and motion. mood is the expression on top: neutral, happy, surprised, sad, skeptical, wink, focused or determined. Changing either one plays a short squash, then the face eases into the new expression.

Speaking with audio

While state is speaking, the body and mouth move on their own loop. Pass level, a loudness from 0 to 1, to make them move with the voice instead. Read it from your audio player's metering, for example expo-audio's metering.

Make it yours

Every part of the look is a prop: color (a scheme or any hex, rgb() or oklch() color), roundness, aspect, surface, eyes, eyeSize, eyeSpacing, eyeHeight, eyeColor, mouth, brows, cheeks and personality. bodyPath replaces the outline with your own SVG path, and accessory draws react-native-svg elements with the body.

seed picks a whole look from any string or number, such as a user id. Props you pass win over the seed. mascotLook(seed) returns that look, so you can store it or tweak it.

Accessibility

The mascot is one image. Screen readers hear "Assistant" and the state, such as "Assistant, thinking". Pass ariaLabel to name it after your product. With reduce motion turned on in the device settings, it holds still and keeps its expressions.

Differences from the web

  • There is no pointer on a phone, so lookAt="pointer", the web default, looks ahead. Pass { x, y } from -1 to 1 to make it look somewhere.
  • source, an audio element or stream on the web, is not available. Pass level from your audio library instead.
  • accessory takes react-native-svg elements, such as Circle and Path, not DOM <svg> elements.
  • The animations are computed in JavaScript each frame and drawn with react-native-svg, so keep the number of mascots on one screen small.

API reference

Prop
Type
Default
Description
state"idle" | "listening" | "thinking" | "speaking" | "sleeping""idle"What the assistant is doing.
mood"neutral" | "happy" | "surprised" | "sad" | "skeptical" | "wink" | "focused" | "determined""neutral"The expression on top of the state.
seedstring | numberPicks a whole look. Props you pass win over it.
color"brand" | "accent" | "neutral" | string"brand"A scheme or any color. Every shade comes from it.
roundnessnumber0.7From 0, a rounded square, to 1, a circle.
aspectnumber1Width over height of the body.
bodyPathstringYour own outline, an SVG path in a 200 × 200 box.
surface"glossy" | "matte" | "flat" | "glass""glossy"How the body takes light.
eyes"tile" | "pill" | "round" | "wide" | "dot" | { path: string }"tile"The eye shape.
eyeSizenumber1Scale of the eyes.
eyeSpacingnumber1Distance between the eyes.
eyeHeightnumber0From -1, up, to 1, down.
eyeColorstringThe features' color. Defaults to a near-black tinted by the body.
mouth"none" | "smile" | "dot" | "line""none"A mouth that follows the mood and moves while speaking.
browsbooleanfalseBrows that follow the mood.
cheeksbooleanfalseBlushed cheeks.
personality"calm" | "default" | "bouncy""default"How it moves.
accessoryReactNodereact-native-svg elements drawn with the body.
lookAt"pointer" | "center" | { x: number; y: number }"pointer"Where the eyes look. pointer looks ahead on a phone.
levelnumberLoudness from 0 to 1 while speaking.
size"s" | "m" | "l" | "xl" | number"l"32, 48, 96 or 160 points, or a number of points.
ariaLabelstringWhat screen readers hear. Defaults to "Assistant" and the state.
...FlexPropsFlexPropsSpacing, position and the other Flex props.
Edit this page on GitHub