Components
Message
Composes Bubble with an optional avatar and role-based layout for chat UIs.
Installation
npx kosmesis add messagepnpm dlx kosmesis add messageyarn dlx kosmesis add messagebunx kosmesis add messageThis component builds on other Kosmesis components — install these first (via kosmesis add or this same manual process on their own pages): bubble.
Copy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { Bubble } from "./bubble";import { cn } from "@/lib/utils";export interface MessageProps { from: "user" | "assistant"; class?: string; /** Rendered before the bubble (e.g. an `Avatar`). */ avatar?: Children; children?: Children;}/** * Composes `Bubble` with an optional avatar and role-based layout — no Morphos equivalent. * `from="user"` mirrors the row and uses the "sent" bubble variant; `from="assistant"` keeps * normal reading order with the "received" variant. */@Component()export class Message extends StatelessComponent<MessageProps> { render() { const { from, class: cls, avatar, children } = this.props; return ( <div class={cn("flex items-end gap-2", from === "user" && "flex-row-reverse", cls)}> {avatar} <Bubble variant={from === "user" ? "sent" : "received"}>{children}</Bubble> </div> ); }}export interface MessageGroupProps { class?: string; children?: Children;}@Component()export class MessageGroup extends StatelessComponent<MessageGroupProps> { render() { const { class: cls, children } = this.props; return <div class={cn("flex flex-col gap-3 p-4", cls)}>{children}</div>; }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssThis component builds on other Kosmesis components — install these first (via kosmesis add or this same manual process on their own pages): bubble.
Copy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { Bubble } from "./bubble";class MessageStyles extends Stylesheet { $root = this.css({ display: "flex", alignItems: "flex-end", gap: "0.5rem" }); $reversed = this.css({ flexDirection: "row-reverse" }); $group = this.css({ display: "flex", flexDirection: "column", gap: "0.75rem", padding: "1rem" });}export interface MessageProps { from: "user" | "assistant"; class?: string; /** Rendered before the bubble (e.g. an `Avatar`). */ avatar?: Children; children?: Children;}/** * Composes `Bubble` with an optional avatar and role-based layout — no Morphos equivalent. * `from="user"` mirrors the row and uses the "sent" bubble variant; `from="assistant"` keeps * normal reading order with the "received" variant. */@Component()export class Message extends StatelessComponent<MessageProps> { @Styled(MessageStyles) $s!: MessageStyles; render() { const { from, class: cls, avatar, children } = this.props; return ( <div class={cx(this.$s.$root, from === "user" && this.$s.$reversed, cls)}> {avatar} <Bubble variant={from === "user" ? "sent" : "received"}>{children}</Bubble> </div> ); }}export interface MessageGroupProps { class?: string; children?: Children;}@Component()export class MessageGroup extends StatelessComponent<MessageGroupProps> { @Styled(MessageStyles) $s!: MessageStyles; render() { const { class: cls, children } = this.props; return <div class={cx(this.$s.$group, cls)}>{children}</div>; }}Examples
Usage
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Message, MessageGroup } from "@/components/ui/message";
@Component()
class Chat extends StatefulComponent {
@State() avatar = new Avatar();
render() {
return (
<MessageGroup>
<Message from="assistant" avatar={
<Avatar class="size-6"><AvatarFallback avatar={this.avatar}>AI</AvatarFallback></Avatar>
}>
How can I help you today?
</Message>
<Message from="user">What's the weather like?</Message>
</MessageGroup>
);
}
}Use with Message Scroller for a scrollable chat viewport, and Attachment for file previews within a message.
Props
Message
| Prop | Type | Default |
|---|---|---|
from | "user" | "assistant" | — required |
avatar | Children | — rendered before the bubble (e.g. an Avatar) |
MessageGroup takes no props beyond class/children.