Components

This page catalogs every component that @ada-cx/lovelace exports, grouped by role. Each entry names the component’s purpose and its most important props, and pairs them with a copyable example. Prop types ship with the package as TypeScript declarations, so your editor completes and checks every prop.

Every component in this catalog renders live below, including each icon glyph. The gallery follows the theme you configure in the theme playground: pick a preset or a scheme on either page, and both pages stay in sync. Overlay components, such as DialogOverlay and SheetOverlay, open from a button inside a contained preview frame in their tile.

Shared conventions

All components follow the same contract:

  • Every component accepts className and style, and takes ref as a regular prop (React 19).
  • Interactive components extend the matching React Aria Components props. Use onPress instead of onClick, and isDisabled instead of disabled.
  • Interactive states render as data-* attributes: data-hovered, data-pressed, data-focus-visible, data-disabled, data-selected. Extend styling by targeting those attributes, not pseudo-classes.
  • Compound components attach their parts with dot notation, for example Input.Field and Dialog.Title. The parts are not separate exports.
  • Icon-only controls require a label prop. It becomes the accessible name.

Conversation

Components that render the conversation itself. The chat composer is not a separate export: it is the Input component’s "composer" variant, with a send Input.Button — see Input.

AgentMessage

A single agent message: an avatar bubble beside the message text. Key props: initials, children.

1import { AgentMessage } from "@ada-cx/lovelace";
2
3<AgentMessage initials="A">
4 Hi! I can help with orders, billing, and returns.
5</AgentMessage>;

UserMessage

The end user’s outbound message bubble, with an optional failed-to-send retry affordance. Key props: children, error, onRetry.

1import { UserMessage } from "@ada-cx/lovelace";
2
3<>
4 <UserMessage>Where is my order?</UserMessage>
5 <UserMessage error="Message failed to send. Retry" onRetry={resend}>
6 This one failed to send.
7 </UserMessage>
8</>;

PictureMessage

An image message frame with a built-in “image unavailable” placeholder. Key props: src, alt, aspectRatio ("16:9" | "4:3" | "1:1" | "3:4" | "9:16"), unavailable, onLoadingStatusChange.

1import { PictureMessage } from "@ada-cx/lovelace";
2
3<PictureMessage
4 src="https://example.com/photo.jpg"
5 alt="Order photo"
6 aspectRatio="16:9"
7/>;

ProactiveMessage

A proactive greeting card shown outside the conversation window. Key props: children.

1import { ProactiveMessage } from "@ada-cx/lovelace";
2
3<ProactiveMessage>
4 👋 Need a hand picking a plan? I can compare them for you.
5</ProactiveMessage>;

Divider

A transcript separator: a plain rule, a labeled marker (for example “1 unread message”), or a centered system message. Key props: variant ("line" | "label" | "message"), heading, children.

1import { Divider } from "@ada-cx/lovelace";
2
3<>
4 <Divider variant="line" />
5 <Divider variant="label">1 unread message</Divider>
6 <Divider variant="message" heading="⏳ You are #1 in the queue">
7 An agent will be with you shortly.
8 </Divider>
9</>;

ScrollMarker

A floating jump-to-bottom control; shows an unread pill when messages wait below the fold. Key props: unreadCount, color ("default" | "brand"), onPress, children.

1import { ScrollMarker } from "@ada-cx/lovelace";
2
3<ScrollMarker unreadCount={2} onPress={scrollToBottom} />;

The conversation header bar. Compound: Header.Title.

1import { Avatar, Header } from "@ada-cx/lovelace";
2
3<Header>
4 <Avatar size="md" label="Ada AI Agent">
5 A
6 </Avatar>
7 <Header.Title>Ada</Header.Title>
8</Header>;

Actions

Buttons and links that trigger an action.

Button

The standard action button. Key props: variant ("primary" | "secondary" | "tertiary"), size ("md" | "sm"), destructive, onPress, isDisabled.

1import { Button } from "@ada-cx/lovelace";
2
3<>
4 <Button variant="primary" onPress={submit}>
5 Primary
6 </Button>
7 <Button variant="secondary">Secondary</Button>
8 <Button variant="tertiary">Tertiary</Button>
9 <Button variant="primary" destructive>
10 Delete
11 </Button>
12</>;

IconButton

An icon-only button. Key props: label (required), variant ("primary" | "secondary" | "tertiary"), size ("md" | "sm" | "xs"), destructive, children (a single icon).

1import { IconButton, SendFill } from "@ada-cx/lovelace";
2
3<IconButton label="Send message" onPress={send}>
4 <SendFill />
5</IconButton>;

PillButton

A pill-shaped secondary action button. Key props: size ("md" | "sm"), onPress, isDisabled.

