StatusBadge

Show the state of a server, agent, task or tool with one shared vocabulary: idle, pending, running, success, warning, error, disabled and needs-auth. Each status has a color, an icon and a default label; pending and running show a loader. Map your domain status to it (for example getMcpAgentUiStatus) and override the text with label. variant="dot" fits dense rows.

Getting Started
$pnpm add @sinups/ai-kit @mantine/core @mantine/hooks @tabler/icons-react
Examples
All statuses
In rows
Source

The component source as it ships in the package. Useful as a reference, or as a starting point if you want to fork a piece.

primitives/StatusBadge/StatusBadge.tsx
import React, { memo } from 'react';
import { Badge, ColorSwatch, Group, Loader, Text, type MantineSize } from '@mantine/core';
import { cx } from '../../utils/cx';
import { getStatusMeta, type AgentUiStatus } from './status-meta';
import classes from './StatusBadge.module.css';

export interface StatusBadgeProps {
  /** Status from the shared vocabulary */
  status: AgentUiStatus;
  /** Overrides the default English label of the status */
  label?: string;
  /** `badge` renders a Mantine `Badge`, `dot` renders a colored dot with text, `badge` by default */
  variant?: 'badge' | 'dot';
  /** Badge and text size, `sm` by default */
  size?: MantineSize;
  /** Shows the status icon, or a loader for `pending` and `running`, `true` by default */
  withIcon?: boolean;
  /** Class name added to the root element */
  className?: string;
  /** Inline styles added to the root element */
  style?: React.CSSProperties;
}

const ICON_SIZE: Record<MantineSize, number> = { xs: 10, sm: 12, md: 14, lg: 16, xl: 18 };

/** Status of a server, agent, task or tool from one shared vocabulary */
export const StatusBadge = memo(function StatusBadge({
  status,
  label,
  variant = 'badge',
  size = 'sm',
  withIcon = true,
  className,
  style,
}: StatusBadgeProps) {
  const meta = getStatusMeta(status);
  const text = label ?? meta.label;
  const iconSize = ICON_SIZE[size];
  const StatusIcon = meta.icon;

  if (variant === 'dot') {
    return (
      <Group
        gap={6}
        wrap="nowrap"
        className={cx(classes.dot, className)}
        style={style}
        data-status={status}
      >
        {withIcon && meta.loading ? (
          <Loader size={iconSize} color={meta.color} aria-hidden />
        ) : (
          <ColorSwatch
            color={`var(--mantine-color-${meta.color}-filled)`}
            size={iconSize - 4}
            withShadow={false}
            className={classes.swatch}
          />
        )}
        <Text size={size} c="dimmed" truncate>
          {text}
        </Text>
      </Group>
    );
  }

  return (
    <Badge
      variant="light"
      color={meta.color}
      size={size}
      className={className}
      style={style}
      data-status={status}
      leftSection={
        withIcon ? (
          meta.loading ? (
            <Loader size={iconSize - 2} color={meta.color} aria-hidden />
          ) : (
            <StatusIcon size={iconSize} aria-hidden />
          )
        ) : undefined
      }
    >
      {text}
    </Badge>
  );
});

StatusBadge.displayName = 'StatusBadge';
API reference
Prop
Type
Required
status
AgentUiStatus
Yes
Status from the shared vocabulary
label
string
No
Overrides the default English label of the status
variant
'badge' | 'dot'
No
`badge` renders a Mantine `Badge`, `dot` renders a colored dot with text, `badge` by default
size
MantineSize
No
Badge and text size, `sm` by default
withIcon
boolean
No
Shows the status icon, or a loader for `pending` and `running`, `true` by default
className
string
No
Class name added to the root element
style
React.CSSProperties
No
Inline styles added to the root element