Visual guides / AI interfaces
Make every AI state understandable.
Compose prompts, response status, citations, tool activity, and decisions. Try the complete local simulation.
Use these primitives to present an application-owned AI workflow with clear send, stop, retry, and decision states.
Loading the interactive workbench…
Start building
Load your adapter stylesheet once. Astro needs its client runtime for enhanced interactions; React manages its own lifecycle; Elements needs client registration.
---
// pnpm add @santi020k/lumen-astro
// In your root layout:
import '@santi020k/lumen-astro/styles.css'
import UIPrimitives from '@santi020k/lumen-astro/runtime'
---
<slot />
<UIPrimitives />// pnpm add @santi020k/lumen-react
// In your application entry:
import '@santi020k/lumen-react/styles.css'
// Import components from the public package:
import { PromptComposer, StreamMessage, SourceCitation, ToolActivity, ApprovalCard } from '@santi020k/lumen-react'// pnpm add @santi020k/lumen-elements
// In your client entry, processed by a bundler:
import '@santi020k/lumen-elements/styles.css'
import { defineLumenElements } from '@santi020k/lumen-elements'
defineLumenElements(['PromptComposer', 'StreamMessage', 'SourceCitation', 'ToolActivity', 'ApprovalCard'])Starter example
The React example includes local state. Astro and Elements show the component structure; your client code owns data updates and event handlers.
'use client'
import { useState } from 'react'
import { PromptComposer, StreamMessage } from '@santi020k/lumen-react'
// A local example. Replace the handler with your application request.
export function PromptPreview() {
const [response, setResponse] = useState('')
return <>
<PromptComposer onPromptSubmit={({ text }) => {
setResponse('Received: ' + text)
}} />
<StreamMessage status={response ? 'complete' : 'idle'}
statusLabel={response ? 'Response ready' : 'Waiting for a prompt'}>
{response || 'Send a prompt to begin.'}
</StreamMessage>
</>
}---
import { PromptComposer, StreamMessage } from '@santi020k/lumen-astro'
---
<PromptComposer value="Explain the workspace" />
<StreamMessage status="idle" statusLabel="Waiting for a prompt">
Send a prompt to begin.
</StreamMessage>
<!-- Handle ui:prompt-submit in your client code; preventDefault() when handled.
Or set action on PromptComposer to your application's POST endpoint. --><lumen-prompt-composer value="Explain the workspace"></lumen-prompt-composer>
<lumen-stream-message status="idle" status-label="Waiting for a prompt">
Send a prompt to begin.
</lumen-stream-message>
<!-- Handle ui:prompt-submit in your client code; preventDefault() when handled.
Your application owns requests, response state, and cancellation. -->Before you ship
- Lumen never contacts a model. Your application owns requests, streaming, cancellation, persistence, and server authorization.
- PromptComposer validates input and exposes onPromptSubmit({ text }) and onStop in React. Astro and Elements emit ui:prompt-submit and ui:prompt-stop.
- Keep streamed tokens outside live regions. Supply a concise statusLabel to StreamMessage and compose retry controls when needed.
- ApprovalCard reports a decision; it does not execute a change or grant permission. Validate every operation on the server.
- Treat response Markdown as untrusted input. Use safe rendering and meaningful source labels.
Component reference
Find props, events, keyboard behavior, and Astro, React, and Elements examples for each primitive.