1import { PillButton } from "@ada-cx/lovelace";
2
3<PillButton onPress={endChat}>End chat</PillButton>;

An inline text link, with optional external-link icon and download semantics. Key props: href, underlined, showIcon, download.

1import { Link } from "@ada-cx/lovelace";
2
3<Link href="https://docs.ada.cx" underlined showIcon>
4 Read the developer docs
5</Link>;

Forms and selection

Form and selection controls, including the chat composer.

Input

The text field and chat composer. Compound: Input.Label, Input.Field, Input.Control (single line), Input.TextArea (auto-growing multi-line), Input.HelperText, Input.Button. Key props — root: variant ("default" | "composer"), value, onChange, isDisabled, isInvalid; Input.TextArea: minRows, maxRows.

1import { Input } from "@ada-cx/lovelace";
2
3<Input aria-label="Email address">
4 <Input.Label>Email address</Input.Label>
5 <Input.Field>
6 <Input.Control placeholder="you@example.com" />
7 </Input.Field>
8 <Input.HelperText>We reply within a day.</Input.HelperText>
9</Input>;

The composer variant adds the send button and an auto-growing text area:

1import { Input, SendFill } from "@ada-cx/lovelace";
2
3<Input variant="composer" aria-label="Message">
4 <Input.Field>
5 <Input.TextArea placeholder="Write a message" minRows={1} maxRows={3} />
6 <Input.Button label="Send">
7 <SendFill />
8 </Input.Button>
9 </Input.Field>
10</Input>;

Checkbox

A checkbox with an optional inline label. Key props: isSelected, onChange, children.

1import { Checkbox } from "@ada-cx/lovelace";
2
3<Checkbox defaultSelected>Email me a transcript</Checkbox>;

Radio and RadioGroup

RadioGroup groups Radio options with keyboard navigation. Key props — RadioGroup: value, onChange, aria-label, children; Radio: value, children.

1import { Radio, RadioGroup } from "@ada-cx/lovelace";
2
3<RadioGroup aria-label="Contact method" defaultValue="chat">
4 <Radio value="chat">Continue in chat</Radio>
5 <Radio value="email">Switch to email</Radio>
6</RadioGroup>;

Toggle

An on/off switch. Track-only: name it with aria-label. Key props: isSelected, onChange, aria-label.

1import { Toggle } from "@ada-cx/lovelace";
2
3<Toggle defaultSelected aria-label="Sound on" />;

Chip

A toggle chip for quick replies and filters. Key props: variant ("text" | "icon" | "number"), size ("md" | "lg"), isSelected, onChange, children.

1import { Chip } from "@ada-cx/lovelace";
2
3<>
4 <Chip defaultSelected>Track my order</Chip>
5 <Chip>Talk to an agent</Chip>
6</>;

SurveyRating

A numeric or icon rating scale (for example CSAT 1 to 5). Key props: options, aria-label (required), showLabels, selectedKey, onChange.

1import { SurveyRating } from "@ada-cx/lovelace";
2
3<SurveyRating
4 aria-label="How satisfied are you?"
5 showLabels
6 options={[
7 { value: 1, label: "Not satisfied" },
8 { value: 2 },
9 { value: 3 },
10 { value: 4 },
11 { value: 5, label: "Very satisfied" },
12 ]}
13/>;

SurveySelect

A chip group for single or multiple choice survey questions. Key props: options, aria-label (required), selectionMode ("single" | "multiple"), disallowEmptySelection, selectedKeys, onChange.

1import { SurveySelect } from "@ada-cx/lovelace";
2
3<SurveySelect
4 aria-label="What did we help with?"
5 selectionMode="multiple"
6 options={[{ label: "Orders" }, { label: "Billing" }, { label: "Returns" }]}
7/>;

Feedback and status

Components that report what the system is doing.

Reports a condition for as long as the condition holds, such as an outage, a lost connection, or a failed send. It never queues and never times out, so nothing transient pushes it out of view. Mount it once and drive it with visible. Give its container overflow: hidden, because the banner slides in from the container’s leading edge. Show one banner at a time. Key props: message, status, visible, revision, onDismiss, dismissLabel.

Pass onDismiss only when the reader can act on the condition. Pass revision when the same condition can repeat with the same wording, so a screen reader hears each repeat.

1import { Banner } from "@ada-cx/lovelace";
2
3<Banner
4 status="error"
5 message="Your network appears to be offline."
6 visible={isOffline}
7/>;

Spinner

A loading spinner for inline or region loading states. Key props: size ("sm" | "lg"), background ("default" | "accent"), label.

1import { Spinner } from "@ada-cx/lovelace";
2
3<Spinner size="lg" label="Loading" />;

ThinkingShimmer

