Skip to content
Cojeev UI

Agent chat

Conversation

A composable agent conversation with a bounded thread, draft composer, attachments, progress, explicit permissions and choice prompts.

React · copy into your project · light and dark themes

Try it

Loading preview…

Take it with you

Copy the example, API and usage notes for your editor or AI assistant.

Open the full agent workspace example →

Add to your project

Terminal
npx shadcn@latest add https://luv-jeri.github.io/cojeev-ui/r/agent-chat.json

The command includes the component’s shared dependencies. Your project keeps editable source files.

Include the complete example

This example also composes button, presence, agent-state. Install its parts together:

Terminal
npx shadcn@latest add https://luv-jeri.github.io/cojeev-ui/r/button.json https://luv-jeri.github.io/cojeev-ui/r/presence.json https://luv-jeri.github.io/cojeev-ui/r/agent-state.json https://luv-jeri.github.io/cojeev-ui/r/agent-chat.json

Using agent chat

  • Compose AgentChatHeader, AgentChatThread and AgentChatComposer inside AgentChat.

  • Keep messages, draft, selected files and request status in your application. Clear a draft only after onSend accepts it.

  • Use AgentChatPermission for deliberate allow/deny decisions. Render its receipt after a decision.

  • Use AgentChatOptions to collect one valid choice; Continue remains disabled until a valid enabled option is selected.

  • The documentation runs a local simulation. Connect callbacks to your own application to perform real work.

API

Compose the exported parts below. The prop types are read from the React source during the registry build.

Native element or underlying primitive props are inherited where declared, including accessible labels, event handlers and refs.

AgentChatLayoutProps

Accepts the native or primitive props declared by its exported TypeScript type.

AgentChatMainProps

Accepts the native or primitive props declared by its exported TypeScript type.

AgentChatAsideProps

Accepts the native or primitive props declared by its exported TypeScript type.

AgentChatProps

Accepts the native or primitive props declared by its exported TypeScript type.

AgentChatHeaderProps

PropTypeRequired
titleReact.ReactNodeNo
descriptionReact.ReactNodeNo
statusAgentStatusNo
statusLabelstringNo
actionsReact.ReactNodeNo

AgentChatThreadProps

PropTypeRequired
jumpLabelstringNo

AgentChatMessageProps

PropTypeRequired
authorstringNo
avatarReact.ReactNodeNo
from"agent" | "user"No
metaReact.ReactNodeNo
actionsReact.ReactNodeNo

AgentChatComposerProps

PropTypeRequired
valuestringYes
onValueChange(value: string) => voidYes
onSend() => voidYes
statusAgentStatusNo
onStop() => voidNo
attachmentsreadonly AgentChatAttachment[]No
onAttach(files: File[]) => voidNo
onRemoveAttachment(id: string) => voidNo
acceptstringNo
disabledbooleanNo
placeholderstringNo
labelstringNo
hintReact.ReactNodeNo
errorReact.ReactNodeNo
onRetry() => voidNo
maxLengthnumberNo

AgentChatPermissionProps

PropTypeRequired
titleReact.ReactNodeYes
descriptionReact.ReactNodeYes
scopeReact.ReactNodeNo
decision"pending" | "allowed" | "denied"No
onDecision(decision: "allowed" | "denied") => voidYes
disabledbooleanNo
allowLabelstringNo
denyLabelstringNo

AgentChatOptionsProps

PropTypeRequired
titlestringYes
optionsreadonly AgentChatOption[]Yes
valuestringNo
onValueChange(value: string) => voidYes
onConfirm(value: string) => voidYes
disabledbooleanNo
confirmLabelstringNo

AgentChatProgressProps

PropTypeRequired
stepsreadonly AgentChatStep[]Yes

Accessibility

  • The thread is a keyboard-reachable live log and follows only while the reader stays near its end.

  • Enter inserts a new line. Command/Ctrl+Enter sends. Stop preserves the conversation.

  • Label attachments and permission scope clearly. Do not treat a preset option as submitted consent.

  • Return focus to the next useful control after a request resolves or is cancelled.

States and appearance

idlethinkingpermissionoptionsworkingcompletedeniedstoppederrorretryattacheddetached

For conditional content, keep a MotionPresence boundary around keyed MotionSurface children. The shared entrance and exit states work with native primitives and respect your motion preference.

Try pointer and keyboard interaction, and switch the appearance control in the navigation to compare light and dark mode. Motion respects reduced motion preferences.