Components/BotAvatar

BotAvatar

Animated canvas bot avatars for agents and assistants, with idle and working states, pointer play and per-type bodies

VerifiedSince 0.6.2

Usage

TxBotAvatar draws a glossy bot on a 2D canvas. Drive state from the agent's real status: working while it streams or runs, default when idle.

Loading demo...

In a 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

One body per agent, each showing whether it is busy. Instances offset their blink timing 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 in a settings card

<template>
  <TxBotAvatar type="hexagon" :size="96" paused />
</template>

Best Practices

  • Set size, never width / height / margin in style or a class — those override the overscan box and the negative margins, and the avatar shifts or crops.
  • The canvas is drawn 1.5× the size box and pulls itself back, so a hop or flip goes outside the layout box. Leave room above the avatar; a tight parent with overflow: hidden crops the jump.
  • Map your own statuses: running / streaming / pending / busy → working; idle / ready / online → default; offline / away / disabled → default with paused.
  • When the agent's name and status are already shown as text beside the avatar, mark it decorative with aria-hidden.
  • An unknown state falls back to default silently; an unknown type falls back to the palette default.
  • These are bots, not people: use a photo or initials for human avatars.

API Reference

Props

PropTypeDefaultDescription
type'clover' | 'flower' | 'star' | 'ghost' | 'mech' | 'circle' | 'hexagon' | 'square''clover'Body shape; each has its own palette colour.
faceBotAvatarFacetype's ownFace kind.
state'default' | 'working' | 'sleeping''default'Idle (looks around, blinks, occasional jump) or working (hops, spins, smiles).
sizenumber | string64Layout size of the avatar box; also accepts any CSS length.
colorstringtype paletteBody colour.
inkstringautoFace ink; dark by default, light on a dark body.
brightness / saturationnumber1 / 1.5Lightness and vividness of the body colour.
speednumber1Multiplier on every animation.
pausedbooleanfalseFreezes the animation on its current frame.
seednumberderived from instanceOffsets blink and glance timing so a row does not blink in unison.
shading'plastic' | 'crisp' | 'smooth' | 'flat' | boolean'plastic'How the body is lit; true is crisp, false is flat.
shadow / highlightnumber0.35 / 1.3Strength of the shadow and lit side.
depthnumber0.65Thickness of the body, 0.2-2.
lightnumber265Light direction in degrees clockwise from the top.
rimnumber0.5Lit rim width (crisp) or Fresnel strength (plastic).
spreadnumber1.55Reach of the soft shading or width of the highlight.
interactivebooleantrueEyes and head follow a nearby pointer; a click makes it hop and turn.
theme'auto' | 'dark' | 'light''auto'The surface the avatar sits on; auto reads an ancestor data-theme attribute or class, then the OS.
turnnumber1How far the head turns side to side while idle.
whirlnumber0Strength of the whirl ring round a spin.
whirlSize / whirlWidth / whirlLength / whirlTiltnumber1Whirl ring geometry.
jumpHeightnumber26How high a jump goes, in body units (the body is 100 tall).
jumpTimenumber0.68Seconds a jump spends in the air.
jumpStretch / jumpSquashnumber1 / 1.15Stretch in the air and squash on the ground.
jumpSquashTime / jumpSquashEase / jumpGroundTime / jumpGroundEase / jumpRiseTime / jumpRiseEase—tunedLanding squash shape, hold and rise.
jumpClickSquashTimenumber0.24Landing squash time for a click's jump.
jumpSpinnumber1Whole turns made in the air.
jumpLeannumber6Degrees of lean into a jump.
jumpEverynumber8Seconds between idle jumps, ±40%; 0 disables them.
jumpLandnumber0When the landing squash begins relative to touch-down (seconds).

Slots

None. The avatar is a single canvas.

Events

No component events. click, pointerenter and every other DOM handler pass straight through to the canvas.

Exposed Methods

No public instance methods.

CSS Variables

None. Colours come from props.

Overview

  • The canvas has role="img" and a per-state aria-label ("Clover bot, idle" / "Clover bot, working"); pass your own aria-label to replace it.
  • Every other attribute is passed straight to the <canvas>, so class, style, data-* and event handlers work as usual.
  • One shared requestAnimationFrame loop serves every avatar; each leaves it when scrolled offscreen (IntersectionObserver) and the loop stops while the tab is hidden.
  • Device pixel ratio is capped at 2. The default look is a per-pixel material whose form is baked on idle time the first time a body type appears; a softer look stands in for those frames.
  • prefers-reduced-motion: reduce draws the still pose of the current state and starts no loop. The media query is read at render time, not watched live.
  • State changes are cross-animated, so toggling state on every token or tool call is safe.

Technologies

  • Manually verified against index.ts, TxBotAvatar.vue, types.ts and bot-avatar.test.ts under packages/tuffex/packages/components/src/bot-avatar/.
  • engine.ts, draw.ts, plastic.ts, color.ts, ticker.ts, presets.ts and shapes.ts are verbatim ports of upstream bot-avatars (MIT © Jakub Antalik) with strict-TS index hardening only.
  • The Vue shell mirrors the upstream React component's canvas lifecycle, overscan box, shared ticker and pointer interaction. The upstream package also ships React Native and SwiftUI ports; those are out of scope here.
  • Component source: packages/tuffex/packages/components/src/bot-avatar/src/TxBotAvatar.vue.
  • Types: packages/tuffex/packages/components/src/bot-avatar/src/types.ts.
  • Upstream: Jakubantalik/Libraries · bot-avatars (MIT).
  • Coverage: packages/tuffex/packages/components/src/bot-avatar/__tests__/bot-avatar.test.ts verifies the type/shape presets, state fallback, size parsing, colour helpers, the per-state label and the paused path.
查看源码
packages/tuffex/packages/components/src/bot-avatar/index.ts