Message

Displays a message in a conversation, with optional avatar, header, footer, and alignment.

Message
Deploying to prod real quick.
It's 4:55 PM. On a Friday.
It's a one-line change.
It's always a one-line change 😭. Make sure to run the tests this time.
Alright, go for it.
Avatar
CN
Something went wrong. Any idea?
ER
I checked the latest deployment and found the build failed during dependency installation.
ER
Something went wrong. Any idea?
CN
I checked the latest deployment and found the build failed during dependency installation.
Can you share the exact error message from the logs?
CN
Something went wrong. Any idea?
Group
I checked the registry addresses.
The component and example JSON now live under the UI registry.
I checked the registry addresses.
The component and example JSON now live under the UI registry.
I checked the registry addresses.
CN
The component and example JSON now live under the UI registry.
I checked the registry addresses.
CN
The component and example JSON now live under the UI registry.
Group Chat
Why is the dashboard showing zero users
Define "zero."
ER
What do you mean?
@eve can you check?
Checking the logs...
Eve
I found the following error in the logs: - Error: No users found - Stack trace: - at src/users/services/user-service.ts:123 - at src/users/services/get-user.ts:230 Can you check if the users are being created?
Header and Footer
You
Can we keep this style quiet and send the update today?
Olivia 1m ago
I checked the logs. The retry finished and the missing invoices are included now.
Marina
I drafted the reply with the exact filter path and a link to the export history.
Assistant note
Ghost messages keep long-form assistant notes aligned with the surrounding text instead of adding a frame.
Automation warning
The old export link expires in 10 minutes. Regenerate before sending this transcript externally.
Actions
What is the status of the deployment?
ER
The install failure is coming from the workspace package. I can open the exact log line or retry the deployment.
Okay drop me a link. I'll check it out.
Attachment
Workspace
Here's the image. Can you add it to the PDF? Use it for the cover page.
Done. Here's the PDF with the image added as the cover page.
sales-dashboard.pdf PDF · 2.4 MB
Thanks. Looks good.
Attachment Group
Workspace
Desk
Office
Here are the brand photos. Can you add them to the deck?
Done. Here's the draft deck and the exported assets.
brand-deck.pdf PDF · 3.1 MB
brand-deck.key Keynote · 9 MB
brand-assets.zip ZIP · 4.2 MB

Installation

Install the dependencies

pnpm add cn

Copy the component

Copy the following files into src/lib/components/ui/message.

src/lib/components/ui/message/Message.svelte
<script lang="ts">
  import type { MessageProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, align = 'start', ...props }: MessageProps = $props();
</script>
<div data-slot="message" data-align={align} {...props} class={cn('text-sm gap-2 group/message relative flex w-full min-w-0 data-[align=end]:flex-row-reverse', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/message/MessageAvatar.svelte
<script lang="ts">
  import type { MessageAvatarProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: MessageAvatarProps = $props();
</script>
<div data-slot="message-avatar" {...props} class={cn('min-w-8 group-has-data-[slot=message-footer]/message:-translate-y-8 flex w-fit shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/message/MessageContent.svelte
<script lang="ts">
  import type { MessageContentProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: MessageContentProps = $props();
</script>
<div data-slot="message-content" {...props} class={cn('gap-2.5 group-data-[align=end]/message:*:data-slot:self-end flex w-full min-w-0 flex-col wrap-break-word', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/message/MessageFooter.svelte
<script lang="ts">
  import type { MessageFooterProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: MessageFooterProps = $props();
</script>
<div data-slot="message-footer" {...props} class={cn('text-xs font-medium text-muted-foreground px-3 group-has-data-[variant=ghost]/message:px-0 flex max-w-full min-w-0 items-center group-data-[align=end]/message:justify-end', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/message/MessageGroup.svelte
<script lang="ts">
  import type { MessageGroupProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: MessageGroupProps = $props();
</script>
<div data-slot="message-group" {...props} class={cn('gap-2 flex min-w-0 flex-col', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/message/MessageHeader.svelte
<script lang="ts">
  import type { MessageHeaderProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: MessageHeaderProps = $props();
</script>
<div data-slot="message-header" {...props} class={cn('text-xs font-medium text-muted-foreground px-3 group-has-data-[variant=ghost]/message:px-0 flex max-w-full min-w-0 items-center', classProp)}>
  {@render children?.()}
</div>
src/lib/components/ui/message/types.ts
import type { HTMLAttributes } from 'svelte/elements';

type NativeDivProps = HTMLAttributes<HTMLDivElement>;

export type MessageGroupProps = NativeDivProps;
export type MessageProps = NativeDivProps & { align?: 'start' | 'end' };
export type MessageAvatarProps = NativeDivProps;
export type MessageContentProps = NativeDivProps;
export type MessageHeaderProps = NativeDivProps;
export type MessageFooterProps = NativeDivProps;
src/lib/components/ui/message/index.ts
export { default as MessageGroup } from './MessageGroup.svelte';
export { default as Message } from './Message.svelte';
export { default as MessageAvatar } from './MessageAvatar.svelte';
export { default as MessageContent } from './MessageContent.svelte';
export { default as MessageHeader } from './MessageHeader.svelte';
export { default as MessageFooter } from './MessageFooter.svelte';
export type { MessageGroupProps, MessageProps, MessageAvatarProps, MessageContentProps, MessageHeaderProps, MessageFooterProps } from './types.js';

Update the import paths

Change the imports to match your project setup.

Usage

<script lang="ts">
  import { Message, MessageAvatar, MessageContent, MessageFooter, MessageHeader } from '$lib/components/ui/message';
</script>
<Message align="end">
  <MessageAvatar>
    <img src="/avatar.png" alt="Rhea" />
  </MessageAvatar>
  <MessageContent>
    <MessageHeader>Rhea</MessageHeader>
    <p>The build is green.</p>
    <MessageFooter>Read 2:14 PM</MessageFooter>
  </MessageContent>
</Message>