Agent

Companion

View as markdown

A face with eyes that morph between expressions, blink and look around.

Preview

neutral

Small even ovals. The default resting face.

Usage

It runs on its own. Give it a state and it picks the expression and blinks at its own pace.

TypeScript

<Companion state="thinking" />

The eyes are cut out of the body, so whatever the face sits on shows through them. Colour comes from the text colour, so text-accent or any other token sets it.

States

A state is a way of behaving. It picks the expression and sets the blink rate.

sleeping
waking
idle
listening
thinking
searching
working
excited
curious
happy
sad
angry
surprised
confused

Expressions

Pass an expression to pin one and ignore the state's choice. Changing it morphs point by point rather than cutting.

neutral
attentive
delighted
startled
sleepy
unconvinced
composed
stern
relaxed
squinting
alert
elated
scanning
asleep
pondering
peering
intense
amused
inspecting
engaged
absorbed
shocked
drowsy
suspicious
bashful
wink
joyful
crestfallen
content
furious
worried
saucer
beady
skyward
lowered

Sizes

Any pixel size. The drawing is vector, so the box is the only thing that changes.

Colour

A token, not a class. current inherits the text colour where a token does not cover it.

accent
ink
ok
warn
danger
info
current

Shapes

The silhouette the eyes are cut out of. Each one scales and drops the face to keep the eyes inside it.

blob
heptagon
hexagon
pentagon
triangle

Source

One file. Every eye is a ring of 48 points in a fixed order, which is what lets any expression morph into any other.

Files

packages/ui/src/components/Companion.tsx

Last updated: 13 August 2026