Summarize the Europe orders.
Components / AI assistant
AI assistant
Explore every variant and expand each example’s formatted usage code.
AI assistant
Prompt inputs, suggestions, action status and result summaries.
Presentation example · Column metadata only
Usage · TSX
<div ref={assistantHost} style={{ width: '100%', minWidth: 0 }}>
<AiAssistant footer="Presentation example · Column metadata only">
<AiSuggestions
items={[
'Show orders above €1,000',
'Sort highest amount first',
'Only Europe',
'Exclude cancelled orders',
]}
onSelect={submit}
disabled={busy}
/>
<AiPromptInput
value={value}
onValueChange={setValue}
onSubmit={submit}
busy={busy}
onStop={() => setPhase('cancelled')}
hint={steps.length ? '' : undefined}
actions={
<AiRequestTrail
items={steps}
onRemove={(id) => {
setSteps((current) =>
current.filter((step) => step.id !== id),
);
setMessage('Request removed.');
}}
onClear={() => {
setSteps([]);
setMessage('Starting view restored.');
}}
onEmpty={() =>
assistantHost.current?.querySelector('textarea')?.focus()
}
/>
}
/>
<AiActionStatus
phase={phase}
message={phase === 'completed' ? '' : message}
/>
{phase === 'completed' && (
<AiResult
summary={message}
matchedRows={24}
actions={
<Button
size="compact"
onClick={() => {
setMessage('Previous view restored.');
setSteps((current) => current.slice(0, -1));
}}
>
Restore previous view
</Button>
}
/>
)}
</AiAssistant>
</div>Understanding your request…
Usage · TSX
<AiPromptInput
label="Cancellable request"
value={request}
onValueChange={setRequest}
onSubmit={() => setRunning(true)}
busy={running}
onStop={() => setRunning(false)}
textareaProps={{
className: 'catalog-ai-sized-prompt',
rows: 3,
style: { minHeight: '5rem', maxHeight: '10rem' },
}}
/>
<AiActionStatus
phase={running ? 'understanding' : 'cancelled'}
message={running ? 'Understanding your request…' : 'Request stopped.'}
/>
<AiPromptInput
label="Busy request"
value="Sort highest amount first"
onValueChange={() => {}}
onSubmit={() => {}}
busy
hint="Loading matching rows…"
/>
<AiPromptInput
label="Unavailable request"
value=""
onValueChange={() => {}}
onSubmit={() => {}}
disabled
hint="AI is unavailable for this view."
/>Understanding your request…
Loading matching rows…
The server could not load this view. Your previous view is unchanged.
Which date column should be used?
Filtered to Europe. Sorted by amount descending.
0 matching rows
Usage · TSX
<AiAssistant>
<AiActionStatus
phase="understanding"
message="Understanding your request…"
/>
<AiActionStatus phase="applying" message="Loading matching rows…" />
<AiActionStatus
phase="error"
message="The server could not load this view. Your previous view is unchanged."
/>
<AiActionStatus
phase="clarification"
message="Which date column should be used?"
/>
<AiSuggestions
items={['Order date', 'Due date']}
onSelect={setValue}
/>
<AiResult
summary="Filtered to Europe. Sorted by amount descending."
matchedRows={0}
/>
</AiAssistant>Independent presentation components · Scripted streaming · No model calls
Reasoning summary · 1sCompleted
Host-provided work summary: read only approved fields and keep the answer scoped to the visible view.
Read visible ordersCompleted
Completed:
Read approved column metadata
Completed:
Summarize the visible Europe orders
The visible view contains 20 Europe orders. This is a scripted UI example; no data was queried and no model was called.
Usage · TSX
<div style={{ width: '100%', minWidth: 0 }}>
<p>
Independent presentation components · Scripted streaming · No model
calls
</p>
<Button
size="compact"
onClick={() =>
setMessages((current) => [
...current,
...Array.from(
{ length: 8 },
(_, index): DemoMessage => ({
id: ++next.current,
from: index % 2 ? 'assistant' : 'user',
text:
index % 2
? response
: 'Show another example of the visible view.',
}),
),
])
}
>
Add sample turns
</Button>
<div
style={{
border: '1px solid var(--rv-ui-border)',
borderRadius: '12px',
overflow: 'hidden',
marginTop: '12px',
}}
>
<AiChat style={{ height: 'auto', maxHeight: '480px' }}>
<AiChatContent busy={busy}>
{messages.map((message) => (
<AiMessage
key={message.id}
from={message.from}
isStreaming={message.streaming}
>
{message.from === 'assistant' && (
<>
<AiReasoning
isStreaming={message.streaming}
duration={message.streaming ? undefined : 1}
>
Host-provided work summary: read only approved fields
and keep the answer scoped to the visible view.
</AiReasoning>
<AiTask
title={
message.cancelled
? 'Stopped reading visible orders'
: message.streaming
? 'Reading visible orders'
: 'Read visible orders'
}
status={
message.cancelled
? 'cancelled'
: message.streaming
? 'running'
: 'completed'
}
>
<AiTaskItem>Read approved column metadata</AiTaskItem>
<AiTaskItem
status={
message.cancelled
? 'cancelled'
: message.streaming
? 'running'
: 'completed'
}
>
Summarize the visible Europe orders
</AiTaskItem>
</AiTask>
</>
)}
<AiMessageContent>
{message.text || 'Preparing a reply…'}
</AiMessageContent>
{message.from === 'assistant' && !message.streaming && (
<AiMessageActions>
<Button
variant="ghost"
size="compact"
onClick={() => setDraft('Show orders above 1000')}
>
Follow up
</Button>
</AiMessageActions>
)}
</AiMessage>
))}
</AiChatContent>
<AiChatComposer
value={draft}
onValueChange={setDraft}
onSubmit={submit}
busy={busy}
onStop={stop}
footer={
<AiSuggestions
items={[
'Only Europe',
'Summarize visible orders',
'Sort by amount',
]}
onSelect={submit}
disabled={busy}
/>
}
/>
</AiChat>
</div>
</div>