Skip to content

Composer

Try the composer’s selectors, attachment options, and recording control. Toggle Agent turn in progress to switch between a single Submit button and Stop with an icon-only split action/ellipsis control. Choose Queue or Steer from the menu; a check marks the current selection, which the primary button performs. Sending a message also starts the simulated turn; Stop or the toggle ends it without clearing your draft.

Messages and files stay in this example.

View code
import { useEffect, useRef, useState } from "react";
import { Composer, type ComposerDraft } from "@stack/ui/composer";
import { useAudioRecording } from "@stack/ui/use-audio-recording";
import { useAttachmentCapabilities } from "@stack/ui/use-attachment-capabilities";
import { Attachment } from "@stack/ui/attachment";
import { Button } from "@/components/ui/button";
import {
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
} from "@/components/ui/dropdown-menu";
import { EllipsisIcon } from "lucide-react";
type LocalFile = { id: string; src: string; name: string; type: string };
type Submission = {
id: string;
text: string;
files: LocalFile[];
action: "Send" | "Queue" | "Steer";
model: string;
effort: string;
};
function FilePreview({
file,
onRemove,
}: {
file: LocalFile;
onRemove?: () => void;
}) {
return (
<Attachment.Root
src={file.src}
name={file.name}
type={file.type}
onRemove={onRemove}
>
<Attachment.PreviewTrigger />
<Attachment.Remove />
<Attachment.PreviewContent>
<Attachment.Header>
<Attachment.HeaderContent>
<Attachment.Title />
<Attachment.Description />
</Attachment.HeaderContent>
<Attachment.Actions>
<Attachment.Download />
<Attachment.Close />
</Attachment.Actions>
</Attachment.Header>
<Attachment.Content />
</Attachment.PreviewContent>
</Attachment.Root>
);
}
export default function Example() {
const { narrowViewport } = useAttachmentCapabilities();
const [draft, setDraft] = useState<ComposerDraft | string>("");
const [files, setFiles] = useState<LocalFile[]>([]);
const [submissions, setSubmissions] = useState<Submission[]>([]);
const [model, setModel] = useState("General");
const [effort, setEffort] = useState("Medium");
const [working, setWorking] = useState(false);
const [busyAction, setBusyAction] = useState<"Queue" | "Steer">("Queue");
const [loading, setLoading] = useState(false);
const [disabled, setDisabled] = useState(false);
const [notice, setNotice] = useState(
"Messages and files stay in this example.",
);
const [exampleError, setExampleError] = useState<string | null>(null);
const urls = useRef(new Set<string>());
const text = typeof draft === "string" ? draft : draft.text;
const voice = useAudioRecording({
scopeKey: "composer-docs",
onRecording(recording) {
attach([
new File([recording.blob], "recording.pcm", {
type: "application/octet-stream",
}),
]);
setNotice(
"Audio attached as raw PCM. No transcription or upload was performed.",
);
},
});
const ready = !!(text.trim() || files.length) && !voice.busy && !disabled;
useEffect(() => {
const created = urls.current;
return () => {
for (const url of created) URL.revokeObjectURL(url);
created.clear();
};
}, []);
function attach(selected: File[]) {
const added = selected.map((file) => {
const src = URL.createObjectURL(file);
urls.current.add(src);
return { id: crypto.randomUUID(), src, name: file.name, type: file.type };
});
setFiles((current) => [...current, ...added]);
}
function submit(action: Submission["action"] = "Send") {
if (!ready) return;
setSubmissions((current) => [
...current,
{ id: crypto.randomUUID(), text, files, action, model, effort },
]);
setDraft("");
setFiles([]);
if (action === "Send") setWorking(true);
setNotice(
action === "Queue"
? "Queued locally. Queue entries are not dispatched automatically."
: action === "Steer"
? "Steered the simulated turn locally."
: "Agent turn in progress. Try Stop, Queue, or Steer.",
);
}
function stop() {
setWorking(false);
setNotice("Local response stopped. Your current draft is preserved.");
}
return (
<div className="grid min-w-0 gap-4">
<div className="flex flex-wrap gap-2">
<Button
role="switch"
aria-label="Agent turn in progress"
aria-checked={working}
variant={working ? "secondary" : "outline"}
size="sm"
onClick={() => {
setWorking((value) => !value);
setNotice(
working
? "Agent turn finished. Your current draft is preserved."
: "Agent turn in progress. Try Stop or queue a message.",
);
}}
>
Agent turn in progress: {working ? "On" : "Off"}
</Button>
<Button
variant="outline"
size="sm"
onClick={() => setLoading((value) => !value)}
>
{loading ? "Finish loading selectors" : "Show selector loading"}
</Button>
<Button
variant="outline"
size="sm"
onClick={() => setDisabled((value) => !value)}
>
{disabled ? "Enable composer" : "Disable composer"}
</Button>
<Button
variant="outline"
size="sm"
onClick={() =>
setExampleError((value) =>
value
? null
: "Example recording error. Clear this message to continue.",
)
}
>
{exampleError ? "Clear recording error" : "Show recording error"}
</Button>
</div>
<Composer.RecordingError error={voice.error ?? exampleError} />
{!!files.length && (
<div aria-label="Draft attachments" className="flex flex-wrap gap-2">
{files.map((file) => (
<FilePreview
key={file.id}
file={file}
onRemove={
disabled
? undefined
: () =>
setFiles((current) =>
current.filter((item) => item.id !== file.id),
)
}
/>
))}
</div>
)}
<Composer.Root
value={draft}
onChange={setDraft}
onFiles={attach}
disabled={disabled}
submitState={ready ? "ready" : "blocked"}
onSubmit={() => submit(working ? busyAction : "Send")}
>
<Composer.Input
id="docs-composer"
aria-label="Message"
placeholder="Message…"
onInterrupt={() => {
if (voice.busy) voice.cancel();
else stop();
}}
/>
<Composer.AttachMenu onFiles={attach}>
{narrowViewport ? (
<>
<Composer.AttachCamera capture="environment" />
<Composer.AttachPhotos />
<Composer.AttachFiles />
</>
) : (
<Composer.AttachPhotosAndFiles />
)}
</Composer.AttachMenu>
<Composer.Footer>
<Composer.RecordAudio
status={voice.status}
level={voice.level}
onStart={voice.start}
onStop={voice.stop}
/>
{working ? (
<>
<Composer.Stop onClick={stop} />
<Composer.SubmitGroup>
<Composer.Submit label={`${busyAction} message`} />
<Composer.SubmitSeparator />
<Composer.SubmitMenu disabled={!ready}>
<Composer.SubmitMenuTrigger>
<EllipsisIcon aria-hidden="true" />
</Composer.SubmitMenuTrigger>
<Composer.SubmitMenuContent>
<DropdownMenuRadioGroup
value={busyAction}
onValueChange={setBusyAction}
>
<DropdownMenuRadioItem value="Queue" closeOnClick>
Queue
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="Steer" closeOnClick>
Steer
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</Composer.SubmitMenuContent>
</Composer.SubmitMenu>
</Composer.SubmitGroup>
</>
) : (
<Composer.Submit label="Send message" />
)}
</Composer.Footer>
</Composer.Root>
<Composer.Toolbar>
<Composer.ToolbarGroup>
<Composer.Selector
value={model}
onValueChange={setModel}
loading={loading}
disabled={disabled}
>
<Composer.SelectorTrigger aria-label="Model">
{model}
</Composer.SelectorTrigger>
<Composer.SelectorContent>
<Composer.SelectorGroup>
<Composer.SelectorLabel>Model</Composer.SelectorLabel>
{["General", "Fast", "Reasoning"].map((value) => (
<Composer.SelectorItem key={value} value={value}>
{value}
</Composer.SelectorItem>
))}
</Composer.SelectorGroup>
</Composer.SelectorContent>
</Composer.Selector>
<Composer.Selector
value={effort}
onValueChange={setEffort}
loading={loading}
disabled={disabled}
>
<Composer.SelectorTrigger aria-label="Reasoning effort">
{effort}
</Composer.SelectorTrigger>
<Composer.SelectorContent>
<Composer.SelectorGroup>
<Composer.SelectorLabel>
Reasoning effort
</Composer.SelectorLabel>
{["Low", "Medium", "High"].map((value) => (
<Composer.SelectorItem key={value} value={value}>
{value}
</Composer.SelectorItem>
))}
</Composer.SelectorGroup>
</Composer.SelectorContent>
</Composer.Selector>
</Composer.ToolbarGroup>
</Composer.Toolbar>
<p role="status">{notice}</p>
{!!submissions.length && (
<div
aria-label="Local submissions"
className="grid max-h-64 gap-4 overflow-auto"
>
{submissions.map((submission) => (
<div key={submission.id} className="grid gap-2">
<p>
{submission.action} · {submission.model} · {submission.effort}
</p>
{submission.text && <p>{submission.text}</p>}
<div className="flex flex-wrap gap-2">
{submission.files.map((file) => (
<FilePreview key={file.id} file={file} />
))}
</div>
</div>
))}
</div>
)}
</div>
);
}
import { useState } from "react";
import { Composer } from "@stack/ui/composer";

