Getting Started
Components
- Agent Status
- Agent Template Card
- API Key Card
- Audio Player
- Bar Visualizer
- Channel Status Card
- Chat Composer
- Code Editor
- Condition Builder
- Confirm Dialog
- Conversation
- Conversation Bar
- Dataset Card
- Document Status Badge
- Extraction Strategy Select
- File Icon
- File Upload
- Indexing Progress
- Live Waveform
- Matrix
- Message
- Mic Selector
- Model Diff View
- Model Selector
- Model Type Filter
- Node Catalog
- Option Editor
- Orb
- Output Variables View
- Package Card
- Prompt Editor
- Provider Status Card
- Radio Card
- Resource Card
- Resource Sidebar
- Response
- Run Node List
- Scrub Bar
- Segment Card
- Shimmering Text
- Speech Input
- Token Trend Chart
- Tool Call Card
- Transcript Viewer
- Usage Stat Card
- Variable Binding Editor
- Variable Selector
- Voice Button
- Voice Picker
- Waveform
- Workflow Node Card
- Workspace Selector
Website Chat
WebConnectedEmbedded chat widget connected to the support agent.
Conversations
1,240
Messages
18,420
Last event 30s ago
Support Inbox
EmailErrorOAuth token needs to be refreshed before new mail can sync.
Conversations
318
Messages
5,902
Sync failed 12 min ago
import { MailIcon, MessageSquareTextIcon } from "lucide-react"
import { ChannelStatusCard } from "@/components/ui/channel-status-card"
export function ChannelStatusCardDemo() {
return (
<div className="grid w-full max-w-3xl gap-3 sm:grid-cols-2">
<ChannelStatusCard
name="Website Chat"
provider="Web"
status="connected"
icon={<MessageSquareTextIcon className="size-5" />}
description="Embedded chat widget connected to the support agent."
conversations={1240}
messages={18420}
lastEvent="Last event 30s ago"
/>
<ChannelStatusCard
name="Support Inbox"
provider="Email"
status="error"
icon={<MailIcon className="size-5" />}
description="OAuth token needs to be refreshed before new mail can sync."
conversations={318}
messages={5902}
lastEvent="Sync failed 12 min ago"
/>
</div>
)
}
Installation
pnpm dlx shadcn@latest add https://ui.zgi.ai/r/channel-status-card.jsonpnpm dlx shadcn@latest add https://ui.zgi.ai/r/channel-status-card.json
yarn dlx shadcn@latest add https://ui.zgi.ai/r/channel-status-card.jsonComponent
"use client"
import * as React from "react"
import {
AlertCircleIcon,
CheckCircle2Icon,
MessageCircleIcon,
RefreshCcwIcon,
} from "lucide-react"
import { cn } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
export type ChannelStatus = "connected" | "syncing" | "error" | "disabled"
export interface ChannelStatusCardProps
extends Omit<React.ComponentProps<typeof Card>, "title"> {
name: React.ReactNode
provider?: React.ReactNode
status?: ChannelStatus
description?: React.ReactNode
icon?: React.ReactNode
conversations?: number
messages?: number
lastEvent?: React.ReactNode
onSync?: () => void
onManage?: () => void
}
const channelStatusConfig = {
connected: {
label: "Connected",
icon: CheckCircle2Icon,
className: "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
},
syncing: {
label: "Syncing",
icon: RefreshCcwIcon,
className: "bg-blue-500/10 text-blue-700 dark:text-blue-300",
},
error: {
label: "Error",
icon: AlertCircleIcon,
className: "bg-destructive/10 text-destructive",
},
disabled: {
label: "Disabled",
icon: MessageCircleIcon,
className: "bg-muted text-muted-foreground",
},
} satisfies Record<
ChannelStatus,
{
label: string
icon: React.ComponentType<{ className?: string }>
className: string
}
>
export function ChannelStatusCard({
name,
provider,
status = "connected",
description,
icon,
conversations,
messages,
lastEvent,
onSync,
onManage,
className,
...props
}: ChannelStatusCardProps) {
const config = channelStatusConfig[status]
const StatusIcon = config.icon
return (
<Card className={cn("rounded-lg py-0", className)} {...props}>
<CardContent className="space-y-4 p-4">
<div className="flex items-start gap-3">
<div className="bg-muted text-muted-foreground flex size-10 shrink-0 items-center justify-center rounded-lg">
{icon ?? <MessageCircleIcon className="size-5" />}
</div>
<div className="min-w-0 flex-1">
<div className="flex min-w-0 flex-wrap items-center gap-2">
<h3 className="truncate text-sm font-medium">{name}</h3>
{provider ? (
<Badge variant="outline" className="h-6 rounded-md">
{provider}
</Badge>
) : null}
<Badge
variant="secondary"
className={cn("h-6 rounded-md border-0", config.className)}
>
<StatusIcon
className={cn(
"size-3.5",
status === "syncing" && "animate-spin"
)}
/>
{config.label}
</Badge>
</div>
{description ? (
<p className="text-muted-foreground mt-1 line-clamp-2 text-xs leading-5">
{description}
</p>
) : null}
</div>
</div>
<div className="grid grid-cols-2 gap-2 text-xs">
{typeof conversations === "number" ? (
<div className="rounded-md border p-2">
<div className="text-muted-foreground">Conversations</div>
<div className="mt-1 font-medium tabular-nums">
{conversations.toLocaleString()}
</div>
</div>
) : null}
{typeof messages === "number" ? (
<div className="rounded-md border p-2">
<div className="text-muted-foreground">Messages</div>
<div className="mt-1 font-medium tabular-nums">
{messages.toLocaleString()}
</div>
</div>
) : null}
</div>
<div className="flex flex-wrap items-center justify-between gap-3 border-t pt-3">
{lastEvent ? (
<span className="text-muted-foreground text-xs">{lastEvent}</span>
) : (
<span />
)}
<div className="flex gap-2">
{onSync ? (
<Button
type="button"
variant="outline"
size="sm"
className="h-8 gap-2 rounded-md"
onClick={onSync}
>
<RefreshCcwIcon className="size-3.5" />
Sync
</Button>
) : null}
{onManage ? (
<Button
type="button"
size="sm"
className="h-8 rounded-md"
onClick={onManage}
>
Manage
</Button>
) : null}
</div>
</div>
</CardContent>
</Card>
)
}
Usage
import { ChannelStatusCard } from "@/components/ui/channel-status-card"
export function Example() {
return (
<ChannelStatusCard
name="Website Chat"
provider="Web"
status="connected"
conversations={1240}
messages={18420}
/>
)
}Props
| Prop | Type | Default |
|---|---|---|
| name | ReactNode | required |
| provider | ReactNode | - |
| status | "connected" | "syncing" | "error" | "disabled" | "connected" |
| description | ReactNode | - |
| icon | ReactNode | - |
| conversations | number | - |
| messages | number | - |
| lastEvent | ReactNode | - |
| onSync | () => void | - |
| onManage | () => void | - |
Deploy and Scale Agents with ZGI
ZGI delivers the infrastructure and developer experience you need to ship reliable audio & agent applications at scale.
Talk to an expert