# ChatTool

> An expandable section that indicates whether an AI tool has been called and its execution state.

## Usage

The ChatTool component renders a collapsible block that displays AI tool invocation status, such as "Searching components" or "Reading documentation". When a default slot is provided, it becomes collapsible to reveal tool output.

```vue [ChatToolExample.vue]
<script setup lang="ts">
import TerminalIcon from '@bitrix24/b24icons-vue/file-type/TerminalIcon'

const streaming = ref(true)
const result = ref(`$ pnpm run lint

> eslint .

✔ No lint errors found.
`)

let timer: ReturnType<typeof setTimeout> | undefined

onMounted(() => {
  timer = setTimeout(() => {
    streaming.value = false
  }, 5000)
})

onUnmounted(() => {
  clearTimeout(timer)
})
</script>

<template>
  <B24ChatTool
    :text="streaming ? 'Running lint checks' : 'Lint checks completed'"
    suffix="cd, pnpm run"
    :streaming="streaming"
    :icon="TerminalIcon"
    variant="card"
    chevron="leading"
    class="w-80"
  >
    <pre language="bash" v-text="result" />
  </B24ChatTool>
</template>
```

### Text

Use the `text` prop to set the tool status text.

```vue
<template>
  <B24ChatTool text="Searched components" />
</template>
```

### Suffix

Use the `suffix` prop to display secondary text after the main label.

```vue
<template>
  <B24ChatTool text="Reading component" suffix="Button" />
</template>
```

### Streaming

Use the `streaming` prop to indicate the tool is actively running. The text displays a shimmer animation.

```vue
<template>
  <B24ChatTool streaming text="Searching components..." />
</template>
```

> [!TIP]
> Use the `isToolStreaming` utility from `@bitrix24/b24ui-nuxt/utils/ai` to determine if a tool part is still running.

### Shimmer

