ActionBar

Action

메시지에 붙는 복사·재생성·피드백 액션 모음.

Usage

어시스턴트 메시지에 복사·재생성·피드백 같은 재사용 액션 버튼을 제공할 때 사용한다.

import

import

import { ActionBar } from '@mildang/design-system/unofficial/Chat';

ActionBar 하나만 가져오면 ActionBar.Copy · ActionBar.Reload · ActionBar.Edit · ActionBar.Speak · ActionBar.StopSpeaking · ActionBar.FeedbackPositive · ActionBar.FeedbackNegative · ActionBar.More 를 그 아래에서 쓸 수 있다.

예제를 복사해 쓸 때 필요한 준비

@mildang/icons 를 따로 설치한다. DS 패키지에 아이콘 컴포넌트가 포함되지 않는다.

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

외부 패키지를 따로 설치한다. DS 의 전이 의존성에 기대지 않는다.

Anatomy

tsx

import { ActionBar } from '@mildang/design-system/unofficial/Chat';

export default function Example() {
  return (
    <ActionBar.Copy />
    <ActionBar.Reload />
    <ActionBar.Edit />
    <ActionBar.Speak />
    <ActionBar.StopSpeaking />
    <ActionBar.FeedbackPositive />
    <ActionBar.FeedbackNegative />
    <ActionBar.More />
  );
}

부품

필수 여부

반복

위치

ActionBar.Copy

선택

ActionBar.Reload

선택

ActionBar.Edit

선택

ActionBar.Speak

조건부

런타임에 SpeechSynthesisAdapter가 있어야 동작한다.

ActionBar.StopSpeaking

조건부

런타임에 SpeechSynthesisAdapter가 있어야 동작한다.

ActionBar.FeedbackPositive

선택

ActionBar.FeedbackNegative

선택

ActionBar.More

선택

  • 모든 버튼은 같은 위계와 크기(tertiary, xs)를 공유하며 아이콘과 aria-label만 교체할 수 있다.
  • ActionBar.More는 자체 Root/Trigger/Content/Item/Separator 슬롯으로 추가 구성할 수 있다.
  • 메시지 컨텍스트가 필요하므로 ThreadPrimitive.Messages 안에서 렌더한다.

API Reference

ActionBar Props

Prop

Type

Default

asChild

boolean

지정 안 함

autohide

"always" | "never" | "not-last"

never

autohideFloat

"always" | "never" | "single-branch"

never

hideWhenRunning

boolean

false

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.Copy

메시지 내용을 클립보드로 복사하는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

copiedDuration

number

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.Reload

어시스턴트 응답을 다시 생성하는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.Edit

메시지를 편집 모드로 전환하는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.Speak

메시지를 음성으로 읽어주는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.StopSpeaking

진행 중인 음성 읽기를 멈추는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.FeedbackPositive

응답에 긍정 피드백을 남기는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.FeedbackNegative

응답에 부정 피드백을 남기는 버튼이다.

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

icon

ReactNode

지정 안 함

render

import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>

지정 안 함

ActionBar.More

자주 쓰지 않는 액션을 접어 두는 더보기 메뉴다.

Prop

Type

Default

children

ReactNode

지정 안 함

contentProps

ActionBarMoreContentProps

지정 안 함

triggerProps

ActionBarMoreTriggerProps

지정 안 함

같은 패밀리

@mildang/design-system/unofficial/Chat 에서 같이 내보내는 컴포넌트다.

예제

기본 사용

어시스턴트 메시지에 기본 액션 7종을 붙인 예시다.

코드

// ActionBarDemo.example.tsx
import { css } from "@mildang/styled-system/css";
import { ThreadPrimitive } from "@assistant-ui/react";
import { ActionBar } from "@mildang/design-system/unofficial/Chat";

// ../../examples/mockRuntime.tsx
import {
  AssistantRuntimeProvider,
  useLocalRuntime,
  useRemoteThreadListRuntime
} from "@assistant-ui/react";
import { useState } from "react";
var mockAdapter = {
  async run() {
    return {
      content: [{ type: "text", text: "안녕하세요! 무엇을 도와드릴까요? (mock 응답)" }]
    };
  }
};
var sampleMessages = [
  { role: "user", content: "밀당 채팅 컴포넌트 잘 붙었어?" },
  {
    role: "assistant",
    content: "네! assistant-ui 프리미티브를 Panda CSS 슬롯 레시피로 스타일링했습니다. Thread / Composer / Message 3종이 렌더됩니다."
  }
];
function MockRuntimeProvider({
  children,
  initialMessages
}) {
  const runtime = useLocalRuntime(mockAdapter, { initialMessages });
  return <AssistantRuntimeProvider runtime={runtime}>{children}</AssistantRuntimeProvider>;
}

// ActionBarDemo.example.tsx
var AssistantMessage = () => <div className={css({ display: "flex", flexDirection: "column", gap: "8", paddingY: "8" })}>
    <ActionBar>
      <ActionBar.Copy />
      <ActionBar.Reload />
      <ActionBar.Speak />
      <ActionBar.StopSpeaking />
      <ActionBar.FeedbackPositive />
      <ActionBar.FeedbackNegative />
    </ActionBar>
  </div>;
var UserMessage = () => <div className={css({ display: "flex", justifyContent: "flex-end", paddingY: "8" })}>
    <ActionBar autohide="never">
      <ActionBar.Edit />
      <ActionBar.Copy />
    </ActionBar>
  </div>;
var wrapper = css({ padding: "16", display: "flex", flexDirection: "column" });
var ActionBarDemoExample = () => <MockRuntimeProvider initialMessages={sampleMessages}>
    <div className={wrapper}>
      <ThreadPrimitive.Root>
        <ThreadPrimitive.Messages components={{ UserMessage, AssistantMessage }} />
      </ThreadPrimitive.Root>
    </div>
  </MockRuntimeProvider>;