The attachment menu shows Camera, Photos, and Files on narrow screens, and Photos & Files on desktop.

Messages, files, and queue entries stay in memory. Queue entries are not sent automatically. Camera and microphone access is requested only when their controls are clicked. Audio is attached as raw PCM without transcription. The controls above the composer let you try selector loading, the disabled state, and recording errors.

Tables list component-specific props and inherited control options. Components that forward native props also accept the applicable React HTML attributes and event handlers, including data-* and aria-* attributes.

Also accepts native element props.

Prop Type Required Description
className string No Additional CSS classes for the underlying element.
children ReactNode No Content rendered inside the component.
onPasteCapture ClipboardEventHandler<HTMLDivElement> No Handle paste events before the built-in attachment handler.
onFocusCapture FocusEventHandler<HTMLDivElement> No Handle focus entering the composer.
onBlurCapture FocusEventHandler<HTMLDivElement> No Handle focus leaving the composer.
onDragOverCapture DragEventHandler<HTMLDivElement> No Handle drag-over events before the built-in attachment handler.
onDropCapture DragEventHandler<HTMLDivElement> No Handle drop events before the built-in attachment handler.
onFiles ((files: File[]) => void) No Receive files selected, pasted, or dropped into the component.
value string | ComposerDraft Yes Current controlled value.
onChange (value: ComposerDraft) => void Yes Called when the value changes.
onSubmit () => void Yes Handle submission.
inputRef Ref<PromptInputHandle> No Ref for the prompt editor’s imperative handle.
newlineShortcut "enter" | "shift-enter" | "ctrl-enter" No Keyboard shortcut that inserts a newline. Default: "shift-enter".
submitShortcut "enter" | "shift-enter" | "ctrl-enter" No Keyboard shortcut that submits the draft. Default: "enter".
disabled boolean No Disable interaction. Default: false.
submitState "ready" | "blocked" | "pending" No Control whether submission is ready, blocked, or pending. Default: "ready".

