Widgets
Generative UI widgets for rendering AI responses.
Generative UI Widgets
Widgets render rich visual outputs from AI tool results in the chat interface.
Available Widgets
ChartWidget
Displays data as charts using the Charts component.
import { ChartWidget } from '@/components/ai';
<ChartWidget
data={{
widgetId: 'chart-1',
type: 'bar',
title: 'Monthly Sales',
data: [
{ month: 'Jan', sales: 400 },
{ month: 'Feb', sales: 300 },
{ month: 'Mar', sales: 600 },
],
xAxis: 'month',
yAxis: 'sales',
}}
/>
Supported chart types: bar, line, area, pie, radar
DataGridWidget
Displays tabular data with auto-generated columns.
import { DataGridWidget } from '@/components/ai';
<DataGridWidget
data={{
widgetId: 'grid-1',
title: 'Users',
data: [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
],
columns: [
{ key: 'id', label: 'ID', type: 'number' },
{ key: 'name', label: 'Name' },
{ key: 'email', label: 'Email' },
],
pageSize: 5,
}}
/>
MetricWidget
Displays a single metric with optional change indicator.
import { MetricWidget } from '@/components/ai';
<MetricWidget
data={{
widgetId: 'metric-1',
value: 12500,
label: 'Total Revenue',
format: 'currency',
change: 12.5,
changeLabel: 'vs last month',
trend: 'up',
}}
/>
Format options: number, currency, percent
TextWidget
Displays formatted text with optional markdown support.
import { TextWidget } from '@/components/ai';
<TextWidget
data={{
widgetId: 'text-1',
content: '**Bold** and *italic* text with `code`',
format: 'markdown',
}}
/>
NavigationWidget
Displays navigation confirmation.
import { NavigationWidget } from '@/components/ai';
<NavigationWidget
data={{
widgetId: 'nav-1',
previousPath: '/docs',
currentPath: '/dashboard',
navigatedAt: new Date().toISOString(),
}}
/>
HighlightWidget
Shows component highlight confirmation.
import { HighlightWidget } from '@/components/ai';
<HighlightWidget
data={{
widgetId: 'highlight-1',
componentId: 'main-nav',
color: '#1f8bff',
message: 'This is the main navigation',
}}
/>
Widget Router
The WidgetRouter automatically renders the appropriate widget based on tool name:
import { WidgetRouter } from '@/components/ai';
function renderToolResult(toolName: string, result: object) {
return <WidgetRouter toolName={toolName} result={result} />;
}
Tool to widget mapping:
| Tool Name | Widget |
|---|---|
createChart | ChartWidget |
createDataGrid | DataGridWidget |
createWidget (type: metric) | MetricWidget |
createWidget (type: text) | TextWidget |
navigateTo | NavigationWidget |
highlightComponent | HighlightWidget |
Creating Custom Widgets
1. Define the Widget Type
// In types.ts
export interface MyWidgetData extends BaseWidgetData {
customField: string;
options?: MyOptions;
}
2. Create the Widget Component
// In widgets/Widgets.tsx
interface MyWidgetProps {
data: MyWidgetData;
}
export const MyWidget = memo(function MyWidget({ data }: MyWidgetProps) {
const { customField, options } = data;
return (
<div className={styles.myWidget}>
{/* Widget content */}
</div>
);
});
3. Add to Widget Router
// In WidgetRouter
case 'myTool':
return <MyWidget data={result as MyWidgetData} />;
Widget Styling
Widgets use SCSS modules for styling:
// Widgets.module.scss
.myWidget {
padding: $space-4;
border-radius: $radius-md;
background: var(--color-bg-secondary);
.title {
font-weight: 600;
margin-bottom: $space-2;
}
}
Best Practices
- Use memo - Widgets should be memoized to prevent unnecessary re-renders
- Handle missing data - Always validate data before rendering
- Keep widgets focused - Each widget should do one thing well
- Use design tokens - Maintain visual consistency with the design system
- Accessible - Include proper ARIA attributes and keyboard support