Pre-built React widgets for Rodger AI tools
npm install @rodgerai/widgetsBeautiful, production-ready React widgets for Rodger AI tools. Seamlessly integrate with @assistant-ui/react to provide rich, interactive UI experiences for tool results.
- 5 Pre-built Widgets - Cart builder, product lookup, quick actions, email signup, CTA buttons
- Built on assistant-ui - Leverages powerful assistant-ui primitives
- Type-Safe - Full TypeScript support with proper interfaces
- Tailwind Styled - Easy customization with Tailwind CSS
- State Management - Handles loading, success, error states automatically
- Responsive Design - Works on mobile, tablet, and desktop
``bash`
npm install @rodger/widgetsor
pnpm add @rodger/widgets
`json`
{
"@assistant-ui/react": "^0.11.0",
"react": "^18.0.0 || ^19.0.0"
}
These are automatically installed if not present.
`typescript
// app/api/chat/route.ts
import { createAgent } from '@rodger/core';
import { cartBuilder, productLookup } from '@rodger/tools';
const agent = createAgent({
name: 'Shopping Assistant',
llm: { provider: 'openai', model: 'gpt-4o' },
tools: { cartBuilder, productLookup }
});
`
`tsx
// components/Chat.tsx
'use client';
import { Thread } from '@rodger/ui';
import { CartBuilderUI, ProductLookupUI } from '@rodger/widgets';
export default function Chat() {
return (
cartBuilder: CartBuilderUI,
productLookup: ProductLookupUI
}}
/>
);
}
`
That's it! When your agent uses these tools, the widgets automatically render the results.
Interactive cart builder with approval workflow, loading states, and checkout links.
`tsx
import { CartBuilderUI } from '@rodger/widgets';
cartBuilder: CartBuilderUI
}}
/>
`
Features:
- Preview state with product details
- User approval workflow
- Loading state during cart creation
- Success state with checkout link
- Error handling with retry options
- Animated transitions
Tool Result Interface:
`typescript`
interface CartBuilderResult {
requiresApproval?: boolean;
preview?: {
products: Array<{
entityId: number;
name: string;
quantity: number;
price?: number;
}>;
protocolName: string;
notes: string | null;
};
message?: string;
}
States:
1. Preview - Shows cart contents, requires approval
2. Loading - Displays spinner during cart creation
3. Success - Shows checkout link and confirmation
4. Error - Shows error message with retry option
Pairs with: cartBuilder from @rodger/tools
Display product search results as interactive cards.
`tsx
import { ProductLookupUI } from '@rodger/widgets';
productLookup: ProductLookupUI
}}
/>
`
Features:
- Responsive card grid layout
- Product metadata display (name, price, size)
- External product page links
- Disclaimer for research products
- Hover effects and animations
Tool Result Format:
``
ID: 123 | Product Name (Nickname) | $99.99 | 30 servings | https://example.com/product
ID: 456 | Another Product | $79.99 | 60 capsules | https://example.com/product2
Component Exports:
`typescript`
import {
ProductLookupUI, // Main widget
ProductCard, // Individual card component
parseProductList // Helper to parse tool results
} from '@rodger/widgets';
Pairs with: productLookup from @rodger/tools
Display interactive button choices to guide conversations.
`tsx
import { QuickActionsWidget } from '@rodger/widgets';
quickActions: QuickActionsWidget
}}
/>
`
Features:
- Grid layout for multiple buttons
- Click to send pre-filled prompts
- Hover effects
- Responsive design (1-2 columns)
- Integrated with ThreadPrimitive.Suggestion
Tool Result Interface:
`typescript`
{
message: string; // Message above buttons
actions: Array<{
label: string; // Button text
prompt: string; // Prompt to send when clicked
}>;
}
Example Rendering:
``
What would you like to do?
[Browse Products] [Get Recommendations]
Pairs with: quickActions from @rodger/tools
Collect user email addresses with validation and feedback.
`tsx
import { EmailSignupWidget } from '@rodger/widgets';
emailSignup: EmailSignupWidget
}}
/>
`
Features:
- Success/error state handling
- Visual feedback with icons
- Animated transitions
- Clean, minimal design
- Email validation messages
Tool Result Interface:
`typescript`
{
success: boolean;
email: string | null;
message: string; // Feedback message
}
States:
1. Success - Shows checkmark and confirmation
2. Error - Shows error icon and message
Pairs with: emailSignup from @rodger/tools
Display prominent call-to-action buttons for important actions.
`tsx
import { CtaButtonWidget } from '@rodger/widgets';
ctaButton: CtaButtonWidget
}}
/>
`
Features:
- Primary and secondary variants
- Optional description text
- External link with icon
- Hover animations
- Calendar icon for booking actions
- Opens in new window
Tool Result Interface:
`typescript`
{
label: string; // Button text
url: string; // Link destination
description?: string; // Optional description
variant?: 'primary' | 'secondary'; // Button style
}
Variants:
- Primary - Navy background with light text
- Secondary - Border style with hover fill
Pairs with: ctaButton from @rodger/tools
`tsx
import { Thread } from '@rodger/ui';
import {
CartBuilderUI,
ProductLookupUI,
QuickActionsWidget,
EmailSignupWidget,
CtaButtonWidget
} from '@rodger/widgets';
cartBuilder: CartBuilderUI,
productLookup: ProductLookupUI,
quickActions: QuickActionsWidget,
emailSignup: EmailSignupWidget,
ctaButton: CtaButtonWidget
}}
/>
`
Only register widgets for tools your agent uses:
`tsx`
// Agent only uses cartBuilder and productLookup
cartBuilder: CartBuilderUI,
productLookup: ProductLookupUI
}}
/>
Export and use sub-components directly:
`tsx
import { ProductCard, parseProductList } from '@rodger/widgets';
function MyCustomProductDisplay({ toolResult }) {
const products = parseProductList(toolResult);
return (
$3
Load widgets dynamically:
`tsx
import { widgets } from '@rodger/widgets';// Lazy load widgets
const CartBuilderUI = await widgets.cartBuilder();
const ProductLookupUI = await widgets.productLookup();
widgets={{
cartBuilder: CartBuilderUI,
productLookup: ProductLookupUI
}}
/>
`Styling and Theming
$3
Add @rodger/widgets to your Tailwind config:
`js
// tailwind.config.js
module.exports = {
content: [
'./app/*/.{js,ts,jsx,tsx}',
'./node_modules/@rodger/widgets/dist/*/.{js,mjs}'
],
theme: {
extend: {
colors: {
'navy-dark': '#1a202c',
'warm-beige': '#f5f1e8',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
'muted-foreground': 'hsl(var(--muted-foreground))'
}
}
}
};
`$3
Define theme colors in your CSS:
`css
/ app/globals.css /
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--muted-foreground: 215.4 16.3% 46.9%;
}.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--muted-foreground: 215 20.2% 65.1%;
}
`$3
Override widget styles with Tailwind classes:
`tsx
// Custom cart builder styling
`Or use custom CSS:
`css
/ Custom widget styles /
.cart-preview {
@apply rounded-xl shadow-lg;
}.product-card {
@apply hover:scale-105 transition-transform;
}
`Creating Custom Widgets
Build your own widgets using the assistant-ui patterns:
$3
`tsx
// MyWidget.tsx
import { makeAssistantToolUI } from '@assistant-ui/react';export const MyWidget = makeAssistantToolUI({
toolName: 'myTool',
render: function MyWidgetContent({ result }) {
const data = result as { message: string };
return (
{data.message}
);
}
});
`$3
`tsx
import { makeAssistantToolUI } from '@assistant-ui/react';
import { useState } from 'react';export const InteractiveWidget = makeAssistantToolUI({
toolName: 'interactiveTool',
render: function Content({ result }) {
const [isApproved, setIsApproved] = useState(false);
if (isApproved) {
return
Approved!;
} return (
);
}
});
`$3
`tsx
import { makeAssistantToolUI } from '@assistant-ui/react';
import { useState } from 'react';export const ApiWidget = makeAssistantToolUI({
toolName: 'apiTool',
render: function Content({ result }) {
const [status, setStatus] = useState<'idle' | 'loading' | 'success'>('idle');
const handleAction = async () => {
setStatus('loading');
await fetch('/api/action', {
method: 'POST',
body: JSON.stringify(result)
});
setStatus('success');
};
return (
{status === 'loading' && Loading...}
{status === 'success' && Success!}
{status === 'idle' && (
)}
);
}
});
`$3
1. Type Safety - Define interfaces for tool results:
`typescript
interface MyToolResult {
data: string;
metadata?: Record;
}render: ({ result }) => {
const data = result as MyToolResult;
// Full type safety
}
`2. Error Handling - Handle missing or malformed data:
`typescript
render: ({ result }) => {
if (!result || typeof result !== 'object') {
return Invalid tool result;
}
// Render normally
}
`3. Loading States - Show feedback during async operations:
`typescript
const [isLoading, setIsLoading] = useState(false);const handleAction = async () => {
setIsLoading(true);
try {
await performAction();
} finally {
setIsLoading(false);
}
};
`4. Accessibility - Use semantic HTML and ARIA attributes:
`tsx
onClick={handleAction}
aria-label="Approve cart"
disabled={isLoading}
>
Approve
`5. Responsive Design - Use Tailwind responsive classes:
`tsx
{/ Responsive grid /}
`TypeScript Support
Full TypeScript support with exported types:
`typescript
import type {
CartPreview,
Product
} from '@rodger/widgets';
`Complete Example
`tsx
// app/page.tsx
'use client';import { RodgerProvider, Thread, useRodgerChat } from '@rodger/ui';
import {
CartBuilderUI,
ProductLookupUI,
QuickActionsWidget,
EmailSignupWidget,
CtaButtonWidget
} from '@rodger/widgets';
export default function ShoppingChat() {
const { runtime, isLoadingHistory } = useRodgerChat({
endpoint: '/api/chat',
sessionId: 'shopping-session'
});
if (isLoadingHistory) {
return
Loading...;
} return (
welcomeMessage={
Shopping Assistant
Browse products and build your cart
}
widgets={{
cartBuilder: CartBuilderUI,
productLookup: ProductLookupUI,
quickActions: QuickActionsWidget,
emailSignup: EmailSignupWidget,
ctaButton: CtaButtonWidget
}}
/>
);
}
``- @rodger/core - Agent framework (required for backend)
- @rodger/tools - Pre-built tools (pairs with widgets)
- @rodger/ui - React components for chat UIs
- Full Documentation
- Creating Custom Widgets
- Widget Integration Guide
MIT