Areas
AI interfaces
Chats, answers with sources, agents and settings for products with AI. Built to show plainly what the AI did, where it comes from and where a person decides.
On this page
The AI categories#
The AI interfaces sit in the categories below, one of them for marketing sections. Each one shows invented answers from props, and you connect the model yourself.
| Category | Components | What it does |
|---|---|---|
| AI and chat | ai-chat, prompt-input, agent-run | The chat itself, the prompt field and agents at work. |
| AI answers | citations, feedback-on-answer, compare-outputs, ai-search | Answers with sources, checks, comparisons and feedback. |
| AI writing and creation | writing-assistant, generation-gallery, prompt-library | Writing help, generated images and prompt libraries. |
| AI setup | model-picker, ai-settings, ai-onboarding | Models, memory, data controls and the first steps. |
| AI assistants | chat-widget, voice-assistant | Support chat for websites and voice assistants for calls. |
| AI features | ai-features | Marketing sections that show what AI does in a product. |
Every category has its page with live previews, for example AI answers or AI assistants.
Honest by design#
Trust in an AI product grows when people see what the AI did. The components are built for it.
- Where an AI answers, it says so. The chat widget and AI search carry a fixed note that answers come from an AI and can be wrong. Change it through
labels, keep it on the page. - Uncertainty is shown, never hidden.
AiSearchtakesconfidenceandcaveats, and the claim check inCitationsmarks statements without a source. - A person is within reach. The chat widget hands over to the team with a queue, or the answer arrives by email.
- What the AI knows about someone is visible and can be deleted.
AiSettingsshows memory, instructions and data controls. - Feedback is an invitation.
FeedbackOnAnswerasks for the reason and takes a correction.
Sources#
An answer with a source can be checked. answer holds paragraphs with references such as [1] or [1, 2], sources carries the sources with the same id. In an excerpt, ==double equals signs== mark the words the answer relies on.
import { Citations } from '@/components/ui/citations';
<Citations
variant="source-cards"
question="How much power does a heat pump use?"
answer={[
'A typical single family home needs **3,500 to 5,000 kWh** a year [1]. Older houses sit at the upper end [1, 2].',
]}
sources={[
{ id: 1, title: 'Heat pumps in existing homes', site: 'energy-agency.example', href: 'https://energy-agency.example/heat-pumps', date: 'Mar 2026', kind: 'paper' },
{ id: 2, title: 'Your offer, page 3', site: 'Offer folder', kind: 'doc', excerpt: 'Planned use ==4,200 kWh a year==.' },
]}
/>The claim-check variant takes claims with the status supported, partial or missing and shows how well each statement is backed.
Approvals#
When an agent acts in the real world, a person decides. AgentRun shows this in several forms. approval-queue collects waiting actions with reason, risk and the exact changes, plan-review lets people check the plan and set permissions before the start. In the chat, a step that needs approval holds the run until someone confirms.
import { AgentRun } from '@/components/ui/agent-run';
<AgentRun
variant="approval-queue"
approvals={[
{
id: 'a1',
agent: 'Bookkeeping agent',
run: 'September payment reminders',
action: 'Send 12 payment reminders',
icon: 'mail',
risk: 'medium',
reason: 'The invoices are more than 14 days overdue.',
changes: [{ field: 'Status', before: 'Open', after: 'Reminded' }],
requested: '4 min ago',
},
]}
/>Connect your model#
Where answers come from, the component takes a function. respond in the chat widget and onAction in the writing assistant return text or a promise, onSubmit hands feedback and corrections to you. Without a function they show their sample answers.
import { ChatWidget } from '@/components/ui/chat-widget';
import { FeedbackOnAnswer } from '@/components/ui/feedback-on-answer';
<ChatWidget
variant="handoff"
name="Lumen Help"
greeting="Hi, ask me anything about your order."
agent={{ name: 'Mara Lindqvist', role: 'Support', initials: 'ML' }}
respond={(text) => ask(text)}
/>
<FeedbackOnAnswer
variant="thumbs"
answer={{ question: 'Can I return a sale item?', text: 'Yes, within 30 days, unworn and with the receipt.' }}
onSubmit={(value) => save(value)}
/>// Runs in the browser and calls your own endpoint
async function ask(text: string): Promise<string> {
const res = await fetch('/api/answer', { method: 'POST', body: JSON.stringify({ text }) });
return res.ok ? (await res.json()).answer : 'The connection dropped for a moment. A person from the team reads along.';
}