Receber por email
← Voltar para o catálogo

uix-components

Uma biblioteca de componentes UIX e skill de adaptador de protocolo para construir interfaces de chat de IA, útil para UIs de agentes de IA ou integração com protocolos de IA como Vercel AI SDK. Ela oferece uma API de componente AgentChat, padrões de uso de adaptador e um sistema de tipos UIX IR.

10estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add Deepractice/UIX

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/uix-components/svg)](https://www.skillteca.com.br/skills/uix-components)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

UIX Components — AI Chat UI in 3 Lines

You are an expert in the UIX protocol and component library. UIX is an AI-to-UI Intermediate Representation (IR) protocol layer that bridges multiple AI protocols into a unified component system.

Core Concept

AI Agent Events (Vercel AI SDK / AG-UI / Anthropic / ...)
    ↓ adapter
UIX IR (LucidConversation[])
    ↓ render
React Components (AgentChat)

Quick Start — The 3-Line Pattern

The fastest way to build an AI chat UI:

With Vercel AI SDK

import { AgentChat } from '@uix-ai/agent'
import { useVercelChat } from '@uix-ai/adapter-vercel/react'

export default function Chat() {
  const { conversations, status, send, stop } = useVercelChat({ api: '/api/chat' })
  return <AgentChat conversations={conversations} status={status} onSend={send} onStop={stop} />
}

With AG-UI Protocol

import { AgentChat } from '@uix-ai/agent'
import { useAGUI } from '@uix-ai/adapter-agui/react'

export default function Chat() {
  const { conversations, status, send, stop } = useAGUI({ url: '/api/agent' })
  return <AgentChat conversations={conversations} status={status} onSend={send} onStop={stop} />
}

Without Any Adapter (Manual IR)

import { AgentChat } from '@uix-ai/agent'
import type { LucidConversation } from '@uix-ai/core'

const conversations: LucidConversation[] = [
  { id: '1', role: 'user', status: 'completed', blocks: [{ id: 'b1', type: 'text', status: 'completed', content: { text: 'Hello' } }] },
  { id: '2', role: 'assistant', status: 'completed', blocks: [{ id: 'b2', type: 'text', status: 'completed', content: { text: 'Hi! How can I help?' } }] },
]

export default function Chat() {
  return <AgentChat conversations={conversations} onSend={(msg) => console.log(msg)} />
}

UIX IR Type System

LucidConversation

interface LucidConversation {
  id: string
  role: 'user' | 'assistant' | 'system'
  status: 'streaming' | 'completed' | 'error'
  blocks: LucidBlock[]
  agentName?: string
  agentAvatar?: string
  timestamp?: number
}

LucidBlock

interface LucidBlock {
  id: string
  type: 'text' | 'tool' | 'thinking' | 'image' | 'file' | 'error' | 'source'
  status: 'streaming' | 'completed' | 'error'
  content: TextBlockContent | ToolBlockContent | ThinkingBlockContent | ...
}

Block Types

| Type | Content | Description | |------|---------|-------------| | text | { text: string } | Markdown text, supports streaming | | tool | { name, input?, output?, toolStatus } | Tool call with status lifecycle | | thinking | { text: string } | AI reasoning/chain-of-thought | | image | { url, alt?, width?, height? } | Image content | | file | { url, filename, mimeType?, size? } | File attachment | | error | { message, code? } | Error display | | source | { type, url?, title?, excerpt? } | Citation/RAG source |

Type Guards

import { isTextBlock, isToolBlock, isThinkingBlock, isStreaming, isCompleted } from '@uix-ai/core'

if (isTextBlock(block)) {
  // block.content is TextBlockContent
}
if (isStreaming(conversation)) {
  // show streaming indicator
}

AgentChat Props

interface AgentChatProps {
  // Required
  conversations: LucidConversation[]
  onSend: (message: string) => void

  // Optional - status & control
  status?: 'idle' | 'streaming' | 'error'
  onStop?: () => void
  onRetry?: (conversationId: string) => void

  // Optional - agent info
  agent?: { name: string; avatar?: string; description?: string }

  // Optional - tool approval
  onToolApprove?: (blockId: string) => void
  onToolDeny?: (blockId: string) => void

  // Optional - customization
  placeholder?: string
  emptyState?: React.ReactNode
  renderBlock?: (block: LucidBlock) => React.ReactNode | null
  showHeader?: boolean
  autoScroll?: boolean
}

Composable Components

When you need more control than AgentChat, use individual components:

Layout

| Component | Description | |-----------|-------------| | ChatWindow | Container with header, messages, input | | ChatWindowHeader | Agent name, avatar, status | | ChatWindowMessages | Scrollable message area | | ChatWindowInput | Text input with send button | | ChatWindowEmpty | Empty state placeholder | | ChatList | Sidebar conversation list |

Messages

| Component | Description | |-----------|-------------| | ChatMessage | Full message with avatar and blocks | | MessageList | Scrollable message container | | StreamText | Streaming markdown renderer | | ThinkingIndicator | Pulsing thinking state | | ToolResult | Tool call display with status | | SourceBlock | Citation/RAG source card |

Avatars

| Component | Description | |-----------|-------------| | Avatar | Composable avatar (Avatar > AvatarImage + AvatarFallback) | | AvatarGroup | Stacked avatar group with overflow |

Input

| Component | Description | |-----------|-------------| | ChatInput | Text input with @ mention support | | MentionPopover | Mention suggestion popup |

Adapter Reference

Vercel AI SDK Adapter

// React hook (recommended)
import { useVercelChat } from '@uix-ai/adapter-vercel/react'
const { conversations, status, send, stop, setMessages } = useVercelChat({
  api: '/api/chat',
  // all useChat options supported
})

// Manual conversion
import { fromVercelMessages, toVercelMessages } from '@uix-ai/adapter-vercel'
const lucidConversations = fromVercelMessages(vercelMessages)
const vercelMessages = toVercelMessages(lucidConversations)

AG-UI Adapter

// React hook (recommended)
import { useAGUI } from '@uix-ai/adapter-agui/react'
const { conversations, status, send, stop, reset } = useAGUI({
  url: '/api/agent',
  threadId: 'optional-thread-id',
  headers: { Authorization: 'Bearer ...' },
})

// Manual event processing
import { AGUIEventProcessor } from '@uix-ai/adapter-agui'
const processor = new AGUIEventProcessor()
processor.process(event) // feed AG-UI events
const conversations = processor.getConversations()

A2UI Adapter (Experimental)

import { fromA2UIPayload, toA2UIPayload } from '@uix-ai/adapter-a2ui'

// Google A2UI → UIX IR
const conversation = fromA2UIPayload(a2uiPayload)

// UIX IR → Google A2UI
const payload = toA2UIPayload(conversation)

Common Patterns

Next.js App Router + Vercel AI SDK

// app/api/chat/route.ts
import { streamText } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'

export async function POST(req: Request) {
  const { messages } = await req.json()
  const result = streamText({
    model: anthropic('claude-sonnet-4-20250514'),
    messages,
  })
  return result.toDataStreamResponse()
}

// app/page.tsx
'use client'
import { AgentChat } from '@uix-ai/agent'
import { useVercelChat } from '@uix-ai/adapter-vercel/react'

export default function Page() {
  const { conversations, status, send, stop } = useVercelChat({ api: '/api/chat' })
  return (
    <div className="h-screen">
      <AgentChat
        conversations={conversations}
        status={status}
        onSend={send}
        onStop={stop}
        agent={{ name: 'Claude', description: 'AI Assistant' }}
      />
    </div>
  )
}

Custom Block Rendering

<AgentChat
  conversations={conversations}
  onSend={send}
  renderBlock={(block) => {
    if (block.type === 'tool' && block.content.name === 'weather') {
      return <WeatherCard data={block.content.output} />
    }
    return null // fall back to default rendering
  }}
/>

Multiple Conversations (Sidebar + Chat)

import { ChatList, ChatWindow } from '@uix-ai/agent'

function App() {
  const [activeId, setActiveId] = useState<string>()
  return (
    <div className="flex h-screen">
      <ChatList conversations={allConversations} activeId={activeId} onSelect={setActiveId} />
      <ChatWindow conversation={activeConversation} onSend={send} />
Compartilhar X LinkedIn