An animated shimmer label shown while the AI Agent generates a reply. Key props: label.

1import { ThinkingShimmer } from "@ada-cx/lovelace";
2
3<ThinkingShimmer label="Thinking" />;

ToastNotification

The status card that Banner and ToastRegion render. It carries no live region of its own, so it announces nothing when you render it alone. Use it directly only inside a container that owns the announcement. Key props: status ("success" | "warning" | "error"), onDismiss, dismissLabel, dismissDisabled, messageProps, children.

1import { ToastNotification } from "@ada-cx/lovelace";
2
3<ToastNotification status="success" onDismiss={() => setShown(false)}>
4 Transcript sent
5</ToastNotification>;

ToastRegion

Shows the toasts on a queue as a labelled landmark region. The region owns announcement, dismissal timing, and focus. It names the dismiss button in the reader’s own language. It holds each countdown while the reader hovers or focuses the region. It keeps the region reachable with F6. The region shows no toast while a modal overlay is open. It holds each toast on the queue and shows it after the overlay closes. Create one queue for each surface. Give the region’s container overflow: hidden, because a toast slides in from the region’s leading edge. Key props: queue, aria-label.

1import { ToastQueue, ToastRegion } from "@ada-cx/lovelace";
2
3const toasts = new ToastQueue({ maxVisibleToasts: 1 });
4
5toasts.add({ message: "Transcript sent", status: "success" }, { timeout: 5000 });
6
7<ToastRegion queue={toasts} />;

TypingIndicator

An animated three-dot bubble shown while a human agent types. Use ThinkingShimmer for AI generation instead. Key props: aria-label, aria-live.

1import { TypingIndicator } from "@ada-cx/lovelace";
2
3<TypingIndicator aria-label="Agent is typing" />;

Overlays and menus

Modal and floating surfaces. The overlay components own presentation (scrim, focus trap, dismissal); the content components own layout.

BubbleOverlay

A non-dimming modal bubble near the bottom edge; the chat behind it stays visible. Key props: isOpen, onOpenChange, isDismissable, aria-label.

1import { BubbleOverlay } from "@ada-cx/lovelace";
2import { useState } from "react";
3
4function QuickHelp() {
5 const [open, setOpen] = useState(false);
6 return (
7 <BubbleOverlay
8 isOpen={open}
9 onOpenChange={setOpen}
10 isDismissable
11 aria-label="Quick help"
12 >
13 <p>A non-dimming bubble near the bottom edge.</p>
14 </BubbleOverlay>
15 );
16}

DialogOverlay

A centered modal dialog presentation with a scrim. Key props: isOpen, onOpenChange, isDismissable, role ("dialog" | "alertdialog").

1import { Button, Dialog, DialogOverlay } from "@ada-cx/lovelace";
2import { useState } from "react";
3
4function ConfirmDelete() {
5 const [open, setOpen] = useState(false);
6 return (
7 <DialogOverlay isOpen={open} onOpenChange={setOpen} isDismissable>
8 <Dialog>
9 <Dialog.Content>
10 <Dialog.Title>A modal dialog</Dialog.Title>
11 <Dialog.Body>
12 Presented by DialogOverlay with a scrim and a focus trap.
13 </Dialog.Body>
14 </Dialog.Content>
15 <Dialog.Actions>
16 <Button onPress={() => setOpen(false)}>Done</Button>
17 </Dialog.Actions>
18 </Dialog>
19 </DialogOverlay>
20 );
21}

FullscreenOverlay

A modal surface that fills the window. Key props: isOpen, onOpenChange, isDismissable.

1import { Button, FullscreenOverlay } from "@ada-cx/lovelace";
2import { useState } from "react";
3
4function FullscreenDemo() {
5 const [open, setOpen] = useState(false);
6 return (
7 <FullscreenOverlay isOpen={open} onOpenChange={setOpen} isDismissable>
8 <p>A surface that fills the window.</p>
9 <Button onPress={() => setOpen(false)}>Close</Button>
10 </FullscreenOverlay>
11 );
12}

SheetOverlay

A dimming, slide-up modal bottom-sheet presentation. Key props: isOpen, onOpenChange, isDismissable, aria-label.

1import { Sheet, SheetOverlay } from "@ada-cx/lovelace";
2import { useState } from "react";
3
4function TranscriptSheet() {
5 const [open, setOpen] = useState(false);
6 return (
7 <SheetOverlay isOpen={open} onOpenChange={setOpen} isDismissable>
8 <Sheet>
9 <Sheet.Header
10 title="A bottom sheet"
11 showClose
12 onClose={() => setOpen(false)}
13 />
14 <Sheet.Body>
15 <p>Presented by SheetOverlay: it dims and slides up.</p>
16 </Sheet.Body>
17 </Sheet>
18 </SheetOverlay>
19 );
20}

