# Chat Message

## Usage

Sender context wrapper: handles avatar, name, metadata, and alignment based on sender role.

`sender` is required. It decides the alignment, and whether the avatar, name, and metadata slots are rendered at all: a `system` row is centered and ignores all three. Density comes from the surrounding `ChatMessageList` unless the row sets its own.

The name and metadata slots belong to the raw-content case. When the first child is a `ChatMessageBubble`, put the name on the bubble instead, so the name lines up with the bubble padding. The same goes for metadata on the last bubble.

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

<template>
  <ChatMessageList>
    <ChatMessage sender="user">
      <ChatMessageBubble>
        Can you review the token validation changes?
      </ChatMessageBubble>
    </ChatMessage>
    <ChatMessage sender="assistant">
      <ChatMessageBubble variant="ghost">
        Looks good — ship it.
      </ChatMessageBubble>
    </ChatMessage>
  </ChatMessageList>
</template>
```

## Examples

Common configurations, variations, and states.

### Avatar & Name

Messages with avatars and sender names. Place the name on the bubble when using bubbles, or on the message wrapper for raw content.

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

const agent = 'Agent'
</script>

<template>
  <ChatMessageList>
    <ChatMessage sender="assistant">
      <template #avatar>
        <Avatar :name="agent" size="md" />
      </template>
      <ChatMessageBubble :name="agent">
        {{ 'I reviewed the pull request. The changes look solid — clean code and good test coverage.' }}
        <template #metadata>
          <ChatMessageMetadata timestamp="10:15 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
    <ChatMessage sender="user">
      <ChatMessageBubble>
        {{ 'Thanks! Merging it now.' }}
        <template #metadata>
          <ChatMessageMetadata status="read" timestamp="10:16 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
    <ChatMessage sender="assistant">
      <template #avatar>
        <Avatar :name="agent" size="md" />
      </template>
      <ChatMessageBubble :name="agent">
        {{ 'I can run the deployment pipeline once it lands. Just let me know.' }}
        <template #metadata>
          <ChatMessageMetadata timestamp="10:17 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
  </ChatMessageList>
</template>
```

### Ghost

Ghost variant for messages without visible bubble boundaries. Keeps padding for alignment but renders a transparent background, useful for AI-style responses.

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

<template>
  <ChatMessageList>
    <ChatMessage sender="assistant">
      <ChatMessageBubble variant="ghost">
        {{ 'Here is an analysis of your production metrics from last week. Traffic peaked at 12,400 requests per second on Wednesday, with a p99 latency of 45ms. Error rate stayed below 0.1% across all endpoints.' }}
        <template #metadata>
          <ChatMessageMetadata footer="Claude Opus 4.6" timestamp="9:45 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
    <ChatMessage sender="user">
      <ChatMessageBubble>
        {{ 'That looks great. Can you compare it to the week before?' }}
      </ChatMessageBubble>
    </ChatMessage>
    <ChatMessage sender="assistant">
      <ChatMessageBubble variant="ghost">
        {{ 'Compared to the previous week, traffic is up 8% and latency improved by 3ms. The deployment on Tuesday seems to have helped.' }}
        <template #metadata>
          <ChatMessageMetadata footer="Claude Opus 4.6" timestamp="9:46 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
  </ChatMessageList>
</template>
```

### Multi-Bubble

Grouped bubbles using the group prop for corner radius reduction. Use first, middle, and last to visually connect related bubbles from the same sender.

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

const agent = 'Agent'
</script>

<template>
  <ChatMessageList>
    <ChatMessage sender="user">
      <ChatMessageBubble group="first">
        {{ 'I have a couple of questions about the new API.' }}
      </ChatMessageBubble>
      <ChatMessageBubble group="middle">
        {{ 'First, how should we handle pagination?' }}
      </ChatMessageBubble>
      <ChatMessageBubble group="last">
        {{ 'And second, what\'s the rate limit?' }}
        <template #metadata>
          <ChatMessageMetadata status="delivered" timestamp="11:00 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
    <ChatMessage sender="assistant">
      <template #avatar>
        <Avatar :name="agent" size="md" />
      </template>
      <ChatMessageBubble group="first" :name="agent">
        {{ 'Great questions! For pagination, use cursor-based with a limit parameter. The response includes a nextCursor field.' }}
      </ChatMessageBubble>
      <ChatMessageBubble group="last">
        {{ 'Rate limit is 100 requests per minute per API key. You\'ll get a 429 response with a Retry-After header if you exceed it.' }}
        <template #metadata>
          <ChatMessageMetadata timestamp="11:01 AM" />
        </template>
      </ChatMessageBubble>
    </ChatMessage>
  </ChatMessageList>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `sender` | `'user' \| 'assistant' \| 'system'` | — | Who sent this message: controls alignment and layout. Required. A `system` row is centered and ignores the avatar, name, and metadata slots. |
| `name` | `string` | — | Plain sender name rendered above the body. Use it when the first child is raw content, not a bubble; with bubbles, set the name on the first bubble instead so it lines up with the bubble padding. |
| `density` | `ChatDensity` | list value, then `'balanced'` | Visual density: `'compact'`, `'balanced'`, or `'spacious'`. Inherited from the surrounding `ChatMessageList` when not set. |

## Slots

- `default`: message content: bubbles, tool calls, reasoning, or raw nodes. Custom content renders flush with the message edge; wrap it in a ghost `ChatMessageBubble` to align it with the bubble text column.
- `avatar`: element rendered beside the message, typically `Avatar`. Ignored when `sender` is `system`.
- `name`: replaces the `name` prop.
- `metadata`: rendered below the body. Use it when the last child is raw content, not a bubble; with bubbles, use the bubble's `metadata` slot instead.

## Exposed

- `element`: the root `<article>` element.
