BotAvatar
An animated bot avatar drawn on a canvas.
Usage
Basic
Drive state from the agent's real status: working while it streams or runs, default when idle.
Loading demo...
Chat Reply
<template>
<div class="msg msg--bot">
<TxBotAvatar type="clover" :state="streaming ? 'working' : 'default'" :size="32" />
<div class="msg-body">
{{ streaming ? 'Thinking…' : content }}
</div>
</div>
</template>
Agent Roster
Each instance offsets its blink timing by default, so a row never blinks in unison.
<template>
<ul class="roster">
<li v-for="agent in agents" :key="agent.id">
<TxBotAvatar :type="agent.avatar" :state="agent.busy ? 'working' : 'default'" :size="32" aria-hidden />
<span>{{ agent.name }}</span>
<span class="muted">{{ agent.status }}</span>
</li>
</ul>
</template>
Still Avatar
<template>
<TxBotAvatar type="hexagon" :size="96" paused />
</template>
Best Practices
- Set
size; never putwidth,height, ormargininstyleor a class, or the avatar shifts or crops. - Leave room above the avatar: the canvas draws 1.5× the
sizebox, so a jump leaves the layout box and anoverflow: hiddenparent crops it. - Map your own statuses:
running/streaming/pending/busy→working;idle/ready/online→default;offline/away/disabled→defaultwithpaused. - When the name and status already appear as text beside it, mark the avatar decorative with
aria-hidden. - Use it for bots only; give people a photo or initials.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | BotAvatarType | 'clover' | Body shape; each has its own palette color. |
face | BotAvatarFace | type's own | Face kind. |
state | 'default' | 'working' | 'sleeping' | 'default' | Idle (looks around, blinks, jumps now and then), working (hops, spins, smiles), or sleeping. |
size | number | string | 64 | Layout size; also accepts any CSS length. |
color | string | type palette | Body color. |
ink | string | auto | Face ink; dark by default, light on a dark body. |
brightness / saturation | number | 1 / 1.5 | Lightness and vividness of the body color. |
speed | number | 1 | Multiplier on every animation. |
paused | boolean | false | Freezes the animation on its current frame. |
seed | number | derived from instance | Offsets blink and glance timing so a row doesn't move in unison. |
shading | 'plastic' | 'crisp' | 'smooth' | 'flat' | boolean | 'plastic' | How the body is lit; true means crisp, false means flat. |
shadow / highlight | number | 0.35 / 1.3 | Strength of the shadow and lit sides. |
depth | number | 0.65 | Body thickness, 0.2–2. |
light | number | 265 | Light direction in degrees clockwise from the top. |
rim | number | 0.5 | Lit rim width under crisp, Fresnel strength under plastic. |
spread | number | 1.55 | Reach of the soft shading, or width of the highlight. |
interactive | boolean | true | Eyes and head follow a nearby pointer; a click makes it hop and turn. |
theme | 'auto' | 'dark' | 'light' | 'auto' | The surface beneath; auto reads an ancestor data-theme attribute or class, then the OS. |
turn | number | 1 | How far the head turns side to side while idle. |
whirl | number | 0 | Strength of the whirl ring around a spin. |
whirlSize / whirlWidth / whirlLength / whirlTilt | number | 1 | Whirl ring geometry. |
jumpHeight | number | 26 | Jump height in body units; the body is 100 tall. |
jumpTime | number | 0.68 | Seconds a jump spends in the air. |
jumpStretch / jumpSquash | number | 1 / 1.15 | Stretch in the air and squash on the ground. |
jumpSquashTime / jumpSquashEase | number / BotAvatarSquashEase | 0.37 / 'pulse' | Seconds and easing of the landing squash, from contact to recovery. |
jumpGroundTime / jumpGroundEase | number / BotAvatarSquashEase | 0.11 / 'pulse' | Seconds and easing of the hold at the deepest squash. |
jumpRiseTime / jumpRiseEase | number / BotAvatarSquashEase | 0.33 / 'pulse' | Seconds and easing of the rise from the deepest squash back to shape. |
jumpClickSquashTime | number | 0.24 | Landing squash time for a click's jump. |
jumpSpin | number | 1 | Whole turns made in the air. |
jumpLean | number | 6 | Degrees of lean into a jump. |
jumpEvery | number | 8 | Seconds between idle jumps, ±40%; 0 disables them. |
jumpLand | number | 0 | When the landing squash starts relative to touch-down, in seconds. |
BotAvatarType has 18 shapes: clover, flower, triangle, square, blob, ghost, circle, drop, star, droid, mech, alien, hexagon, cat, cloud, pill, pebble, and puddle. BotAvatarFace is 'eyes' | 'mouth'. BotAvatarSquashEase is 'sharp' | 'pulse' | 'soft' | 'bouncy'.
Exposed Methods
| Name | Type | Description |
|---|---|---|
canvas | HTMLCanvasElement | null | The root <canvas> element. |
Overview
- The canvas is a
role="img"whosearia-labelfollows the state ("Clover bot, idle"); passaria-labelto replace it. - Other attributes and DOM listeners pass straight to the
<canvas>, soclass,style, anddata-*work as usual. - An unknown
statefalls back todefault; an unknowntypefalls back toclover. - One shared
requestAnimationFrameloop serves every avatar; drawing stops offscreen and while the tab is hidden. - Under reduced motion no loop starts and only the state's still pose is drawn; the preference is read at render time, not watched.
- State changes cross-animate, so switching
stateon every token or tool call is safe.
Technologies
- Device pixel ratio is capped at 2;
plasticshading bakes each body type on idle time when it first appears, with a softer look standing in until then. - The drawing engine is a verbatim port of upstream Jakubantalik/Libraries · bot-avatars (MIT © Jakub Antalik); the Vue shell mirrors its React component.
- Source:
packages/tuffex/packages/components/src/bot-avatar/.
查看源码
packages/tuffex/packages/components/src/bot-avatar/index.ts