logoassistant-ui
Radix UI Primitives

ActionBarMorePrimitive

A dropdown menu for additional actions that don't fit in the main action bar.

Anatomy

import { ActionBarPrimitive, ActionBarMorePrimitive } from "@assistant-ui/react";

const MessageActions = () => (
  <ActionBarPrimitive.Root>
    <ActionBarPrimitive.Copy />
    <ActionBarPrimitive.Reload />

    <ActionBarMorePrimitive.Root>
      <ActionBarMorePrimitive.Trigger>
        <MoreHorizontalIcon />
      </ActionBarMorePrimitive.Trigger>
      <ActionBarMorePrimitive.Content>
        <ActionBarMorePrimitive.Item onSelect={() => console.log("Edit")}>
          Edit
        </ActionBarMorePrimitive.Item>
        <ActionBarMorePrimitive.Item onSelect={() => console.log("Speak")}>
          Read aloud
        </ActionBarMorePrimitive.Item>
        <ActionBarMorePrimitive.Separator />
        <ActionBarMorePrimitive.Item onSelect={() => console.log("Feedback")}>
          Submit feedback
        </ActionBarMorePrimitive.Item>
      </ActionBarMorePrimitive.Content>
    </ActionBarMorePrimitive.Root>
  </ActionBarPrimitive.Root>
);

API Reference

Root

Contains all parts of the dropdown menu.

ActionBarMorePrimitiveRootProps

defaultOpen:

boolean = false

The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state.

open?:

boolean

The controlled open state of the dropdown menu. Must be used in conjunction with onOpenChange.

onOpenChange?:

(open: boolean) => void

Event handler called when the open state of the dropdown menu changes.

modal:

boolean = true

The modality of the dropdown menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers.

dir?:

'ltr' | 'rtl'

The reading direction of the dropdown menu.

Trigger

A button that toggles the dropdown menu.

This primitive renders a <button> element unless asChild is set.

ActionBarMorePrimitiveTriggerProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

Data attributeValues
[data-state]

"open" | "closed"

[data-disabled]

Present when disabled

Content

The component that pops out when the dropdown menu is open.

This primitive renders a <div> element unless asChild is set.

ActionBarMorePrimitiveContentProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

side:

'top' | 'right' | 'bottom' | 'left' = 'bottom'

The preferred side of the trigger to render against.

sideOffset:

number = 4

The distance in pixels from the trigger.

align:

'start' | 'center' | 'end' = 'center'

The preferred alignment against the trigger.

alignOffset:

number = 0

An offset in pixels from the align option.

portalProps?:

PortalProps

Props to pass to the Portal component.

Data attributeValues
[data-state]

"open" | "closed"

[data-side]

"top" | "right" | "bottom" | "left"

[data-align]

"start" | "center" | "end"

Refer to Radix UI's Documentation for DropdownMenu.Content for more details.

Item

A menu item within the dropdown menu.

This primitive renders a <div> element unless asChild is set.

ActionBarMorePrimitiveItemProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

disabled?:

boolean

When true, prevents the user from interacting with the item.

onSelect?:

(event: Event) => void

Event handler called when the user selects an item (via mouse or keyboard). Calling event.preventDefault in this handler will prevent the dropdown menu from closing when selecting that item.

textValue?:

string

Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item.

Data attributeValues
[data-disabled]

Present when disabled

[data-highlighted]

Present when highlighted

Refer to Radix UI's Documentation for DropdownMenu.Item for more details.

Separator

A visual separator between groups of items.

This primitive renders a <div> element unless asChild is set.

ActionBarMorePrimitiveSeparatorProps

asChild:

boolean = false

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

Example Usage

Basic dropdown menu

import { ActionBarMorePrimitive } from "@assistant-ui/react";
import { MoreHorizontal, Pencil, Volume2, ThumbsUp } from "lucide-react";

const MoreActionsMenu = () => (
  <ActionBarMorePrimitive.Root>
    <ActionBarMorePrimitive.Trigger className="action-button">
      <MoreHorizontal className="size-4" />
    </ActionBarMorePrimitive.Trigger>
    <ActionBarMorePrimitive.Content className="dropdown-content">
      <ActionBarMorePrimitive.Item
        className="dropdown-item"
        onSelect={() => console.log("Edit")}
      >
        <Pencil className="size-4" />
        Edit message
      </ActionBarMorePrimitive.Item>
      <ActionBarMorePrimitive.Item
        className="dropdown-item"
        onSelect={() => console.log("Speak")}
      >
        <Volume2 className="size-4" />
        Read aloud
      </ActionBarMorePrimitive.Item>
      <ActionBarMorePrimitive.Separator className="dropdown-separator" />
      <ActionBarMorePrimitive.Item
        className="dropdown-item"
        onSelect={() => console.log("Like")}
      >
        <ThumbsUp className="size-4" />
        Good response
      </ActionBarMorePrimitive.Item>
    </ActionBarMorePrimitive.Content>
  </ActionBarMorePrimitive.Root>
);

Using with action hooks

You can combine the dropdown menu items with action hooks from ActionBarPrimitive:

import {
  ActionBarPrimitive,
  ActionBarMorePrimitive,
  useAssistantApi,
  useAssistantState,
} from "@assistant-ui/react";
import { useCallback } from "react";

const useEditAction = () => {
  const api = useAssistantApi();
  const disabled = useAssistantState(({ composer }) => composer.isEditing);
  const callback = useCallback(() => api.composer().beginEdit(), [api]);
  if (disabled) return null;
  return callback;
};

const useSpeakAction = () => {
  const api = useAssistantApi();
  return useCallback(() => api.message().speak(), [api]);
};

const MoreActionsWithHooks = () => {
  const edit = useEditAction();
  const speak = useSpeakAction();

  return (
    <ActionBarMorePrimitive.Root>
      <ActionBarMorePrimitive.Trigger>
        <MoreHorizontalIcon />
      </ActionBarMorePrimitive.Trigger>
      <ActionBarMorePrimitive.Content>
        <ActionBarMorePrimitive.Item onSelect={edit ?? undefined} disabled={!edit}>
          Edit
        </ActionBarMorePrimitive.Item>
        <ActionBarMorePrimitive.Item onSelect={speak}>
          Read aloud
        </ActionBarMorePrimitive.Item>
      </ActionBarMorePrimitive.Content>
    </ActionBarMorePrimitive.Root>
  );
};