Also accepts native element props.

Prop Type Required Description
className string No Additional CSS classes for the underlying element.
children ReactNode No Content rendered inside the component.

Also accepts native element props.

Prop Type Required Description
className string No Additional CSS classes for the underlying element.
children ReactNode No Content rendered inside the component.
Prop Type Required Description
defaultOpen boolean No Whether the menu is initially open.
loopFocus boolean No Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.
highlightItemOnHover boolean No Whether moving the pointer over items should highlight them.
modal boolean No Determines if the menu enters a modal state when open. - true: user interaction is limited to the menu: document page scroll is locked and pointer interactions on outside elements are disabled. - false: user interaction with the rest of the document is allowed.
onOpenChange ((open: boolean, eventDetails: MenuRoot.ChangeEventDetails) => void) No Event handler called when the menu is opened or closed.
onOpenChangeComplete ((open: boolean) => void) No Event handler called after any animations complete when the menu is opened or closed.
onItemHighlighted ((highlightedItem: HTMLElement | undefined, eventDetails: MenuRoot.HighlightEventDetails) => void) No Callback fired when an item is highlighted or unhighlighted.
open boolean No Controlled open state.
orientation MenuRootOrientation No Orientation of the component.
disabled boolean No Whether the component should ignore user interaction. Default: false.
closeParentOnEsc boolean No When in a submenu, determines whether pressing the Escape key closes the entire menu, or only the current child menu.
actionsRef RefObject<MenuRootActions | null> No A ref to imperative actions. - unmount: Ends the closing phase of the menu after an externally controlled closing animation finishes.
triggerId string | null No ID of the trigger that the menu is associated with.
defaultTriggerId string | null No ID of the trigger that the menu is associated with.
handle Handle<unknown> No A handle to associate the menu with a trigger.
children ReactNode | PayloadChildRenderFunction<unknown> No Content rendered inside the component.
value string Yes Current controlled value.
onValueChange (value: string) => void Yes Called when the selected value changes.
loading boolean No Whether data is loading. Default: false.

