All components

Components · Learning

Hubert

The mascot. He reacts to the lesson: idle, thinking, correct, incorrect, celebrate.

Try itChange the motion setting at the top to feel each personality.

Use it

<Hubert state={answerState} lookX={x} lookY={y} />

How it moves

Hubert is the mascot. He reacts to the lesson, and his motion follows the personality like every other component: --ss-motion-energy scales how far and how big he moves, from 0 under reduced to 1 under playful. There are two versions with the same inputs: the drawing animated in CSS, and the Rive file hubert/hubert.riv, used when you pass rive={{ src, wasm }} (it needs the optional dependency @rive-app/canvas). The drawing shows until the Rive file is playing, and stays if it cannot load.

StateWhenWhat movesLength
idleNothing is happeningBreathes. Blinks at uneven times, about every one and a half to five seconds, and sometimes twice. Every few seconds he glances somewhere and back: his pupils move and his stalks lean, each a little differently. When the app sets lookX and lookY, he looks there insteadRepeats
thinkingThe app is checking or loadingSettles into his shell on the ground, his body dark inside it. His eyes look up and around, and his claws grip the rim, one tappingHolds
correctOne right answerA hop with a squash on take-off and landing, his right claw lifts in a wave, happy eyesAbout half a second
incorrectOne wrong answerHe is upset: his smile turns to a frown, sad brows come down, his stalks droop and splay, he slumps with his claws hanging, a sweat drop slides down beside his head, and he shakes his head slowly. Then he recoversAbout nine-tenths of a second
celebrateThe lesson is finishedA jump and a smaller second bounce, both claws up, happy eyesAbout a second and a half

Rules:

Reduced motion: energy is 0, so he does not hop, tilt, breathe, blink, or glance. Each reaction is still clear, because his eyes and claws change pose in place: happy eyes for correct, soft eyes for incorrect, claws up for celebrate.

Screen readers: he is hidden by default, because the lesson already says what happened. Give him a label only when he carries meaning on his own.

Colors: the six character roles, --ss-color-character-shell, -shell-shade, -claw, -claw-shade, -body, -outline.

CSS variables used: --ss-motion-energy, --ss-motion-state-change-spring, --ss-motion-state-change-spring-duration, --ss-motion-state-change-duration.

Bring your own mascot

Hubert is the starting point, not a requirement. Any character built to the same contract drops into the same component: it reacts to the lesson, looks where it is told, and follows your colors and your motion personality, with no app code changes.

It can be any style: flat, hand-drawn, or 3D. And it can do more than the five states Hubert starts with, such as giving a hint, waving hello, dozing off when no one is around, or dancing when a streak grows.

Hubert, flatThe same character in a simpler style.
The werewolf, idling
The werewolfFrom Halloween Hotel
Haruki, the ninja raccoon, idling
Haruki, the ninja raccoonFrom Character Select