v2.5.3

ChatTool New

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.

<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>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
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.

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

Suffix

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

<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.

<template>
  <B24ChatTool streaming text="Searching components..." />
</template>
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 component. Use the shimmer prop to customize its duration and spread.

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

Icon

Use the icon prop to display an Icon component next to the trigger.

<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.

<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.

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

Chevron

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

When chevron is set to leading with an icon, the icon swaps with the chevron on hover and when open.
<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.

<template>
  <B24ChatTool chevron-icon="function render(_ctx, _cache) {
  return (_openBlock(), _createElementBlock("svg", {
    xmlns: "http://www.w3.org/2000/svg",
    fill: "none",
    viewBox: "0 0 24 24",
    "aria-hidden": "true",
    "data-slot": "icon"
  }, [
    _createElementVNode("path", {
      fill: "currentColor",
      "fill-rule": "evenodd",
      d: "M8.292 16.885c.99.828 2.158 1.267 3.415 1.153.22.572.598 1.51 1.124 2.643 2.4-1.448 2.743-3.471 2.697-4.683q.354-.353.707-.771c2.881-3.423 3.28-10.079 2.492-10.738-.788-.66-7.295.888-10.176 4.311q-.357.425-.646.837c-1.207.17-3.134.863-4.144 3.459 1.207.318 2.195.526 2.799.643.107 1.25.743 2.32 1.732 3.146m1.718-2.041a2.056 2.056 0 0 0 2.89-.252 2.04 2.04 0 0 0-.252-2.882 2.056 2.056 0 0 0-2.89.252 2.04 2.04 0 0 0 .252 2.882m5.07-4.315a1.104 1.104 0 0 1-1.552.136 1.096 1.096 0 0 1-.136-1.548 1.104 1.104 0 0 1 1.552-.135c.466.39.527 1.083.136 1.547m-5.701 7.974a5.1 5.1 0 0 1-1.75-.933 4.9 4.9 0 0 1-1.267-1.484c-.874 2.119-1.251 3.831-.984 4.045s1.968-.438 4.001-1.628",
      "clip-rule": "evenodd"
    })
  ]))
}" text="Searched components">
Tool output content
</B24ChatTool>
</template>

Variant

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

<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

Check the Chat overview page for installation instructions, server setup and usage examples.

API

Props

Prop Default Type
text string

The text content to display.

suffix string

The suffix text displayed after the main text.

iconIconComponent

The icon displayed next to the trigger.

loadingfalseboolean

Whether the tool is in a loading state.

useWaitfalseboolean

Shows LoaderWaitIcon in loading mode

useClockfalseboolean

Shows LoaderClockIcon icon in loading mode

loadingIconicons.loadingIconComponent

The icon displayed when loading.

streamingfalseboolean

Whether the tool content is currently streaming.

variant'inline' "card" | "inline"

The visual variant of the tool display.

chevron'trailing' "trailing" | "leading"

The position of the chevron icon.

chevronIconicons.chevronDownIconComponent

The icon displayed as the chevron.

shimmer Partial<Omit<ChatShimmerProps, "text">>

Customize the ChatShimmer component when streaming.

disabledboolean

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

openundefinedboolean

The controlled open state of the collapsible. Can be binded with v-model.

defaultOpenboolean

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

unmountOnHidefalseboolean

When true, the element will be unmounted on closed state.

b24ui { root?: ClassNameValue; trigger?: ClassNameValue; leading?: ClassNameValue; leadingIcon?: ClassNameValue; chevronIcon?: ClassNameValue; label?: ClassNameValue; suffix?: ClassNameValue; trailingIcon?: ClassNameValue; content?: ClassNameValue; body?: ClassNameValue; }

Slots

Slot Type
default{ open: boolean; }

Emits

Event Type
update:open[value: boolean]

Theme

https://github.com/bitrix24/b24ui/tree/main/src/theme/chat-tool.ts
export default {
  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'
  }
}