Also accepts native element props.

Prop Type Required Description
children ReactNode No Content rendered inside the component.
disabled boolean No Disable interaction.
handle Handle<unknown> No A handle to associate the trigger with a menu.
payload unknown No A payload to pass to the menu when it is opened.
delay number No How long to wait before the menu may be opened on hover.
closeDelay number No How long to wait before closing the menu that was opened on hover.
openOnHover boolean No Open the hint when the trigger is hovered.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
aria-label string Yes Defines a string value that labels the current element.
className string | ((state: MenuTriggerState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, MenuTriggerState> No Replace the underlying element using render composition.
style CSSProperties | ((state: MenuTriggerState) => CSSProperties | undefined) No Inline styles for the underlying element.

Also accepts native element props.

Prop Type Required Description
children ReactNode No Content rendered inside the component.
id string No Element identifier.
finalFocus boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) No Determines the element to focus when the menu is closed.
className string | ((state: ContextMenuPopupState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuPopupState> No Replace the underlying element using render composition.
style CSSProperties | ((state: ContextMenuPopupState) => CSSProperties | undefined) No Inline styles for the underlying element.
align Align No Alignment of the component.
alignOffset number | OffsetFunction No Additional offset along the alignment axis in pixels.
side Side No Side on which the popup or panel appears.
sideOffset number | OffsetFunction No Distance between the anchor and the popup in pixels.

Also accepts native element props.

Prop Type Required Description
value any Yes Current controlled value.
onClick ((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void) No The click handler for the menu item.
disabled boolean No Disable interaction.
label string No Accessible or displayed label for the control.
id string No Element identifier.
closeOnClick boolean No Whether to close the menu when the item is clicked.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
children ReactNode No Content rendered inside the component.
className string | ((state: ContextMenuRadioItemState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuRadioItemState> No Replace the underlying element using render composition.
style CSSProperties | ((state: ContextMenuRadioItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
inset boolean No Inset the menu item to align it with neighboring items.

Also accepts native element props.

Prop Type Required Description
children ReactNode No Content rendered inside the component.
className string | ((state: ContextMenuGroupState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuGroupState> No Replace the underlying element using render composition.
style CSSProperties | ((state: ContextMenuGroupState) => CSSProperties | undefined) No Inline styles for the underlying element.

Also accepts native element props.

Prop Type Required Description
children ReactNode No Content rendered inside the component.
className string | ((state: ContextMenuGroupLabelState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuGroupLabelState> No Replace the underlying element using render composition.
style CSSProperties | ((state: ContextMenuGroupLabelState) => CSSProperties | undefined) No Inline styles for the underlying element.
inset boolean No Inset the menu item to align it with neighboring items.
Prop Type Required Description
id string Yes Element identifier.
aria-describedby string No ID of the element supplying the accessible description.
aria-invalid boolean No Indicate that the input value is invalid.
aria-label string No Accessible name for the control.
aria-labelledby string No ID of the element supplying the accessible name.
disabled boolean No Disable interaction.
required boolean No Mark the input as required.
compact boolean No Use the compact input presentation.
placeholder string Yes Placeholder shown when the input is empty.
onInterrupt (() => void | boolean) No Handle an interruption request from the editor.
onHistory ((direction: "older" | "newer", editor: Editor) => boolean) No Handle navigation through older or newer drafts.
autocomplete ComposeAutocompleteProvider[] No Autocomplete providers for the prompt editor.

Also accepts native element props.

Prop Type Required Description
className string No Additional CSS classes for the underlying element.
children ReactNode No Content rendered inside the component.
align "inline-end" | "inline-start" | "block-start" | "block-end" | null No Alignment of the component.
Prop Type Required Description
className string No Additional CSS classes for the underlying element.
label string No Accessible or displayed label for the control. Default: "Send message".
children ReactNode No Content rendered inside the component.

Also accepts native element props.

Prop Type Required Description
className string No Additional CSS classes for the underlying element.
children ReactNode No Content rendered inside the component.
orientation "horizontal" | "vertical" | null No Orientation of the component.

Also accepts native element props.

Prop Type Required Description
orientation Orientation No Orientation of the component. Default: "vertical".
children ReactNode No Content rendered inside the component.
className string | ((state: SeparatorState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SeparatorState> No Replace the underlying element using render composition.
style CSSProperties | ((state: SeparatorState) => CSSProperties | undefined) No Inline styles for the underlying element.
Prop Type Required Description
defaultOpen boolean No Whether the menu is initially open.
loopFocus boolean No Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.
highlightItemOnHover boolean No Whether moving the pointer over items should highlight them.
modal boolean No Determines if the menu enters a modal state when open. - true: user interaction is limited to the menu: document page scroll is locked and pointer interactions on outside elements are disabled. - false: user interaction with the rest of the document is allowed.
onOpenChange ((open: boolean, eventDetails: MenuRoot.ChangeEventDetails) => void) No Event handler called when the menu is opened or closed.
onOpenChangeComplete ((open: boolean) => void) No Event handler called after any animations complete when the menu is opened or closed.
onItemHighlighted ((highlightedItem: HTMLElement | undefined, eventDetails: MenuRoot.HighlightEventDetails) => void) No Callback fired when an item is highlighted or unhighlighted.
open boolean No Controlled open state.
orientation MenuRootOrientation No Orientation of the component.
disabled boolean No Whether the component should ignore user interaction. Default: false.
closeParentOnEsc boolean No When in a submenu, determines whether pressing the Escape key closes the entire menu, or only the current child menu.
actionsRef RefObject<MenuRootActions | null> No A ref to imperative actions. - unmount: Ends the closing phase of the menu after an externally controlled closing animation finishes.
triggerId string | null No ID of the trigger that the menu is associated with.
defaultTriggerId string | null No ID of the trigger that the menu is associated with.
handle Handle<unknown> No A handle to associate the menu with a trigger.
children ReactNode | PayloadChildRenderFunction<unknown> No Content rendered inside the component.

Also accepts native element props.

Prop Type Required Description
children ReactNode No Content rendered inside the component.
disabled boolean No Disable interaction.
handle Handle<unknown> No A handle to associate the trigger with a menu.
payload unknown No A payload to pass to the menu when it is opened.
delay number No How long to wait before the menu may be opened on hover.
closeDelay number No How long to wait before closing the menu that was opened on hover.
openOnHover boolean No Open the hint when the trigger is hovered.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
className string | ((state: MenuTriggerState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, MenuTriggerState> No Replace the underlying element using render composition.
style CSSProperties | ((state: MenuTriggerState) => CSSProperties | undefined) No Inline styles for the underlying element.

Also accepts native element props.

Prop Type Required Description
children ReactNode No Content rendered inside the component.
id string No Element identifier.
finalFocus boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) No Determines the element to focus when the menu is closed.
className string | ((state: ContextMenuPopupState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuPopupState> No Replace the underlying element using render composition.
style CSSProperties | ((state: ContextMenuPopupState) => CSSProperties | undefined) No Inline styles for the underlying element.
align Align No Alignment of the component.
alignOffset number | OffsetFunction No Additional offset along the alignment axis in pixels.
side Side No Side on which the popup or panel appears.
sideOffset number | OffsetFunction No Distance between the anchor and the popup in pixels.

Also accepts native element props.

Prop Type Required Description
onClick ((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void) No The click handler for the menu item.
disabled boolean No Disable interaction.
label string No Accessible or displayed label for the control.
id string No Element identifier.
closeOnClick boolean No Whether to close the menu when the item is clicked.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
children ReactNode No Content rendered inside the component.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
inset boolean No Inset the menu item to align it with neighboring items.
variant "default" | "destructive" No Appearance variant.

Also accepts native element props.

Prop Type Required Description
style CSSProperties | ((state: ButtonState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ButtonState) => string | undefined) No Additional CSS classes for the underlying element.
variant "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null No Appearance variant.
size "sm" | "xs" | "icon-xs" | "icon-sm" | null No Size variant.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ButtonState> No Replace the underlying element using render composition.
type "button" | "submit" | "reset" No File MIME type.
focusableWhenDisabled boolean No Whether the button should be focusable when disabled.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
label string No Accessible or displayed label for the control. Default: "Stop response".
Prop Type Required Description
status AudioRecordingStatus Yes Current operation status.
level RefObject<number> No Ref containing the current audio level.
onStart () => void Yes Start recording.
onStop () => void Yes Stop recording.
disabled boolean No Disable interaction. Default: false.
processingLabel string No Label shown while recorded audio is processing. Default: "Processing…".
Prop Type Required Description
error string | null No Error text to display.
Prop Type Required Description
onFiles (files: File[]) => void Yes Receive files selected, pasted, or dropped into the component.
children ReactNode Yes Content rendered inside the component.
Prop Type Required Description
capture "user" | "environment" No Request a front or rear camera from supported file pickers.

Also accepts native element props.

Prop Type Required Description
label string No Accessible or displayed label for the control.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
variant "default" | "destructive" No Appearance variant.
id string No Element identifier.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
disabled boolean No Disable interaction.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
closeOnClick boolean No Whether to close the menu when the item is clicked.
inset boolean No Inset the menu item to align it with neighboring items.
multiple boolean No Allow selecting multiple files.

Also accepts native element props.

Prop Type Required Description
label string No Accessible or displayed label for the control.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
variant "default" | "destructive" No Appearance variant.
id string No Element identifier.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
disabled boolean No Disable interaction.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
closeOnClick boolean No Whether to close the menu when the item is clicked.
inset boolean No Inset the menu item to align it with neighboring items.
multiple boolean No Allow selecting multiple files.

Also accepts native element props.

Prop Type Required Description
label string No Accessible or displayed label for the control.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
variant "default" | "destructive" No Appearance variant.
id string No Element identifier.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
disabled boolean No Disable interaction.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
closeOnClick boolean No Whether to close the menu when the item is clicked.
inset boolean No Inset the menu item to align it with neighboring items.
multiple boolean No Allow selecting multiple files.

Also accepts native element props.

Prop Type Required Description
label string No Accessible or displayed label for the control.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
variant "default" | "destructive" No Appearance variant.
id string No Element identifier.
children ReactNode No Content rendered inside the component.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
disabled boolean No Disable interaction. Default: false.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
closeOnClick boolean No Whether to close the menu when the item is clicked.
inset boolean No Inset the menu item to align it with neighboring items.
accept string Yes File-picker accept filter, such as image/* or .pdf.
multiple boolean No Allow selecting multiple files. Default: true.
capture "user" | "environment" No Request a front or rear camera from supported file pickers.

Also accepts native element props.

Prop Type Required Description
label string No Accessible or displayed label for the control.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
variant "default" | "destructive" No Appearance variant.
id string No Element identifier.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
disabled boolean No Disable interaction.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
closeOnClick boolean No Whether to close the menu when the item is clicked.
inset boolean No Inset the menu item to align it with neighboring items.
capture "user" | "environment" No Request a front or rear camera from supported file pickers.
multiple boolean No Allow selecting multiple files.

Also accepts native element props.

Prop Type Required Description
label string No Accessible or displayed label for the control.
style CSSProperties | ((state: ContextMenuItemState) => CSSProperties | undefined) No Inline styles for the underlying element.
className string | ((state: ContextMenuItemState) => string | undefined) No Additional CSS classes for the underlying element.
variant "default" | "destructive" No Appearance variant.
id string No Element identifier.
render ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ContextMenuItemState> No Replace the underlying element using render composition.
disabled boolean No Disable interaction.
nativeButton boolean No Whether the component renders a native <button> element when replacing it via the render prop.
closeOnClick boolean No Whether to close the menu when the item is clicked.
inset boolean No Inset the menu item to align it with neighboring items.
capture "user" | "environment" No Request a front or rear camera from supported file pickers.
multiple boolean No Allow selecting multiple files.