When streaming, the trigger label uses the [`ChatShimmer`](https://bitrix24.github.io/b24ui/raw/docs/components/chat-shimmer.md) component. Use the `shimmer` prop to customize its `duration` and `spread`.

```vue
<template>
  <B24ChatTool streaming text="Searching components..." :shimmer="{duration:2,spread:2}" />
</template>
```

### Icon

Use the `icon` prop to display an [Icon](https://bitrix24.github.io/b24icons/icons/) component next to the trigger.

```vue
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>

<template>
  <B24ChatTool :icon="RocketIcon" text="Searched components" />
</template>
```

### Loading

Use the `loading` prop to show a loading indicator. Use the `loading-icon` prop to customize the loading icon.

```vue
<template>
  <B24ChatTool loading text="Searching components..." />
</template>
```

### Loading Icon

Use `use-clock` or `use-wait` props to show different loading icons.

Use the `loading-icon` prop to customize the loading icon.

```vue
<template>
  <B24ChatTool loading text="Searching components..." />
</template>
```

```vue
<template>
  <B24ChatTool loading use-wait text="Searching components..." />
</template>
```

### Chevron

Use the `chevron` prop to change the position of the chevron icon.

> [!NOTE]
> When `chevron` is set to `leading` with an `icon`, the icon swaps with the chevron on hover and when open.

```vue
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>

<template>
  <B24ChatTool chevron="leading" :icon="RocketIcon" text="Searched components">
Tool output content
</B24ChatTool>
</template>
```

### Chevron Icon

Use the `chevron-icon` prop to customize the chevron [Icon](https://bitrix24.github.io/b24icons/icons/).

```vue
<template>
  <B24ChatTool chevron-icon="RocketIcon" text="Searched components">
Tool output content
</B24ChatTool>
</template>
```

### Variant

Use the `variant` prop to change the visual style. Defaults to `inline`.

```vue
<script setup lang="ts">
import RocketIcon from '@bitrix24/b24icons-vue/main/RocketIcon'
</script>

<template>
  <B24ChatTool variant="card" text="Searched components" :icon="RocketIcon" chevron="trailing">
Tool output content
</B24ChatTool>
</template>
```

## Examples

> [!TIP]
> See: /docs/components/chat/
> Check the Chat overview page for installation instructions, server setup and usage examples.

## API

### Props

```ts
/**
 * Props for the ChatTool component
 */
interface ChatToolProps {
  /**
   * The text content to display.
   */
  text?: string | undefined;
  /**
   * The suffix text displayed after the main text.
   */
  suffix?: string | undefined;
  /**
   * The icon displayed next to the trigger.
   */
  icon?: IconComponent | undefined;
  /**
   * Whether the tool is in a loading state.
   * @default "false"
   */
  loading?: boolean | undefined;
  /**
   * Shows LoaderWaitIcon in loading mode
   */
  useWait?: boolean | undefined;
  /**
   * Shows LoaderClockIcon icon in loading mode
   */
  useClock?: boolean | undefined;
  /**
   * The icon displayed when loading.
   */
  loadingIcon?: IconComponent | undefined;
  /**
   * Whether the tool content is currently streaming.
   * @default "false"
   */
  streaming?: boolean | undefined;
  /**
   * The visual variant of the tool display.
   * @default "\"inline\""
   */
  variant?: "card" | "inline" | undefined;
  /**
   * The position of the chevron icon.
   * @default "\"trailing\""
   */
  chevron?: "trailing" | "leading" | undefined;
  /**
   * The icon displayed as the chevron.
   */
  chevronIcon?: IconComponent | undefined;
  /**
   * Customize the [`ChatShimmer`](https://bitrix24.github.io/b24ui/docs/components/chat-shimmer/) component when streaming.
   */
  shimmer?: Partial<Omit<ChatShimmerProps, "text">> | undefined;
  b24ui?: { root?: ClassNameValue; trigger?: ClassNameValue; leading?: ClassNameValue; leadingIcon?: ClassNameValue; chevronIcon?: ClassNameValue; label?: ClassNameValue; suffix?: ClassNameValue; trailingIcon?: ClassNameValue; content?: ClassNameValue; body?: ClassNameValue; } | undefined;
  /**
   * When `true`, prevents the user from interacting with the collapsible.
   */
  disabled?: boolean | undefined;
  /**
   * The controlled open state of the collapsible. Can be binded with `v-model`.
   * @default "undefined"
   */
  open?: boolean | undefined;
  /**
   * The open state of the collapsible when it is initially rendered. <br> Use when you do not need to control its open state.
   */
  defaultOpen?: boolean | undefined;
  /**
   * When `true`, the element will be unmounted on closed state.
   * @default "false"
   */
  unmountOnHide?: boolean | undefined;
}
```

### Slots

```ts
/**
 * Slots for the ChatTool component
 */
interface ChatToolSlots {
  default(): any;
}
```

### Emits

```ts
/**
 * Emitted events for the ChatTool component
 */
interface ChatToolEmits {
  update:open: (payload: [value: boolean]) => void;
}
```

## Theme

```ts [app.config.ts]
export default defineAppConfig({
  b24ui: {
    chatTool: {
      slots: {
        root: '',
        trigger: 'group w-full min-w-0 flex items-center gap-1.5 text-muted text-sm disabled:cursor-default disabled:hover:text-muted hover:text-default focus-visible:outline-offset-2 focus-visible:outline-primary transition-colors',
        leading: 'relative shrink-0 size-5',
        leadingIcon: 'shrink-0 size-5',
        chevronIcon: 'shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
        label: 'truncate',
        suffix: 'text-dimmed ms-1',
        trailingIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
        content: 'motion-safe:data-[state=open]:animate-[collapsible-down_200ms_ease-out] motion-safe:data-[state=closed]:animate-[collapsible-up_200ms_ease-out] overflow-hidden',
        body: 'text-sm text-dimmed whitespace-pre-wrap'
      },
      variants: {
        variant: {
          inline: {
            body: 'pt-2'
          },
          card: {
            root: 'light:[--leftmenu-group-stroke:var(--ui-color-base-30)] rounded-md ring ring-(--leftmenu-group-stroke) overflow-hidden',
            trigger: 'px-2 py-1',
            trailingIcon: 'ms-auto',
            body: 'border-t border-(--leftmenu-group-stroke) p-2 max-h-[200px] overflow-y-auto'
          }
        },
        chevron: {
          leading: {
            leadingIcon: 'group-hover:opacity-0'
          },
          trailing: ''
        },
        useWait: {
          true: ''
        },
        useClock: {
          true: ''
        },
        loading: {
          true: {}
        },
        alone: {
          false: {
            leadingIcon: 'absolute inset-0 group-data-[state=open]:opacity-0 transition-opacity duration-200',
            chevronIcon: 'absolute inset-0 opacity-0 group-hover:opacity-100 group-data-[state=open]:opacity-100 transition-[rotate,opacity] duration-200'
          }
        }
      },
      compoundVariants: [
        {
          loading: true,
          useWait: false,
          useClock: false,
          class: {
            leadingIcon: 'm-0.5 size-4 animate-spin stroke-2'
          }
        }
      ],
      defaultVariants: {
        variant: 'inline'
      }
    }
  }
})
```