Dialog

Dialog content: icon, title, body, and action buttons. Compound: Dialog.Icon, Dialog.Content, Dialog.Title, Dialog.Body, Dialog.Actions. Wrap in DialogOverlay for the modal presentation.

1import { Button, Dialog } from "@ada-cx/lovelace";
2
3<Dialog>
4 <Dialog.Icon intent="warning" />
5 <Dialog.Content>
6 <Dialog.Title>Delete conversation?</Dialog.Title>
7 <Dialog.Body>This can't be undone.</Dialog.Body>
8 </Dialog.Content>
9 <Dialog.Actions>
10 <Button destructive>Delete</Button>
11 <Button variant="tertiary">Cancel</Button>
12 </Dialog.Actions>
13</Dialog>;

Sheet

Bottom-sheet content. Compound: Sheet.Header, Sheet.Body, Sheet.Actions. Wrap in SheetOverlay for the modal presentation.

1import { Button, Sheet } from "@ada-cx/lovelace";
2
3<Sheet>
4 <Sheet.Header title="Email transcript" showClose onClose={close} />
5 <Sheet.Body>
6 <p>Enter an email address to receive a copy of this conversation.</p>
7 </Sheet.Body>
8 <Sheet.Actions>
9 <Button>Send</Button>
10 </Sheet.Actions>
11</Sheet>;

Menu is a role="menu" collection with arrow-key navigation and typeahead; MenuItem is one row (compound: MenuItem.Label, plus MenuItem.Checkbox / MenuItem.Radio / MenuItem.Toggle for a selection indicator). Row content is ordered by child position around the label. Key props — Menu: aria-label, onAction, children; MenuItem: children.

1import { Menu, MenuItem } from "@ada-cx/lovelace";
2
3<Menu aria-label="Conversation actions" onAction={handleAction}>
4 <MenuItem>
5 <MenuItem.Label>Email transcript</MenuItem.Label>
6 </MenuItem>
7 <MenuItem>
8 <MenuItem.Label>Mute sounds</MenuItem.Label>
9 </MenuItem>
10 <MenuItem>
11 <MenuItem.Label>End chat</MenuItem.Label>
12 </MenuItem>
13</Menu>;

Tooltip and TooltipTrigger

Tooltip is an inverse-surface tooltip with a directional arrow; TooltipTrigger (re-exported from React Aria Components) associates it with a focusable trigger. Key props — Tooltip: placement ("top" | "bottom" | "left" | "right"), children; TooltipTrigger: delay, children.

1import { Button, Tooltip, TooltipTrigger } from "@ada-cx/lovelace";
2
3<TooltipTrigger delay={0}>
4 <Button variant="secondary" size="sm">
5 Hover me
6 </Button>
7 <Tooltip placement="top">Tooltips point at their trigger</Tooltip>
8</TooltipTrigger>;

Primitives

Low-level building blocks the other components compose.

Avatar

A circular avatar bubble holding initials, an Icon, or an Image. Key props: size ("sm" | "md" | "lg" | "xl"), label (or aria-hidden), showAvatar, children.

1import { Avatar, Image } from "@ada-cx/lovelace";
2
3<>
4 <Avatar size="lg" label="Ada AI Agent">
5 A
6 </Avatar>
7 <Avatar size="md" label="Support agent">
8 <Image src="https://example.com/agent.jpg" alt="" />
9 </Avatar>
10</>;

AvatarPlaceholder

An empty avatar bubble for loading or anonymous states. Key props: size.

1import { AvatarPlaceholder } from "@ada-cx/lovelace";
2
3<AvatarPlaceholder size="md" />;

Icon

Wraps one icon glyph and standardizes its size and accessible name. Key props: label, children.

1import { Icon, SendFill } from "@ada-cx/lovelace";
2
3<Icon label="Send">
4 <SendFill />
5</Icon>;

Image

An image with load-state tracking and a fallback slot. Key props: src, alt (required), fallback, onLoadingStatusChange.

1import { Image } from "@ada-cx/lovelace";
2
3<Image src="https://example.com/photo.jpg" alt="Order photo" />;

Icon glyphs

The package also exports a set of ready-made glyph components, including ArrowDown, Checkmark, ChevronLeft, CloudUpload, Email, Paperclip, SendFill, ThumbsDown, and ThumbsUp. Each glyph wraps itself for correct sizing, so you can pass one directly wherever a component asks for an icon:

1import { IconButton, SendFill } from "@ada-cx/lovelace";
2
3<IconButton label="Send message" onPress={send}>
4 <SendFill />
5</IconButton>;

The full glyph list is in the package’s TypeScript declarations, and every glyph renders in the live component gallery.