# ChatReasoning

> An expandable panel that shows the AI's internal reasoning steps.

## Usage

The ChatReasoning component renders a collapsible block that displays AI reasoning or thinking content. It auto-opens during streaming and auto-closes after.

```vue [ChatReasoningExample.vue]
<script setup lang="ts">
const streaming = ref(false)
const text = ref('')

async function simulateStreaming() {
  streaming.value = true
  text.value = ''

  const content = 'The user is asking about Vue components. I should explain the Composition API pattern and how it relates to their question about reactive state management. Let me think about the best way to structure this response.\n\nFirst, I need to consider the key differences between the Options API and Composition API. The Composition API was introduced in Vue 3 to address limitations of the Options API when building large-scale applications.\n\nFor reactive state management specifically, the Composition API offers ref() for primitive values and reactive() for objects.'

  for (const char of content) {
    text.value += char
    await new Promise(resolve => setTimeout(resolve, 10))
  }

  streaming.value = false
}

onMounted(simulateStreaming)
</script>

<template>
  <B24ChatReasoning
    :text="text"
    :streaming="streaming"
    class="w-60"
  />
</template>
```

> [!NOTE]
> See: /docs/composables/use-scroll-shadow/
> The body content uses the `useScrollShadow` composable to apply fade shadows when overflowing.

### Text

Use the `text` prop to set the reasoning content. The text is displayed inside the collapsible body.

```vue
<template>
  <B24ChatReasoning text="The user is asking about Vue components..." />
</template>
```

### Streaming

Use the `streaming` prop to indicate active reasoning. The component auto-opens when streaming starts and auto-closes when it ends.

```vue
<template>
  <B24ChatReasoning streaming text="The user is asking about Vue components..." />
</template>
```

> [!TIP]
> Use the `isPartStreaming` utility from `@bitrix24/b24ui-nuxt/utils/ai` to determine if a reasoning part is currently being streamed.

### 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>
  <B24ChatReasoning streaming text="The user is asking about Vue 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>
  <B24ChatReasoning :icon="RocketIcon" text="The user is asking about Vue 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>
  <B24ChatReasoning chevron="leading" :icon="RocketIcon" text="The user is asking about Vue components..." />
</template>
```

### Chevron Icon

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

```vue
<template>
  <B24ChatReasoning chevron-icon="RocketIcon" text="The user is asking about Vue components..." />
</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 ChatReasoning component
 */
interface ChatReasoningProps {
  /**
   * The reasoning text content to display.
   */
  text?: string | undefined;
  /**
   * Whether the reasoning content is currently streaming.
   * @default "false"
   */
  streaming?: boolean | undefined;
  /**
   * The duration in seconds that the AI spent reasoning.
   * If not provided, it will be calculated automatically based on streaming time.
   */
  duration?: number | undefined;
  /**
   * The icon displayed next to the trigger.
   */
  icon?: IconComponent | undefined;
  /**
   * The position of the chevron icon.
   * @default "\"trailing\""
   */
  chevron?: "trailing" | "leading" | undefined;
  /**
   * The icon displayed as the chevron.
   */
  chevronIcon?: IconComponent | undefined;
  /**
   * The delay in milliseconds before auto-closing when streaming ends.
   * Set to `0` to disable auto-close.
   * @default "500"
   */
  autoCloseDelay?: number | 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; 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 ChatReasoning component
 */
interface ChatReasoningSlots {
  default(): any;
}
```

### Emits

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

## Theme

```ts [app.config.ts]
export default defineAppConfig({
  b24ui: {
    chatReasoning: {
      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 size-5 shrink-0',
        leadingIcon: 'size-5 shrink-0',
        chevronIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
        label: 'truncate',
        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: 'max-h-[200px] pt-2 overflow-y-auto text-sm text-dimmed whitespace-pre-wrap'
      },
      variants: {
        chevron: {
          leading: {
            leadingIcon: 'group-hover:opacity-0'
          },
          trailing: ''
        },
        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'
          }
        }
      }
    }
  }
})
```