Skip to main content
For development, import BottomSheet from @servicetitan/anvil2-ai-kit. For design, find it in the AI Kit Web Component Library file.

Options

The Bottom Sheet supports an optional subheader, an optional close button, and any content composed from Carto components.

Subheader

An optional subheader renders a secondary line beneath the title — useful for a short status or timestamp. Omit it for a title-only header, as in the hero example above.

Close Button

The header close button is shown by default. Set showCloseButton={false} to hide it — the sheet remains dismissable via the drag handle, the backdrop, and Escape.

Content

content accepts any ReactNode, so compose Carto components — Checkbox, ArtifactCard, ActionLog, and so on — to build the sheet’s body.

Behavior

The Bottom Sheet negotiates its own height from content and viewport, and its body scrolls independently of the pinned header.

Sizing and Resizing

The sheet has a single, self-negotiated size rather than discrete size options. It opens at a start height that hugs its content up to 50% of the viewport, and the drag handle — draggable by pointer, or by Arrow Up / Arrow Down / Home / End when focused — resizes it between that start height and a 90% viewport ceiling. Dragging or pressing Arrow Down below the start height closes the sheet.

Scrolling Body

When content exceeds the current detent, the body scrolls independently while the header and drag handle stay pinned. A scroll shadow appears once the body has scrolled.

Usage Guidelines

When to Use

Use the Bottom Sheet when:
  • Secondary content – Supporting content needs a modal panel that rises from the bottom of the screen.
  • Forms, lists, and composed layouts – The body combines Carto components, such as Checkbox, Artifact Card, or Action Log.
  • Content that varies in height – The sheet opens at the height of its content, up to half the viewport, and users drag it taller to see more.

When not to use

Avoid using the Bottom Sheet for:
  • Short confirmations and acknowledgements – Use a Dialog for message-style content, such as a confirm and cancel decision or an acknowledge-only message.

Keyboard Interaction

Users can navigate, resize, and dismiss the Bottom Sheet using standard keyboard controls.

Code

Common Examples

To use the BottomSheet, pass the required title and content props. Open it with a Carto Button through trigger, or control it with isOpen and onOpenChange.

Body content

Unlike Dialog, the sheet’s content is a general body region for forms, lists, and composed layouts.

Subheader

Pass a short subheader to provide context beneath the title.

Close button

The header close button appears by default. Set showCloseButton={false} to remove it. The sheet remains dismissable through the drag handle, backdrop, and Escape.

Scrolling body

Content beyond the current detent scrolls inside the body while the handle and header remain visible.

Controlled state

Omit trigger and pass isOpen with onOpenChange when an event or another component opens the sheet.

Internationalization

Localize title, subheader, and content before passing them to BottomSheet. The component uses these messages for built-in controls:
  • ai-kit.bottomSheet.close
  • ai-kit.bottomSheet.resize
  • ai-kit.bottomSheet.resizeValue
Mount AiKitIntlProvider inside CartoTheme to switch locale or override them. resizeValue receives a {percent} value.

React Accessibility

  • The required title labels the modal through aria-labelledby. subheader is associated through aria-describedby.
  • The drag handle is a vertical slider. Arrow keys move between detents and expose the current viewport percentage.
  • The body is always keyboard-focusable so keyboard users can scroll plain content.
  • React Aria supplies focus trapping and restoration, scroll lock, aria-modal, Escape dismissal, and outside-interaction dismissal.
Last modified on October 27, 2026