# Chat Layout

## Usage

ChatLayout is the layout shell for full-page chat interfaces. It renders messages in normal page flow and docks the composer to the bottom with a frosted glass blur layer. Set the `density` prop to control spacing; it defaults to `balanced`. Use it to wrap ChatMessageList and ChatComposer for a complete chat experience with built-in auto-scroll and a scroll-to-bottom button.

```ts
import { ChatLayout } from '@astryx-vue/core/Chat'
```

### Anatomy

- **Message area**: Scrollable region for messages. Renders children (typically ChatMessageList) in a flex column that pushes content to the bottom when the list is short.
- **Frosted glass dock**: Sticky or fixed container at the bottom with a backdrop-blur layer. Houses the scroll button and composer.
- **Scroll-to-bottom button**: Appears when the user scrolls up or new messages arrive. Defaults to ChatLayoutScrollButton; pass null to hide or a custom element to override.
- **Composer**: The input area for sending messages, typically ChatComposer. Docked at the bottom inside the frosted glass layer.
- **Empty state**: Centered placeholder shown when no messages exist. Use EmptyState for a consistent look.

## Best practices

| Guidance | Practices |
| --- | --- |
| Do | Pass ChatMessageList as children and ChatComposer as the `composer` slot for a complete chat interface. |
| Do | Provide an `empty` slot so new conversations show a prompt instead of a blank screen. |
| Do | Use `scrollRef` when the chat is embedded in a page where a parent element handles scrolling. |
| Don't | Apply a fixed height on the layout; let it fill its container with `flex: 1`. |
| Don't | Render multiple ChatLayout instances in the same scroll container; each expects to own its scroll context. |

## Examples

Common configurations, variations, and states.

### ChatLayout — Panel View

Narrow sidebar chat in a constrained container that triggers compact density. Use for side panels, drawers, or embedded chat widgets where horizontal space is limited.

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

<template>
  <div class="chat-preview__panel">
    <ChatLayout>
      <ChatMessageList>
        <ChatSystemMessage variant="divider">
          Today
        </ChatSystemMessage>

        <ChatMessage sender="user">
          <ChatMessageBubble>
            Can you review the Button component and fix the focus ring?
          </ChatMessageBubble>
        </ChatMessage>

        <ChatMessage sender="assistant">
          <div class="chat-preview__lines">
            <p>I'll check the Button component now.</p>
            <p>Found the issue — the border radius was hardcoded. Replaced with the theme token.</p>
          </div>
        </ChatMessage>

        <ChatMessage sender="user">
          <ChatMessageBubble>
            Nice, can you also check the Card component?
          </ChatMessageBubble>
        </ChatMessage>

        <ChatMessage sender="assistant">
          <div class="chat-preview__lines">
            <p>Checking the component now.</p>
            <p>Found the issue — the border radius was hardcoded. Replaced with the theme token.</p>
          </div>
        </ChatMessage>
      </ChatMessageList>
      <template #composer>
        <ChatComposer placeholder="Ask something..." />
      </template>
    </ChatLayout>
  </div>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `density` | `ChatDensity` | `'balanced'` | Spacing, bubble width, and the frosted dock. `compact`, `balanced`, or `spacious`. |
| `scrollRef` | `HTMLElement \| null` | — | Element that scrolls instead of the layout root. Left unset, the layout itself scrolls and the dock sticks; set it and the dock becomes fixed over that element. |
| `showScrollButton` | `boolean` | `true` | Renders the built-in scroll-to-bottom button. Set it to `false` when the `scrollButton` slot should be the only control, or when there should be none. |

## Slots

| Slot | Description |
| --- | --- |
| (default) | Transcript. Usually one `ChatMessageList`. |
| `composer` | Pinned to the bottom, above the frosted scrim. Usually one `ChatComposer`. |
| `empty` | Shown when the default slot is omitted. Centered, so an `EmptyState` keeps a consistent look. |
| `scrollButton` | Replaces the built-in scroll button. Receives `isVisible`, `label`, and `scrollToBottom`, which dismisses the new-message label and scrolls down. |

## Exposed

| Name | Type | Description |
| --- | --- | --- |
| `element` | `HTMLElement \| null` | The layout root. |
| `scrollToBottom` | `() => void` | Dismisses the new-message state and scrolls to the latest message. |
