Actions

PreviousNext

Action buttons for AI responses with tooltips.

Hello, how are you?
I am fine, thank you!
"use client"

import { useState } from "react"
import {
  CopyIcon,
  RefreshCwIcon,
  ShareIcon,
  ThumbsDownIcon,
  ThumbsUpIcon,
} from "lucide-react"

import { Action, Actions } from "@/components/ai-elements/actions"
import {
  Conversation,
  ConversationContent,
} from "@/components/ai-elements/conversation"
import {
  Message,
  MessageContent,
} from "@/components/ai-elements/message"

const messages = [
  {
    id: "1",
    from: "user" as const,
    content: "Hello, how are you?",
    avatar: "https://github.com/haydenbleasel.png",
    name: "Hayden Bleasel",
  },
  {
    id: "2",
    from: "assistant" as const,
    content: "I am fine, thank you!",
    avatar: "https://github.com/openai.png",
    name: "OpenAI",
  },
]

export function ActionsDemo() {
  const [liked, setLiked] = useState(false)
  const [disliked, setDisliked] = useState(false)

  const handleRetry = () => {
    console.log("Retry clicked")
  }

  const handleCopy = () => {
    console.log("Copy clicked")
  }

  const handleShare = () => {
    console.log("Share clicked")
  }

  const actions = [
    {
      icon: RefreshCwIcon,
      label: "Retry",
      onClick: handleRetry,
    },
    {
      icon: ThumbsUpIcon,
      label: "Like",
      onClick: () => setLiked(!liked),
    },
    {
      icon: ThumbsDownIcon,
      label: "Dislike",
      onClick: () => setDisliked(!disliked),
    },
    {
      icon: CopyIcon,
      label: "Copy",
      onClick: handleCopy,
    },
    {
      icon: ShareIcon,
      label: "Share",
      onClick: handleShare,
    },
  ]

  return (
    <Conversation className="relative w-full">
      <ConversationContent>
        {messages.map((message) => (
          <Message
            className={`flex flex-col gap-2 ${message.from === "assistant" ? "items-start" : "items-end"}`}
            from={message.from}
            key={message.id}
          >
            <MessageContent>{message.content}</MessageContent>
            {message.from === "assistant" && (
              <Actions className="mt-2">
                {actions.map((action) => (
                  <Action
                    key={action.label}
                    label={action.label}
                    onClick={action.onClick}
                    tooltip={action.label}
                  >
                    <action.icon className="size-4" />
                  </Action>
                ))}
              </Actions>
            )}
          </Message>
        ))}
      </ConversationContent>
    </Conversation>
  )
}

Installation

pnpm dlx taki-ui@latest add actions

Usage

import { Action, Actions } from "@/ai-elements/actions"
<Actions>
  <Action tooltip="Copy">
    <CopyIcon className="size-4" />
  </Action>
  <Action tooltip="Like">
    <ThumbsUpIcon className="size-4" />
  </Action>
</Actions>

Examples

With Handlers

<Actions>
  <Action tooltip="Copy" onPress={() => copyToClipboard()}>
    <CopyIcon className="size-4" />
  </Action>
  <Action tooltip="Regenerate" onPress={() => regenerate()}>
    <RefreshCwIcon className="size-4" />
  </Action>
</Actions>

Without Tooltips

<Actions>
  <Action label="Copy">
    <CopyIcon className="size-4" />
  </Action>
</Actions>

API Reference

Actions

Container for action buttons.

PropTypeDefaultDescription
classNamestring-Additional CSS classes

Action

PropTypeDefaultDescription
tooltipstring-Tooltip text (shows on hover)
labelstring-Accessibility label
variant"ghost" | "outline" | ..."ghost"Button variant
size"sm" | "default" | ..."sm"Button size