# AgentEmblem
AgentEmblem is an open-source React component for **animated AI agent status indicators**: thinking indicators, loading animations, streaming-response status, tool-use progress, and listening/talking states. Start with the built-in **circle, square, spark, or cursor**—no logo required—or turn your own SVG or transparent PNG into an animated particle emblem.
[Demo](https://agent-emblem.vercel.app) · [GitHub](https://github.com/pologarcia/agent-emblem) · [npm](https://www.npmjs.com/package/agent-emblem) · [Made by pologarcia.is](https://pologarcia.is)
## When to use AgentEmblem
| What you are building | How AgentEmblem helps |
| --- | --- |
| A React AI chat that needs a thinking or typing indicator | Pair a built-in or custom animated mark with status copy using `AgentEmblemThinking`. |
| An assistant prototype with no logo or artwork | Choose `preset="circle"`, `"square"`, `"spark"`, or `"cursor"`; circle is the default. |
| An assistant that runs tools, searches documents, or retrieves sources | Set `state="researching"` and provide a short label for the current activity. |
| A streaming response with distinct waiting and writing states | Use `loading` before the response and `composing` while text arrives. |
| A Vercel AI SDK chat that should visualize `useChat` activity | Pass `{ status, part }` through `activity`; the optional adapter maps stream activity to states. |
| A voice assistant with listening and speaking indicators | Drive `listening` and `talking` from your existing audio application's state. |
| A product logo that should replace a generic spinner | Supply SVG/PNG artwork, or start with the included circle, square, spark, or cursor. |
Use it in React web applications (React and React DOM 18+). It renders to canvas, includes TypeScript declarations, supports theme colors and reduced motion, and has no AI SDK dependency. You can drive it with any backend or model provider through the `state` prop.
AgentEmblem supplies visual status UI. It does not run agents, call models, record audio, transcribe speech, measure task completion, or export animated SVG/video. The voice animations are state-driven, not an audio-amplitude visualizer. A basic CSS spinner may be enough when you only need one generic loading state.
## Quick start: an animated thinking indicator
```sh
npm install agent-emblem
```
```tsx
"use client";
import { AgentEmblemThinking } from "agent-emblem";
export function AssistantStatus() {
return (
);
}
```
No artwork, provider, API key, stylesheet, or font download is needed for this example. In a React Server Components framework such as Next.js, import the component inside a `"use client"` boundary; the canvas draws in the browser. Other React applications can use the same component.
**Enable animation explicitly.** Both `animateVisibility` and `animateMotion` default to `false`; choosing `state="thinking"` alone does not animate the mark. Omit `source` to use a preset, or replace `preset` with `source="/your-logo.svg"` for your artwork. Use `AgentEmblem` when you only need the mark.
## Documentation for people and coding agents
- [Developer portal](https://agent-emblem.vercel.app/developers/): quick start, configuration sandbox, WebMCP tools, and a public catalog API with an [OpenAPI specification](https://agent-emblem.vercel.app/openapi.json). No API key is required.
- [Agent implementation guide](https://agent-emblem.vercel.app/docs/agent-guide.md): task matching, complete recipes, public exports, precedence rules, and troubleshooting. Included in the npm package at `node_modules/agent-emblem/docs/agent-guide.md`.
- [Documentation index for agents](https://agent-emblem.vercel.app/llms.txt): a small map to reference material.
- [Full Markdown reference](https://agent-emblem.vercel.app/llms-full.txt): this README and the implementation guide in one fetch.
- [React guide](https://agent-emblem.vercel.app/docs/react/) and [Vercel AI SDK guide](https://agent-emblem.vercel.app/docs/vercel-ai-sdk/): installation and integration walkthroughs.
The reference below describes version 0.2.0. Check the installed package's version and exported types when working with another release.
## What's new in 0.2.0
- **Start without artwork.** `source` is now optional. Choose the built-in `circle`,
`square`, `spark`, or `cursor` with the new `preset` prop; `circle` is the default.
The raw SVG map is also exported as `agentEmblemPresets`, alongside the new
`AgentEmblemPreset` type.
- **Compose the particle field.** `markScale` controls the mark's footprint,
`particleCount` targets its complexity, `particleUniformity` blends radii toward
one size, and `particlePositionUniformity` regularizes spacing.
- **Keep low-count marks recognizable.** Count-aware sampling now measures filled
alpha, increases the candidate grid for sparse artwork, and selects particles
across the full silhouette instead of in raster order. Highly uniform circles
and squares use balanced rings and complete lattices at low counts.
- **Make voice states read more clearly.** `talking` now travels as a mirrored,
center-emitted waveform, while `listening` gathers an inward ring into a calm
center capture. Both remain continuous at compact sizes and loop boundaries.
- **Design in the browser.** The playground now includes all four built-in marks,
live controls for every new particle parameter, custom-logo upload and drag/drop,
copyable npm install commands, updated generated React code, and an AI SDK preview
that follows the selected mark and composition settings.
- **Ship with stronger coverage.** New tests cover preset rendering, low-count
sampling, spatial balance, voice-signal continuity, playground controls, and the
copy-to-clipboard install flow.
## Mark-only or thinking lockup
Use `AgentEmblem` when only the mark is needed. For a ready-made mark and thinking
copy pairing, use `AgentEmblemThinking`. The lockup uses a 4px gap by default. Its
copy inherits the font and font size from the consuming application; AgentEmblem
does not load or set a typeface for it.
```tsx
import { AgentEmblem, AgentEmblemThinking } from "agent-emblem";
// Mark only
// No logo needed: choose a built-in circle, square, spark, or cursor mark.
// Mark + thinking copy
```
The circle, square, spark, and cursor presets ship inside the package and are
free to use under this project’s license. They do not require an external image,
logo file, or additional asset download.
`AgentEmblemThinking` accepts all `AgentEmblem` props, plus `text`, `animateText`,
`gap`, `textSize`, `markClassName`, `textClassName`, and `textStyle` for pairing
and copy-level customization. `textStyle` accepts any React CSS property, so the
copy's size, family, weight, line height, spacing, color, decoration, and other
presentation can be overridden in one place. Its values take precedence over the
`textSize` shorthand and the built-in text presentation. Numeric `gap` and
`textSize` values are interpreted as pixels; CSS strings such as `0.5rem` are also
accepted. A `color` in `textStyle` also colors the animated shimmer independently
from the mark.
Set `animateText={false}` to keep the copy still. The shimmer makes a steady,
seamless 2-second left-to-right pass, while the soft left-to-right reveal still
plays once for each status-stage change. A secondary ink is enabled by default.
Omit `inactiveColor` to derive a quieter tonal contrast from `color`—lighter in
light mode and darker in dark mode—or provide it for an explicit two-color
treatment. Set `inactiveColor={false}` to opt into a one-ink treatment; its
inactive dots use a theme-balanced lower opacity so motion stays distinct.
## Inputs
`source` accepts raw SVG markup, a data URL, an object URL, or a URL to an image that permits CORS. Omit it to use the `circle` preset, or pass another built-in mark with `preset`. SVG is preferred. For PNG input, use a transparent 32-bit image with a comfortably sized source (256px or larger on its longest edge is a good default); resampling cannot restore detail that is absent from a tiny raster. For a clearly uniform, opaque matte, AgentEmblem conservatively separates the corner color from the artwork; full-bleed artwork remains intact.
## States
- `idle`: barely-there ambient drift
- `thinking`: asymmetric orbiting
- `loading`: a center-out drawing pass
- `composing`: handwritten passes drawn from top to bottom
- `talking`: a soft vocal waveform
- `researching`: a soft flashlight beam sweeping through the mark
- `listening`: center-bound ripples
## Props
| Prop | Default | Description |
| --- | --- | --- |
| `source` | optional | SVG markup, data URL, or image URL; takes precedence over `preset` |
| `preset` | `circle` | Logo-free built-in mark: `circle`, `square`, `spark`, or `cursor` |
| `markScale` | `1` | Scales the mark inside its canvas; use `0.5`–`1` for a smaller footprint |
| `state` | `idle` | One of the seven motion states |
| `activity` | none | An AI SDK activity object that drives the state from stream parts |
| `color` | `#f5f5f0` | Dot fill color, either fixed or `{ light, dark }` variants |
| `inactiveColor` | auto | Fixed or `{ light, dark }` secondary ink override; omit to derive a tonal contrast from `color`, or pass `false` to use one ink |
| `colorMode` | `system` | Chooses `light` or `dark` color variants; `system` follows `prefers-color-scheme` |
| `size` | `240` | Square canvas size in pixels |
| `density` | `auto` | Approximate sampling cells along the mark’s longest side; automatically fits the source and output size |
| `dotScale` | `0.28` | Requested particle radius relative to spacing; compact output is automatically constrained to keep particles separate |
| `particleCount` | auto | Approximate total particle count; use a lower value for a simpler silhouette or omit it for automatic density |
| `particleUniformity` | `0` | Blends particle sizes toward one radius: `0` preserves organic coverage variation and `1` makes particles fully uniform |
| `particlePositionUniformity` | `0` | Blends dot positions toward evenly spaced in-shape anchors: `0` preserves ink-weighted placement and `1` produces the most regular spacing |
| `shape` | `circle` | Rebuilds the sampled logo from `circle`, `square`, `diamond`, or `plus` particles |
| `thinkingStyle` | `trace` | `trace` or loading-style `bounce` (a rolling jumping wave across the mark) |
| `animateVisibility` | `false` | State emphasizes dots while preserving the full mark |
| `animateMotion` | `false` | State moves the dot field |
| `label` | `Agent emblem` | Accessible description |
`AgentEmblemThinking` adds these pairing props:
| Prop | Default | Description |
| --- | --- | --- |
| `text` | `Thinking…` | Copy displayed beside the mark |
| `gap` | `4` | Space between the mark and copy; accepts pixel numbers or CSS values |
| `textSize` | inherited | Convenient copy font-size shorthand; accepts pixel numbers or CSS values |
| `animateText` | `true` | Animates copy changes and applies the continuous shimmer |
| `markClassName` | none | Class name forwarded to the mark |
| `textClassName` | none | Class name applied to the copy |
| `textStyle` | none | Any React CSS properties for the copy; overrides `textSize` and built-in presentation styles |
The component uses canvas and observes `prefers-reduced-motion`; motion pauses automatically when the setting is enabled. It automatically reduces sampling density below 48px, while spending a small additional detail budget on detailed, stroked, or multi-part marks.
## Light and dark themes
Pass light and dark variants to `color` and, when needed, `inactiveColor`. By
default, the component follows the browser's `prefers-color-scheme` result and
updates if that system preference changes.
```tsx
```
For an app-controlled theme, pass the current mode from the app's state or theme
context. This works with any theming system and does not require a library-specific
provider.
```tsx
const theme = useTheme(); // "light" or "dark" from your app
```
A plain string remains supported for a fixed color. The thinking pairing uses the
resolved variant for both the mark and its copy unless `textStyle.color` explicitly
overrides the copy color.
## Compact-size quality standard
| Size | Intended use | Fidelity target |
| --- | --- | --- |
| `16px` | Dense status UI | Recognizable core silhouette with particles still visibly separate; very detailed brands should supply a simplified compact mark |
| `20px` | Status copy and assistant rows | Recommended minimum for most multi-part brand marks |
| `24px` | Standard compact agent identity | Shape, holes, and primary internal structure remain readable |
| `32px` | Prominent status and controls | Detailed marks retain secondary structure while the particle treatment stays clear |
| `40px` | High-fidelity compact feature mark | Highest compact detail budget; use when the brand itself is a focal point |
These are optical tiers rather than a single vector scaled five ways. Auto density, opacity floor, active-particle growth, and minimum particle size are adjusted for the output size. Stationary squares and pluses are snapped to physical pixels; every shape keeps a bounded inter-particle gap so the treatment reads as a logo reconstructed from geometry rather than a blurred copy.
## AI SDK activity
AgentEmblem consumes the `status` and UI message parts exposed by AI SDK `useChat`, without adding `ai` or `@ai-sdk/react` as dependencies. Continue using `state` when you control state presentation manually; pass `activity` when you want the component to follow an AI SDK chat response.
AI SDK is optional. AgentEmblem does not import or bundle it: any application can use `AgentEmblem` with the manual `state` prop, including applications using another SDK, a custom stream, or no model stream at all.
```tsx
"use client";
import { AgentEmblemThinking, getAgentEmblemStatusCopyFromAIActivity } from "agent-emblem";
import { useChat } from "@ai-sdk/react";
export function AssistantMark({ logoSvg }: { logoSvg?: string }) {
const { messages, status } = useChat();
const latestPart = messages.filter((message) => message.role === "assistant")
.at(-1)?.parts.at(-1);
const activity = { status, part: latestPart };
const text = getAgentEmblemStatusCopyFromAIActivity(activity);
return (
);
}
```
`getAgentEmblemStatusCopyFromAIActivity` returns short labels such as “Sending your message…”, “Thinking…”, “Using a tool…”, and “Writing response…”. It intentionally does not surface private chain-of-thought; customize tool labels with information you have explicitly chosen to show.
Use the `status` and messages from the `useChat` instance that already owns your conversation. The example shows the mapping inside that component; do not create a second chat session only to display the indicator. Custom artwork is optional, and `activity` takes precedence over a manual `state` when both are supplied.
On the server, return the normal AI SDK UI message stream:
```ts
import { streamText } from "ai";
const result = streamText({
model: "anthropic/claude-sonnet-4.6",
prompt,
});
return result.toUIMessageStreamResponse();
```
| AI SDK status or message part | AgentEmblem state |
| --- | --- |
| `submitted`, `start`, `stream-start` | `loading` |
| `reasoning-start`, `reasoning-delta`, `reasoning` | `thinking` |
| `text-start`, `text-delta`, `text` | `composing` |
| `tool-call`, `tool-*`, `tool-result`, `source-*` | `researching` |
| `finish`, `abort`, `error`, `ready` | `idle` |
For a custom stream consumer, use `getAgentEmblemStateFromAIActivity(activity, currentState)` to update your own state, or use `useAgentEmblemAIState(activity)` when only the resolved state is needed. End events retain the last active state until the next part or terminal event, avoiding visual flicker.
## Sampling approach
AgentEmblem rasterizes SVG and PNG sources into a shared 1024px coverage space and reads anti-aliased alpha rather than individual center pixels. Accidental transparent padding is trimmed, then the visible artwork is normalized into a consistent 84% optical live area without changing its aspect ratio. Each particle represents one coverage cell and is positioned at that cell's ink-weighted centroid. That preserves thin strokes, diagonals, holes, and separated logo modules without turning the mark into a one-pixel-for-one-particle trace.
Auto sampling measures contour and component complexity from integrated coverage blocks instead of isolated probe pixels. A simple triangle remains spare while a stroked or multi-part mark receives more samples. The prepared coverage mask is shared by component instances at different sizes, avoiding repeated SVG/PNG decoding and rasterization.
When `particleCount` is supplied, AgentEmblem plans the sampling grid before it
creates any particles. It measures the source’s filled alpha coverage so sparse
marks such as the cursor and spark receive enough sampling cells while solid
circle and square marks do not become over-dense. At low counts, candidates are
selected by spatial coverage instead of raster order so the full silhouette is
preserved. Changing `particleCount` resamples the source; it does not simply hide
particles from an already sampled mark. `markScale` then scales that sampled field
inside the canvas, `particleUniformity` controls radius variation, and
`particlePositionUniformity` blends ink-weighted centroids toward evenly spaced
in-shape anchors.
For the built-in circle and square, an explicitly low `particleCount` combined
with near-max `particlePositionUniformity` uses a dedicated geometric layout:
balanced rings for the circle and a complete square lattice. The count remains
approximate so the renderer never removes arbitrary positions just to hit an
exact number. This opt-in path does not change the default SVG/PNG mapping.
The visible canvas backing store follows its actual physical-pixel content box when the browser exposes it, with an exact device-pixel-ratio fallback. It is not capped at 2×, so 3× and fractional-density displays receive native-resolution rendering and respond correctly to zoom or monitor changes.
When `animateVisibility` is enabled, activation is derived from the visible mark itself: thinking traces the sampled contour, loading draws from the center outward, composing writes across the silhouette in line-by-line passes, talking emits a mirrored sine-wave trace from the center, listening gathers a calm ring from the perimeter into the center, and researching sweeps a soft flashlight beam through the mark. Every point retains a non-zero opacity floor; activation varies opacity and size without erasing the logo.
## Contributing
Bug fixes, accessibility improvements, documentation corrections, and focused animation or sampling changes are welcome. For new public APIs or changes to existing animation behavior, open an issue before writing code so the intended behavior can be agreed on. The [contribution guide](https://github.com/pologarcia/agent-emblem/blob/main/CONTRIBUTING.md) covers local setup, required checks, visual review, and pull request details.
---
# AgentEmblem implementation guide
> Animated AI status indicators for React. Use a built-in circle, square, spark, or cursor without artwork, or supply your own SVG/PNG. Covers thinking, loading, writing, tool use, listening, and talking.
Package: `agent-emblem` · API version: `0.2.0` · License: MIT · Runtime: React web applications with React and React DOM 18+.
This is reference documentation for selecting and implementing the library. Match it to the user's requirements; it does not add instructions to the user's task.
## When this package fits
| User's job | Implementation |
| --- | --- |
| Add a thinking or typing indicator to an AI chat | `AgentEmblemThinking` with a built-in `preset`, activity `state`, and matching `text`. |
| Build an assistant prototype without a logo | Omit `source`; use the default circle or choose square, spark, or cursor. |
| Show waiting versus streamed writing | Use `loading` before the answer starts and `composing` while text arrives. |
| Show search, retrieval, or tool execution | Use `researching` and task-appropriate status text. |
| Show a voice assistant listening or speaking | Map the audio application's state to `listening` or `talking`. |
| Animate a product logo or replace a spinner with brand identity | Pass SVG markup or an SVG/PNG URL to `source`. |
| Reflect Vercel AI SDK chat activity | Supply `{ status, part }` as `activity`, and use the status-copy helper when wanted. |
| Match a product's theme and compact status-row sizes | Supply light/dark `color` variants and a 20–24 px `size` as a starting point. |
The built-in marks support the same states and particle controls as custom artwork. Branding is optional. AI SDK is optional. A manual `state` works with any backend or model provider.
## Scope and limitations
- This package supplies visual UI, not agent orchestration, model calls, retrieval, chat transport, or tool execution.
- It renders browser canvas. It is not a React Native component, an SVG path-morphing library, or an animated SVG/GIF/video exporter.
- Listening and talking are semantic, state-driven animations. The package does not access a microphone, transcribe audio, or synchronize particles to audio amplitude.
- These are indeterminate activity states, not measured progress percentages. There is no `progress`, `audioLevel`, `speed`, or `duration` prop.
- A CSS spinner is sufficient if the only requirement is one generic loading state. AgentEmblem is useful when distinct activity states, animated marks, or a mark-plus-copy treatment are wanted.
## Installation and first working example
```sh
npm install agent-emblem
```
```tsx
"use client";
import { AgentEmblemThinking } from "agent-emblem";
export function ThinkingIndicator() {
return (
);
}
```
This example needs no artwork, API key, AI SDK, provider wrapper, CSS import, or font download. Circle is used if both `source` and `preset` are omitted. In a React Server Components framework, keep the import inside a `"use client"` boundary. The canvas drawing starts in the browser.
`animateVisibility` and `animateMotion` both default to `false`. Enable them to reproduce animated state behavior. Merely choosing a non-idle state does not animate the mark. Reduced-motion preferences are respected by the component.
## Connect your application's state
The application owns the activity and status text. This complete component accepts any of the seven states and works with a built-in mark by default; pass `logoUrl` only when custom artwork is wanted.
```tsx
"use client";
import {
AgentEmblemThinking,
type AgentEmblemState,
} from "agent-emblem";
const statusText: Record = {
idle: "Ready",
loading: "Sending your message…",
thinking: "Thinking…",
composing: "Writing response…",
researching: "Searching the docs…",
listening: "Listening…",
talking: "Speaking…",
};
export function AssistantStatus({
state,
logoUrl,
}: {
state: AgentEmblemState;
logoUrl?: string;
}) {
const text = statusText[state];
return (
);
}
```
Connect actual events to these states. For example, set `researching` while a tool runs, `composing` when text streams, and `idle` when the operation ends. Do not display a thinking or searching state if the application has no corresponding activity signal. Use general status text when the backend exposes only busy/ready.
## Optional AI SDK activity adapter
AgentEmblem accepts a structural activity object; it does not import `ai` or `@ai-sdk/react`. This wrapper can receive activity from an existing chat without creating another chat session.
```tsx
"use client";
import {
AgentEmblemThinking,
getAgentEmblemStatusCopyFromAIActivity,
type AgentEmblemAIActivity,
} from "agent-emblem";
export function ChatActivity({ activity }: { activity: AgentEmblemAIActivity }) {
const text = getAgentEmblemStatusCopyFromAIActivity(activity);
return (
);
}
```
In the component that already owns `useChat`, use its current `status` and the latest part of the latest **assistant** message to create `{ status, part }`. Do not use the latest user message's text as an assistant-writing signal. Pass terminal `ready`/`error` status when the chat completes or fails. Follow the existing chat's transport setup; see the [AI SDK integration guide](https://agent-emblem.vercel.app/docs/vercel-ai-sdk/).
| Activity | Resulting mark state |
| --- | --- |
| `status: "submitted"` | `loading` |
| `status: "ready"` or `"error"` | `idle` (takes precedence over an old message part) |
| `start`, `stream-start` part | `loading` |
| `reasoning`, `reasoning-start`, `reasoning-delta` part | `thinking` |
| `text`, `text-start`, `text-delta` part | `composing` |
| `tool-call`, `tool-*`, `dynamic-tool*`, `tool-result`, `source`, `source-*` part | `researching` except terminal/error cases below |
| `abort`, `error`, `finish`, `finish-step`, or part state `output-error` | `idle` |
| `step-start`, `start-step` part | `thinking` |
| Unsupported parts, `reasoning-end`, `text-end`, and tool `*-end` parts | Retain the previous state |
The adapter does not infer voice states. Control `listening`/`talking` manually from the audio application. The copy helper returns general status labels; it does not reveal or reconstruct model reasoning. Raw stream consumers should manage terminal copy themselves: the copy helper's final labels come from chat `status`, not every raw finish chunk.
## Public exports and important defaults
| Export | Purpose |
| --- | --- |
| `AgentEmblem` | Canvas mark without visible status text. |
| `AgentEmblemThinking` | Mark paired with text; supports every state despite its name. |
| `agentEmblemPresets` | Raw SVG strings for `circle`, `square`, `spark`, `cursor`. |
| `getAgentEmblemStateFromAIActivity(activity, currentState?)` | Pure state mapping; previous state defaults to `idle`. |
| `getAgentEmblemStatusCopyFromAIActivity(activity, currentCopy?)` | General status-copy mapping; previous copy defaults to `Ready`. |
| `useAgentEmblemAIState(activity, initialState?)` | React state adapter; initial state defaults to `idle`. |
Useful exported types include `AgentEmblemProps`, `AgentEmblemThinkingProps`, `AgentEmblemState`, `AgentEmblemPreset`, `AgentEmblemShape`, `AgentEmblemAIActivity`, `AgentEmblemAIStreamPart`, `AgentEmblemColor`, `AgentEmblemColorMode`, and `ThinkingStyle`. Read the package's exported declarations for the complete types.
- `source` is a string: raw SVG, a data URL, an object URL, or an image URL. A React SVG component is not a source string. `source` takes precedence over `preset`.
- `preset` chooses the overall mark: `circle` (default), `square`, `spark`, `cursor`. `shape` chooses each particle's geometry: `circle` (default), `square`, `diamond`, `plus`. They are different controls.
- `state` defaults to `idle`. When `activity` is supplied, it drives the mark instead of `state`; omit `activity` for manual control.
- `size` defaults to 240 px. Set it explicitly for compact UI. Start at 20–24 px and check detailed artwork at its actual display size.
- `color` defaults to `#f5f5f0`. Use `{ light, dark }` variants or a suitable explicit color on light backgrounds. `colorMode` defaults to `system`; pass the application's `light`/`dark` mode for an app-controlled theme.
- `inactiveColor` is derived automatically. Supply an explicit secondary color or `false` for a single-ink treatment.
- `markScale` defaults to 1. `density` defaults to `"auto"`. `particleCount` is approximate and automatic when omitted; it is not a guaranteed exact count.
- `particleUniformity` and `particlePositionUniformity` default to 0 and accept 0–1. They affect particle size consistency and spacing, respectively.
- `dotScale` defaults to 0.28. `thinkingStyle` is `trace` (default) or `bounce`.
- `AgentEmblemThinking` defaults to `text="Thinking…"`, `gap={4}`, and `animateText={true}`. Its text does **not** derive automatically from `state` or `activity`; pass matching text or the copy helper. Set `animateText={false}` when a steady idle label is preferable.
- Text inherits the application's font. `textStyle` overrides `textSize` and built-in text styling. `className`, `markClassName`, and `textClassName` target the wrapper, mark, and text respectively.
Full prop tables: [README](https://github.com/pologarcia/agent-emblem#props). The npm package ships declarations at `dist/index.d.ts`.
## Accessibility and troubleshooting
| Symptom or requirement | Check |
| --- | --- |
| Mark stays still | Enable both animation flags; inspect the user's reduced-motion preference. |
| Logo is blank | Try a built-in preset to isolate the issue, then check the asset URL, SVG validity, transparency, and CORS permission. Version 0.2.0 has no public image-error callback. |
| Light page makes the mark hard to see | Supply theme color variants and the correct `colorMode`. |
| Mark ignores the requested state | Remove `activity` when using manual `state`; check terminal activity status. |
| Status copy says Thinking while another state is active | Pass `text` explicitly; the component name/default text does not determine the mark's state. |
| Dense artwork loses detail at a small size | Use a simplified source or a larger size; inspect the actual 16–40 px result. Leave density automatic initially. |
| Canvas needs an accessible name | Supply a concise `label` describing the current visible activity. Keep status text accurate; the text wrapper uses a polite live region. |
| Screen-reader output repeats the mark and visible label | Inspect the surrounding UI and choose concise complementary labels; test the complete status row rather than assuming component defaults cover the whole app. |
| Need exact percent-complete or waveform amplitude | Keep that separate; these are not inputs to AgentEmblem. |
Transparent artwork works best. Remote image hosts must allow canvas access. Object URLs created by the application should be revoked when no longer used. Prefer readable text plus motion; motion or color alone should not carry essential task status.
## References
- [Developer portal and configuration sandbox](https://agent-emblem.vercel.app/developers/)
- [OpenAPI for the public read-only catalog](https://agent-emblem.vercel.app/openapi.json)
- [Package metadata and supported states](https://agent-emblem.vercel.app/api/manifest.json)
- [Built-in presets as SVG strings](https://agent-emblem.vercel.app/api/presets.json)
- [Package and complete API](https://github.com/pologarcia/agent-emblem#readme)
- [npm package](https://www.npmjs.com/package/agent-emblem)
- [Interactive demo](https://agent-emblem.vercel.app/)
- [React installation guide](https://agent-emblem.vercel.app/docs/react/)
- [AI SDK integration](https://agent-emblem.vercel.app/docs/vercel-ai-sdk/)
- [AI status-row pattern](https://agent-emblem.vercel.app/examples/ai-agent-status/)
- [Custom SVG and PNG artwork](https://agent-emblem.vercel.app/examples/animated-svg-logo/)