StatusLabel
A two-line caption for the orb: the current voice state on top and a spaced-out brand mark below. Place it under the orb or the PushToTalkButton.
import { StatusLabel } from 'jarvis-react-ui';
States
state takes an AppOrbState and maps it to a built-in text. Every state except idle is shown
in the bright accent color.
state |
Text |
|---|---|
idle |
READY |
listening |
listening... |
thinking |
thinking... |
speaking |
speaking... |
follow_up |
follow-up... |
working |
working... |
import { StatusLabel } from 'jarvis-react-ui';
import type { AppOrbState } from 'jarvis-react-ui';
const STATES: AppOrbState[] = ['idle', 'listening', 'thinking', 'speaking', 'follow_up', 'working'];
export default function States() {
return (
<div className="grid grid-cols-2 gap-6 sm:grid-cols-3">
{STATES.map((state) => (
<div key={state} className="flex flex-col items-center gap-2">
<StatusLabel state={state} />
<code className="text-[9px] text-text-muted">{state}</code>
</div>
))}
</div>
);
}
Custom texts and localization
labels overrides the text per state, for example to translate it. It is a partial map: states you
leave out keep their built-in text.
import { StatusLabel } from 'jarvis-react-ui';
import type { AppOrbState } from 'jarvis-react-ui';
const GERMAN: Partial<Record<AppOrbState, string>> = {
idle: 'BEREIT',
listening: 'hört zu...',
thinking: 'denkt nach...',
speaking: 'spricht...',
follow_up: 'Rückfrage...',
working: 'arbeitet...',
};
export default function Localized() {
return (
<div className="flex gap-10">
<StatusLabel state="idle" labels={GERMAN} />
<StatusLabel state="thinking" labels={GERMAN} />
<StatusLabel state="follow_up" labels={GERMAN} />
</div>
);
}
Custom brand
brand replaces the default J A R V I S mark. Spaces between the letters are part of the string;
the component only adds letter spacing.
import { StatusLabel } from 'jarvis-react-ui';
export default function CustomBrand() {
return <StatusLabel state="thinking" brand="F R I D A Y" />;
}
With the orb state
Feed StatusLabel the same state as your orb and pair it with WaveformMeters that run while audio flows. This demo cycles through the states on a timer; in an app the state comes from your voice pipeline. To switch states by hand while developing, use StateSimulator.
import { useEffect, useState } from 'react';
import { StatusLabel, WaveformMeter } from 'jarvis-react-ui';
import type { AppOrbState } from 'jarvis-react-ui';
const CYCLE: AppOrbState[] = ['idle', 'listening', 'thinking', 'speaking', 'follow_up', 'working'];
export default function OrbStateCycle() {
const [index, setIndex] = useState(0);
const state = CYCLE[index % CYCLE.length] ?? 'idle';
const audible = state === 'listening' || state === 'speaking';
useEffect(() => {
const id = setInterval(() => setIndex((i) => i + 1), 1800);
return () => clearInterval(id);
}, []);
return (
<div className="flex items-center gap-6">
<WaveformMeter active={audible} />
<StatusLabel state={state} />
<WaveformMeter active={audible} mirrored />
</div>
);
}
Announce state changes
Set live on the one StatusLabel that represents the assistant state. The status text becomes a
polite live region, so screen readers announce each new state after the current speech:
<StatusLabel state={state} live />
The demos on this page leave live off, because the cycling demo would announce a change every
couple of seconds.
Accessibility
- By default the label is plain text and state changes are not announced. Set
liveto make the status text a polite live region (role="status",aria-live="polite"), so screen readers announce each new state without interrupting. Render only one live StatusLabel per screen, or every copy is announced. - It ignores pointer events (
pointer-events: none), so it never blocks clicks on the orb behind it.
API
| Prop | Type | Default | Description |
|---|---|---|---|
state (required) |
'idle' | 'listening' | 'thinking' | 'speaking' | 'follow_up' | 'working' |
Current orb state; selects the status text (READY, listening..., ...) and highlights it in the accent color for every state except idle. |
|
brand |
string |
J A R V I S |
Brand text shown in small, widely spaced letters below the status. |
className |
string |
Extra classes for the root <div> element. |
|
labels |
Partial<Record<AppOrbState, string>> |
Custom status texts per state, e.g. for localization; states you leave out keep their built-in text (READY, listening..., thinking..., speaking..., follow-up..., working...). |
|
live |
boolean |
false |
Turns the status text into a polite live region (role="status", aria-live="polite"), so screen readers announce state changes. |
Type AppOrbState
Full app-layer orb state — a superset of OrbState that includes
states handled above the base state machine.
Components and hooks should use AppOrbState for their props / return values.
type AppOrbState = OrbState | 'working';
Type OrbState
States that drive the JARVIS orb visual and audio state machine. Single source of truth — copied from src/types.ts.
type OrbState = 'idle' | 'listening' | 'thinking' | 'speaking' | 'follow_up';