# Chat Tokenized Text

## Usage

Use ChatTokenizedText inside a chat message when stored plain text contains serialized token values that should be projected as inline badges or caller-rendered token content. Unmatched text is preserved exactly and empty token values are ignored so rendering always finishes.

The text goes in the default slot. The `text` prop does the same job when a string is easier to pass, and it wins when both are set. Every token `value` is matched literally and costs one pass over the string, so the same token objects a composer trigger returns can be reused here. A structured token renders a `Badge`; a token with its own `render` function renders that markup instead and stays caller-owned.

```vue
<script setup lang="ts">
import { ChatMessage, ChatMessageBubble, ChatTokenizedText } from '@astryx-vue/core/Chat'

const tokens = [
  { value: '@Cindy', label: '@Cindy', variant: 'blue' as const },
]
</script>

<template>
  <ChatMessage sender="user">
    <ChatMessageBubble>
      <ChatTokenizedText :tokens="tokens">
        Assign @Cindy as a reviewer.
      </ChatTokenizedText>
    </ChatMessageBubble>
  </ChatMessage>
</template>
```

### Anatomy

- **Tokenized text**: The inline root that preserves unmatched text and carries the chat-tokenized-text theme target.
- **Rendered token**: Inline token content rendered by `Badge` for structured tokens or by the caller for custom tokens.

## Best practices

| Guidance | Practices |
| --- | --- |
| Do | Reuse the same token definitions for composer insertion and message rendering so serialized values and visible labels stay aligned. |
| Do | Use non-empty, stable serialized values so every definition identifies real message text. |
| Don't | Use token labels as a substitute for the surrounding message text; the complete message must remain understandable in reading order. |
| Don't | Put component-owned interaction or accessibility behavior inside a custom token renderer; custom token content remains caller owned. |

## Examples

Common configurations, variations, and states.

### Basic

A message with @mention tokens. Each matching pattern is replaced with its display name badge.

```vue
<script setup lang="ts">
import type { ChatComposerToken } from '@astryx-vue/core/Chat'
import { ChatMessage, ChatMessageBubble, ChatMessageList, ChatTokenizedText } from '@astryx-vue/core/Chat'

const tokens: ChatComposerToken[] = [
  { value: '@Cindy', label: '@Cindy' },
  { value: '@Alex', label: '@Alex' },
]
</script>

<template>
  <ChatMessageList>
    <ChatMessage sender="user">
      <ChatMessageBubble>
        <ChatTokenizedText text="Assign @Cindy and @Alex as reviewers." :tokens="tokens" />
      </ChatMessageBubble>
    </ChatMessage>
  </ChatMessageList>
</template>
```

### Colors

Tokens with different color variants to distinguish mentions, bugs, and features. Use variant colors to create a visual taxonomy: blue for people, red for bugs, green for features.

```vue
<script setup lang="ts">
import type { ChatComposerToken } from '@astryx-vue/core/Chat'
import { ChatMessage, ChatMessageBubble, ChatMessageList, ChatTokenizedText } from '@astryx-vue/core/Chat'

const tokens: ChatComposerToken[] = [
  { value: '@Cindy', label: '@Cindy', variant: 'blue' },
  { value: '#bug', label: '#bug', variant: 'red' },
  { value: '#feature', label: '#feature', variant: 'green' },
]
</script>

<template>
  <ChatMessageList>
    <ChatMessage sender="user">
      <ChatMessageBubble>
        <ChatTokenizedText text="@Cindy filed #bug and #feature for the sprint" :tokens="tokens" />
      </ChatMessageBubble>
    </ChatMessage>
  </ChatMessageList>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `tokens` | `ChatComposerToken[]` | — | Token definitions using the same type as the composer input. Each non-empty `value` is matched literally. A structured token renders a `Badge`, a token with `render` renders that markup. |
| `text` | `string` | — | Same as the default slot: message text that may contain serialized token values. Anything that does not match a token stays as it is. The prop wins when both it and the default slot are set. |

## Slots

- `default`: the message text. Plain text only, because token content comes from the `tokens` prop. Everything that does not match a token is rendered as-is.
