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.
Each entry opens with a live preview of the component. The previews use the theme and color scheme you set in the theme playground.
Shared conventions
All components follow the same contract:
- Check each component’s TypeScript declarations for its supported
className,ref, andstyleprops. - Interactive components extend the matching React Aria Components props. Use
onPressinstead ofonClick, andisDisabledinstead ofdisabled. - Interactive states render as
data-*attributes:data-disabled,data-focus-visible,data-hovered,data-pressed,data-selected. Extend styling by targeting those attributes, not pseudo-classes. - Compound components attach their parts with dot notation, for example
Input.FieldandDialog.Title. The parts are not separate exports. IconButtonandInput.Buttonrequire alabelprop for the accessible name.Chipwithvariant="icon"and an icon-onlyPillButtontakearia-labelinstead.
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 body. The content accepts blocks, such as lists and tables. Key props: children.
Row layout is yours, not the component’s. Place an avatar, a sender name or a retry control beside the body rather than inside it, so they align with the text and stay outside the body’s own text-direction detection. MessageRow supplies that layout. Use <Avatar showAvatar={false}> to hold the gutter on a grouped message that shows no avatar.
Divider
A transcript separator: a plain rule, a labeled marker (for example “1 unread message”), or a centered system message. Key props: children, heading, variant ("label" | "line" | "message").
DropZone
A region that accepts dropped files. While a drag is over the region, a panel covers its children. Key props: allowMultiple, description, ignorePageDrags, isDisabled, label, onDropError, onFileDrop, onFilesDrop, onMultipleFilesRejected, onNoFilesDropped.
Supply exactly one of onFileDrop and onFilesDrop. onFileDrop receives one file per drop: a drop with more files calls onMultipleFilesRejected, unless allowMultiple is set. onFilesDrop receives every readable file of a drop in one call. label is the panel heading and the accessible name of the keyboard drop button.
The panel fills the nearest positioned ancestor, so that ancestor sets the droppable area. Set ignorePageDrags when the zone covers content that the user can drag, such as text or images in the transcript.
Header
The conversation header bar arranges its children in one row. Key props: children.
Parts:
Header.Titlerenders the header heading. Key props:children,level.
MessageError
The failed-to-send row shown below a message bubble. With onRetry the copy becomes a retry control and names it. Without onRetry the copy renders as static text. Key props: announce, children, onRetry.
children must be a plain string. It supplies the announced text and the retry control’s name.
The row announces the failure through a visually-hidden role="alert". Set announce to false on a surface that announces message failures through its own live region. Two live regions announce the same text twice.
Without onRetry, the row hides the visible copy from assistive technology while announce stays on. The alert already carries that text. With onRetry, the copy stays exposed, because it names the retry control.
The row also aligns at the leading edge of its container. Put it in an end-aligned column to keep it below the bubble.
MessageRow
One row of a transcript: an optional avatar gutter, then MessageRow.Content, the column that holds everything belonging to the message. Key props: sender. Required. Accepts "agent" or "user".
sender sets which edge the row aligns to and the typography the column carries. The row imposes no message body. A row that shows prose renders AgentMessage or UserMessage inside the column. A row that shows a card, a widget or media renders neither, and still reads at message size. Set fill when the content supplies no width of its own.
Keep the avatar a sibling of the column rather than a child of it. A reaction bar or a retry control beside the message then aligns with the message text.
Parts:
MessageRow.Contentholds the message body and related controls. Key props:children,fill.
PictureMessage
An image message frame with a built-in “image unavailable” placeholder. Key props: alt, aspectRatio ("1:1" | "16:9" | "3:4" | "4:3" | "9:16"), onLoadingStatusChange, src, unavailable.
ProactiveMessage
A proactive greeting card shown outside the conversation window. Key props: children.
ScrollMarker
A floating jump-to-bottom control; shows an unread pill when messages wait below the fold. Key props: children, color ("brand" | "default"), onPress, unreadCount.
UserMessage
The end user’s outbound message bubble, shrink-wrapped to its content. The content accepts blocks, such as lists and tables. Key props: children.
Where the bubble sits is yours: align it to the trailing edge in your own row. Render MessageError beside the bubble when a send fails.
VideoMessage
The frame for a video message. It clips the player to the media corner radius, keeps a fixed aspect ratio, and gives the video an accessible group label. The frame has no playback logic: supply your own player as children. Key props: alt (required), aspectRatio ("1:1" | "16:9" | "3:4" | "4:3" | "9:16"), children, unavailable.
The frame shows a “video unavailable” placeholder when unavailable is set or when children renders nothing. The frame fills the width of its container, so constrain it to the message column.
Actions
Buttons and links that trigger an action.
Button
The standard action button. Key props: destructive, isDisabled, onPress, size ("md" | "sm"), variant ("primary" | "secondary" | "tertiary").
IconButton
An icon-only button. Key props: children, destructive, label, size ("md" | "sm" | "xs"), variant ("primary" | "secondary" | "tertiary"). Supply one icon as children and an accessible name as label.
Link
A standalone link control with a trailing external-link icon by default. With download, it shows a download icon. Set showIcon={false} to hide the icon. Its box cannot split across surrounding prose lines. Text inside the control can wrap. Key props: download, href, showIcon, underlined.
PillButton
A pill-shaped secondary action button. Key props: isDisabled, onPress, size ("md" | "sm").
Forms and selection
Form and selection controls, including the chat composer.
AttachmentChip
A staged or attached file inside the composer field: a thumbnail or a stand-in, the file name, and one control. Key props: action, aria-expanded, aria-haspopup, isBusy, label, media, onImageError, onPress, thumbnailUrl.
With onPress, set aria-haspopup="dialog" when the chip opens a sheet. Set aria-expanded to true while the sheet is open.
The chip has two shapes. With action, the chip is a container and the trailing control, typically a remove IconButton, is its only control. With onPress, the chip itself is the control, for example a “3 attachments” summary that opens a sheet. The chip ignores action when onPress is set. Place chips in Input.Attachments: see Input.
Checkbox
A check box with an optional inline label. Key props: children, isSelected, onChange, variant.
variant accepts "inline" or "row". The default, inline, puts the control beside its label. row renders a full-width option row with a minimum height of 40px, which grows for wrapped labels.
CheckboxGroup
CheckboxGroup groups Checkbox options and owns the selected values. Key props: aria-label, children, onChange, value.
Chip
A toggle chip for quick replies and filters. Key props: children, isSelected, onChange, size ("lg" | "md"), variant ("icon" | "number" | "text").
The icon variant has no visible text. Pass aria-label.
Input
Input coordinates the text control, label, and helper text. Key props: isDisabled, isInvalid, onChange, value, variant ("composer" | "default").
Parts:
Input.Attachmentsholds the attachment chips. Key props:children.Input.Buttonadds an icon button to the field. Key props:children,isDisabled,label,onPress.Input.Controlrenders a single line of text. Key props:placeholder,type.Input.Fieldgroups the control, attachments, and button. Key props:children,hasAttachments.Input.HelperTextdescribes the input. Key props:children.Input.Labelsupplies the input’s visible label. Key props:children.Input.TextAreagrows with its content. Key props:maxRows,minRows,placeholder.
The composer variant adds the send button and an auto-growing text area:
Input.Attachments holds attachment chips after the control and before Input.Button. Set hasAttachments on Input.Field. The control fills the first line. The chips and send button share the second line, aligned at the bottom. This replaces the attachment-first layout used before version 1.12.0.
Input.Field allows its children to wrap in both variants. A child that cannot shrink moves to a new line.
Radio and RadioGroup
RadioGroup groups Radio options with keyboard navigation. Key props for Radio: children, value, variant. Key props for RadioGroup: aria-label, children, onChange, value.
Radio.variant accepts "inline" or "row". The default, inline, puts the control beside its label. row renders a full-width option row with a minimum height of 40px, which grows for wrapped labels.
SurveyRating
A numeric or icon rating scale (for example CSAT 1 to 5). Provide aria-label, or use aria-labelledby to reference the visible question label. Key props: aria-label, aria-labelledby, defaultSelectedKey, isDisabled, onChange, options, selectedKey, showLabels.
Each option accepts these fields:
Set icon to render an icon chip instead of the number. Give each icon option a label or aria-label for its accessible name.
key defaults to the option’s index. Use defaultSelectedKey for an uncontrolled scale.
onChange(key, option) receives null for both arguments on deselection.
SurveySelect
A chip group for single or multiple choice survey questions. Provide aria-label, or use aria-labelledby to reference the visible question label. Key props: aria-label, aria-labelledby, disallowEmptySelection, onChange, options, selectedKeys, selectionMode ("multiple" | "single").
Toggle
An on/off switch. Track-only: name it with aria-label. Key props: aria-label, isSelected, onChange.
Feedback and status
Components that report what the system is doing.
Banner
The tinted full-width strip that reports a condition, such as an outage, a lost connection, or a failed send. It carries no control, because only the state that raised the condition takes the banner down. It is presentational and owns no live region, so it announces nothing on its own. Put it in a BannerContainer. Key props: children, status ("error" | "success" | "warning").
BannerContainer
Announces and animates one Banner. It owns the live region and mounts it empty, so a banner that arrives is a change the screen reader reports. error interrupts as an assertive alert. Any other status waits its turn as a polite status. The container clips the banner’s travel, so you need no overflow rule of your own. Mount it for as long as the surface exists. It never queues and never times out, and it holds one banner at a time, so pick the condition to show before you hand it over. Key props: children, occurrence.
Change occurrence whenever the reader must hear the banner again: the same condition raised a second time with the same wording, a different condition taking the slot, or a change of status. A change hides the live region for a frame and reveals it, which is what makes wording the reader has already heard read out again. Leave it alone to reword the banner, and the live region reports the new text on its own.
Spinner
A loading spinner for inline or region loading states. Key props: background ("accent" | "default"), label, size ("lg" | "sm").
ThinkingShimmer
An animated shimmer label shown while the AI Agent generates a reply. Key props: label.
Toast
The floating card that ToastContainer renders. It sits above the transcript on a neutral background, so a passing event does not look like the tinted strip a lasting condition uses. 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: children, dismissDisabled, dismissLabel, icon, messageProps, onDismiss, status ("custom" | "error" | "loading" | "success" | "warning").
Set icon to supply the glyph for status="custom". The loading status shows a spinner and renders no dismiss button.
ToastContainer
Shows the toasts on a queue as a labelled landmark region. The container owns announcement, the card surface, and the motion. It names the dismiss button in the reader’s own language. It keeps the region reachable with F6. The container shows no toast while a modal overlay is open, and shows the queue again after the overlay closes. Create one queue for each surface.
Lovelace overlays register themselves. For your own React Aria ModalOverlay, call useRegisterOverlay() from a component inside it. Then ToastContainer and useHasOpenOverlay detect the open overlay.
You own the clock. Decide which toasts exist, how long each one lives, and what a dismiss press means. Put a key in exiting to start that card’s travel off the stack, and keep the card on the queue until onExited reports it. Key props: aria-label, exiting, onDismiss, onExited, queue.
Hold your countdowns for two cases the reader cannot read through. A modal overlay hides the stack, so a countdown that runs on expires a card the reader never saw. The useHasOpenOverlay hook reports whether one is open. Keyboard focus inside the stack is the reader asking for more time, which is the only extension a card that dismisses itself offers. Listen for focusin and focusout on the container, and hold for as long as focus stays. The example below holds for the overlay; hold for focus the same way.
Each queue entry takes { message, status?, icon? }. The status accepts "custom", "error", "loading", "success", and "warning", and defaults to "success". Set icon to supply the glyph for status: "custom". A loading toast renders no dismiss button, so close or replace it from the code that queued it.
TypingIndicator
An animated three-dot bubble shown while a human agent types. Use ThinkingShimmer for AI generation instead. Key props: aria-label, aria-live.
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: aria-label, isDismissable, isOpen, onOpenChange.
Dialog
Dialog content groups an icon, title, body, and action buttons. Key props: children, className. Wrap the content in DialogOverlay for modal behavior.
Parts:
Dialog.Actionsstacks the action buttons. Key props:children,className.Dialog.Bodyrenders the dialog description. Key props:children,className,id.Dialog.Contentgroups the title and description. Key props:children,className.Dialog.Iconshows the status icon. Key props:className,intent("success"|"warning").Dialog.Titlesupplies the dialog’s accessible name. Key props:children,className.
DialogOverlay
A centered modal dialog presentation with a scrim. Key props: aria-describedby, aria-label, isDismissable, isOpen, onOpenChange, role ("alertdialog" | "dialog").
For role="alertdialog", set an id on Dialog.Body. Pass that ID as aria-describedby.
FullscreenOverlay
A modal surface that fills the window. Key props: aria-label, isDismissable, isOpen, onOpenChange.
Name the dialog with a Sheet.Title inside it or with aria-label.
Menu and MenuItem
Menu groups rows with arrow-key navigation and text search. MenuItem renders one row. Key props for Menu: aria-label, children, defaultSelectedKeys, onAction, selectionMode. Key props for MenuItem: children, id, isDisabled, onAction, textValue.
Parts:
MenuItem.Checkboxshows a checkbox selection indicator. Key props:className,ref.MenuItem.Labelsupplies the row’s text. Key props:children.MenuItem.Radioshows a radio selection indicator. Key props:className,ref.MenuItem.Toggleshows a toggle selection indicator. Key props:className,ref.
Place each selection indicator directly inside MenuItem. Set selectionMode="multiple" for checkboxes and toggles, or selectionMode="single" for radio indicators.
Sheet
Bottom-sheet content groups a header, body, and actions. Key props: children, className, style. Place the header children in this order: Sheet.BackButton, Sheet.Title, Sheet.CloseButton. Wrap the content in SheetOverlay for modal behavior.
Parts:
Sheet.Actionsstacks the action buttons. Key props:children,className.Sheet.BackButtonadds the header’s back button. Key props:className,label,onPress.Sheet.Bodyholds the scrollable content. Key props:children,className,id,keyboardScrollLabel.Sheet.CloseButtonadds the header’s close button. Key props:className,label,onPress.Sheet.Headergroups the title and buttons. Key props:children,className.Sheet.Titlesupplies the dialog’s accessible name. Key props:children,className.
Sheet.Header takes its content as children. The earlier backLabel, closeLabel, onBack, onClose, showBack, showClose, and title props are removed. Render Sheet.Title for the title, and Sheet.BackButton or Sheet.CloseButton for the edge buttons.
SheetOverlay
A dimming, slide-up modal bottom-sheet presentation. Key props: aria-describedby, aria-label, isDismissable, isOpen, maxHeight, onOpenChange.
maxHeight defaults to 80% of the available height. The widget sheet uses 100%.
Tooltip and TooltipTrigger
Tooltip displays help text with a directional arrow. TooltipTrigger associates it with a focusable control. Key props for Tooltip: children, placement ("bottom" | "left" | "right" | "top"). Key props for TooltipTrigger: children, delay.
Primitives
Low-level building blocks the other components compose.
Avatar
A circular avatar bubble holding initials, an Icon, or an Image. Key props: aria-hidden, children, label, showAvatar, size ("lg" | "md" | "sm" | "xl").
Pass exactly one: label to name the avatar, or aria-hidden={true} to mark it decorative.
AvatarPlaceholder
An empty avatar bubble for loading or anonymous states. Key props: size.
Icon
Wraps your own SVG glyph and standardizes its size and accessible name. Exported glyphs already wrap themselves. Pass label to a glyph directly. Key props: children, label.
Icon glyphs
The package exports glyph components, including ArrowDown, ArrowUp, Checkmark, ChevronLeft, CloudUpload, Email, Paperclip, Send, ThumbsDown, and ThumbsUp. Each glyph wraps itself for correct sizing. Pass a glyph directly wherever a component accepts an icon. Key props: label. Each glyph is decorative by default. Set label when the glyph needs its own accessible name.
ArrowUp is a separate upward arrow.
The preview includes every exported glyph:
AdaLogo, ArrowDown, ArrowLeft, ArrowNortheast, ArrowNorthwest, ArrowRight, ArrowUp, Bell, BellSlash, Checkmark, CheckmarkCircle, ChevronLeft, ChevronRight, CloudUpload, Document, Download, Ellipses, Email, ExclamationSync, ExclamationTriangle, Eye, EyeSlash, Language, MediaSlash, MessagingFill, Minimize, Mute, Paperclip, PersonFill, PlayFill, Send, StarBadgeFill, ThumbsDown, ThumbsUp, Volume, Xmark, XmarkCircle.
Image
An image with load-state tracking and a fallback slot. Key props: alt, fallback, onLoadingStatusChange, src. Supply alt for every image.
LovelaceProvider
Applies a color scheme and token overrides to its children, including overlays. Key props: children, override, theme ("auto" | "dark" | "light"). The default "auto" theme follows the system color scheme.
Text
Text at one of the four semantic type tiers. Key props: as, variant ("body" | "caption" | "title-large" | "title-small"), weight ("medium" | "regular" | "semi-bold").
Text renders a <span> by default. Set as to render a different element. Do not use Text for a heading, because a heading gets its level from its role. Use the React Aria Heading component instead, as Dialog.Title does.