var ActionBarDemo_example_default = ActionBarDemoExample;
export {
  ActionBarDemo_example_default as default
};

더보기 메뉴

자주 쓰지 않는 액션을 More 메뉴로 접어 둔 예시다.

코드

// ActionBarMore.example.tsx
import { css } from "@mildang/styled-system/css";
import { ThreadPrimitive } from "@assistant-ui/react";
import { ActionBar } from "@mildang/design-system/unofficial/Chat";

// ../../examples/mockRuntime.tsx
import {
  AssistantRuntimeProvider,
  useLocalRuntime,
  useRemoteThreadListRuntime
} from "@assistant-ui/react";
import { useState } from "react";
var mockAdapter = {
  async run() {
    return {
      content: [{ type: "text", text: "안녕하세요! 무엇을 도와드릴까요? (mock 응답)" }]
    };
  }
};
var sampleMessages = [
  { role: "user", content: "밀당 채팅 컴포넌트 잘 붙었어?" },
  {
    role: "assistant",
    content: "네! assistant-ui 프리미티브를 Panda CSS 슬롯 레시피로 스타일링했습니다. Thread / Composer / Message 3종이 렌더됩니다."
  }
];
function MockRuntimeProvider({
  children,
  initialMessages
}) {
  const runtime = useLocalRuntime(mockAdapter, { initialMessages });
  return <AssistantRuntimeProvider runtime={runtime}>{children}</AssistantRuntimeProvider>;
}

// ActionBarMore.example.tsx
var UserMessage = () => <div className={css({ display: "flex", justifyContent: "flex-end", paddingY: "8" })}>
    <ActionBar autohide="never">
      <ActionBar.Edit />
      <ActionBar.Copy />
    </ActionBar>
  </div>;
var AssistantMessageWithMore = () => <div className={css({ paddingY: "8" })}>
    <ActionBar>
      <ActionBar.More />
    </ActionBar>
  </div>;
var wrapper = css({ padding: "16", display: "flex", flexDirection: "column" });
var ActionBarMoreExample = () => <MockRuntimeProvider initialMessages={sampleMessages}>
    <div className={wrapper}>
      <ThreadPrimitive.Root>
        <ThreadPrimitive.Messages
  components={{ UserMessage, AssistantMessage: AssistantMessageWithMore }}
/>
      </ThreadPrimitive.Root>
    </div>
  </MockRuntimeProvider>;
var ActionBarMore_example_default = ActionBarMoreExample;
export {
  ActionBarMore_example_default as default
};

더보기 고급 조립

More의 Root/Trigger/Content/Item/Separator 슬롯을 직접 조립한 예시다.

코드

// ActionBarMoreAdvanced.example.tsx
import { css } from "@mildang/styled-system/css";
import { ThreadPrimitive } from "@assistant-ui/react";
import EditIcon from "@mildang/icons/react/edit";
import { ActionBar } from "@mildang/design-system/unofficial/Chat";

// ../../examples/mockRuntime.tsx
import {
  AssistantRuntimeProvider,
  useLocalRuntime,
  useRemoteThreadListRuntime
} from "@assistant-ui/react";
import { useState } from "react";
var mockAdapter = {
  async run() {
    return {
      content: [{ type: "text", text: "안녕하세요! 무엇을 도와드릴까요? (mock 응답)" }]
    };
  }
};
var sampleMessages = [
  { role: "user", content: "밀당 채팅 컴포넌트 잘 붙었어?" },
  {
    role: "assistant",
    content: "네! assistant-ui 프리미티브를 Panda CSS 슬롯 레시피로 스타일링했습니다. Thread / Composer / Message 3종이 렌더됩니다."
  }
];
function MockRuntimeProvider({
  children,
  initialMessages
}) {
  const runtime = useLocalRuntime(mockAdapter, { initialMessages });
  return <AssistantRuntimeProvider runtime={runtime}>{children}</AssistantRuntimeProvider>;
}

// ActionBarMoreAdvanced.example.tsx
var UserMessage = () => <div className={css({ display: "flex", justifyContent: "flex-end", paddingY: "8" })}>
    <ActionBar autohide="never">
      <ActionBar.Edit />
      <ActionBar.Copy />
    </ActionBar>
  </div>;
var AssistantMessageWithCustomMore = () => <div className={css({ paddingY: "8" })}>
    <ActionBar>
      <ActionBar.More.Root>
        <ActionBar.More.Trigger aria-label="추가 작업" />
        <ActionBar.More.Content align="end">
          <ActionBar.More.Item icon={<EditIcon />}>직접 수정</ActionBar.More.Item>
          <ActionBar.More.Separator />
          <ActionBar.More.Item>사용자 정의 작업</ActionBar.More.Item>
        </ActionBar.More.Content>
      </ActionBar.More.Root>
    </ActionBar>
  </div>;
var wrapper = css({ padding: "16", display: "flex", flexDirection: "column" });
var ActionBarMoreAdvancedExample = () => <MockRuntimeProvider initialMessages={sampleMessages}>
    <div className={wrapper}>
      <ThreadPrimitive.Root>
        <ThreadPrimitive.Messages
  components={{ UserMessage, AssistantMessage: AssistantMessageWithCustomMore }}
/>
      </ThreadPrimitive.Root>
    </div>
  </MockRuntimeProvider>;
var ActionBarMoreAdvanced_example_default = ActionBarMoreAdvancedExample;
export {
  ActionBarMoreAdvanced_example_default as default
};