Block Rendering
Blocks are structured UI components that an Elaras agent returns alongside a text message — carousels, booking pickers, forms, rating widgets, and more. Elaras ships ready-made renderers so you don't write any block UI code yourself.
Setup
Add two tags to your page — no build step needed:
<link rel="stylesheet" href="https://ask-api.elaras.ai/sdk/blocks.css"> <script src="https://ask-api.elaras.ai/sdk/blocks.js"></script>
The script exposes window.ElarasBlocks with renderBlock and renderBlocks.
Rendering blocks
Blocks arrive on the done event alongside the text response:
const { renderBlocks } = window.ElarasBlocks for await (const event of client.stream(sessionId, message)) { if (event.type === 'done' && event.blocks?.length) { renderBlocks(messagesEl, event.blocks, (text) => client.stream(sessionId, text)) messagesEl.scrollTop = messagesEl.scrollHeight } }
renderBlocks(container, blocks, onSend)
| Argument | Type | Description |
|---|---|---|
container | HTMLElement | Element to append blocks into |
blocks | Block[] | Block array from the chat event |
onSend | (text: string) => void | Called when the user interacts with a block (button click, form submit, slot selection, etc.) |
renderBlock(container, block, onSend)
Same signature but renders a single block. Unknown block.type values are silently ignored.
Image loading and scroll
Card images load asynchronously. When one finishes loading, a elaras:imageload CustomEvent bubbles up through the DOM. Listen on your messages container and re-scroll:
messagesEl.addEventListener('elaras:imageload', () => { messagesEl.scrollTop = messagesEl.scrollHeight })
Theming
All styles use CSS custom properties. Override them on your container element to match your brand:
.my-chat { --ec-primary: #ff6600; --ec-bg: #ffffff; --ec-surface: #f5f5f5; --ec-text: #111111; --ec-text-muted: #777777; --ec-border: #e0e0e0; --ec-input-bg: #fafafa; --ec-input-border: #cccccc; }
Block types
elaras.card
A single card with optional image, metadata, and CTA.
{ "type": "elaras.card", "spec": { "title": "2-bed flat, Shoreditch", "subtitle": "£1,200 pcm", "description": "Modern apartment with private balcony.", "image_url": "https://example.com/photo.jpg", "badge": "Available now", "metadata": [ { "label": "beds", "value": "2" }, { "label": "baths", "value": "1" } ], "cta": { "label": "View property", "url": "https://example.com/listing/123" } } }
cta.sends sends a preset message into the chat instead of opening a URL.
elaras.carousel
A horizontally scrollable row of cards.
{ "type": "elaras.carousel", "spec": { "cards": [ ...card specs... ] } }
elaras.button_group
A set of action buttons.
{ "type": "elaras.button_group", "spec": { "label": "What would you like to do?", "layout": "row", "buttons": [ { "label": "Book a viewing", "sends": "I'd like to book a viewing", "style": "primary" }, { "label": "Ask a question", "sends": "I have a question", "style": "outline" } ] } }
layout is "row" (default) or "column".
elaras.form
An inline form. On submit, field values are interpolated into sends_template and sent as a chat message.
{ "type": "elaras.form", "spec": { "title": "Request a callback", "submit_label": "Send request", "sends_template": "Callback request — Name: {name}, Phone: {phone}", "fields": [ { "name": "name", "label": "Full name", "type": "text", "required": true }, { "name": "phone", "label": "Phone number", "type": "tel", "required": true }, { "name": "time", "label": "Best time", "type": "select", "options": ["Morning", "Afternoon", "Evening"] } ] } }
Field type can be "text", "email", "tel", "select", or "textarea".
elaras.banner
An info, success, or warning callout.
{ "type": "elaras.banner", "spec": { "title": "Offer deadline: 5pm today", "body": "The vendor is reviewing all offers this evening.", "variant": "warning", "cta": { "label": "Make an offer", "sends": "I'd like to make an offer" } } }
variant is "info" (default), "success", or "warning".
elaras.rating
A star rating widget. Replaces itself with a confirmation on selection.
{ "type": "elaras.rating", "spec": { "prompt": "How helpful was this?", "scale": 5, "labels": { "low": "Not helpful", "high": "Very helpful" }, "sends_template": "{value} out of {scale} stars" } }
elaras.stat
A single highlighted metric.
{ "type": "elaras.stat", "spec": { "value": "£1,200,000", "label": "Guide Price", "sublabel": "Freehold", "trend": "up", "trend_value": "+8% YoY" } }
trend is "up", "down", or "neutral".
elaras.slots
A time-slot booking picker. Replaces itself with a confirmation on selection.
{ "type": "elaras.slots", "spec": { "title": "Choose a viewing time", "date_label": "Thursday 19 September", "sends_template": "Book viewing: {time} (ref: {id})", "slots": [ { "id": "v1", "time": "10:00 AM", "label": "30 min", "available": true }, { "id": "v2", "time": "11:00 AM", "label": "30 min", "available": false }, { "id": "v3", "time": "2:00 PM", "label": "30 min", "available": true } ] } }
elaras.choices
A single or multi-select question. Locks itself after submission.
{ "type": "elaras.choices", "spec": { "question": "What type of property are you looking for?", "type": "multi", "options": ["Flat", "House", "New build", "Period property"], "allow_other": true, "other_placeholder": "Something else…" } }
type is "single" (default) or "multi".
Emitting blocks from a skill
Return a _blocks key from any skill tool result:
{ "result": "Here are the closest matches to your search.", "_blocks": [ { "type": "elaras.carousel", "spec": { "cards": [...] } } ] }
The widget and SDK both handle _blocks automatically.
