mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-04 18:59:08 +01:00
messages component
This commit is contained in:
parent
2486804d62
commit
2fc9c54785
51
frontend/app/element/chatmessages.less
Normal file
51
frontend/app/element/chatmessages.less
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.chat-messages {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
font-size: 1em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.chat-user-icon {
|
||||
height: 1em; /* Make user icon height match the text height */
|
||||
width: 1em; /* Keep the icon proportional */
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.chat-username {
|
||||
font-weight: bold;
|
||||
margin-right: 4px;
|
||||
line-height: 1.4; /* Ensure alignment with the first line of the message */
|
||||
}
|
||||
|
||||
.chat-text {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.chat-text img {
|
||||
height: 1em; /* Make inline images (rendered via markdown) match the text height */
|
||||
width: auto; /* Keep the aspect ratio of images */
|
||||
margin: 0 4px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.chat-emoji {
|
||||
margin: 0 2px;
|
||||
font-size: 1em; /* Match emoji size with the text height */
|
||||
}
|
90
frontend/app/element/chatmessages.stories.tsx
Normal file
90
frontend/app/element/chatmessages.stories.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { ChatMessages } from "./chatmessages";
|
||||
import "./chatmessages.less";
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string;
|
||||
username: string;
|
||||
message: string;
|
||||
color?: string;
|
||||
userIcon?: string;
|
||||
messageIcon?: string;
|
||||
}
|
||||
|
||||
const meta = {
|
||||
title: "Elements/ChatMessages",
|
||||
component: ChatMessages,
|
||||
args: {
|
||||
messages: [
|
||||
{
|
||||
id: "1",
|
||||
username: "User1",
|
||||
message: "Hello everyone! 👋",
|
||||
color: "#ff4500",
|
||||
userIcon: "https://via.placeholder.com/50",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
username: "User2",
|
||||
message: "Check this out: ![cool icon](https://via.placeholder.com/20)",
|
||||
color: "#1e90ff",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
username: "User3",
|
||||
message: "This is a simple text message without icons.",
|
||||
color: "#32cd32",
|
||||
userIcon: "https://via.placeholder.com/50",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
username: "User4",
|
||||
message: "🎉 👏 Great job!",
|
||||
color: "#ff6347",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
username: "User5",
|
||||
message: "Look at this cool icon: Isn't it awesome? ![cool icon](https://via.placeholder.com/20)",
|
||||
color: "#8a2be2",
|
||||
userIcon: "https://via.placeholder.com/50",
|
||||
},
|
||||
],
|
||||
},
|
||||
argTypes: {
|
||||
messages: {
|
||||
description: "Array of chat messages to be displayed",
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof ChatMessages>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Messages: Story = {
|
||||
render: (args) => (
|
||||
<div>
|
||||
<ChatMessages {...args} />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const ScrollableMessages: Story = {
|
||||
render: (args) => (
|
||||
<div style={{ height: "100%", overflow: "hidden" }}>
|
||||
<ChatMessages {...args} />
|
||||
</div>
|
||||
),
|
||||
args: {
|
||||
messages: Array.from({ length: 50 }, (_, i) => ({
|
||||
id: `${i + 1}`,
|
||||
username: `User${i + 1}`,
|
||||
message: `This is message number ${i + 1}.`,
|
||||
color: i % 2 === 0 ? "#ff6347" : "#1e90ff",
|
||||
userIcon: "https://via.placeholder.com/50",
|
||||
})),
|
||||
},
|
||||
};
|
60
frontend/app/element/chatmessages.tsx
Normal file
60
frontend/app/element/chatmessages.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { Markdown } from "@/app/element/markdown";
|
||||
import clsx from "clsx";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
import { memo, useEffect, useRef } from "react";
|
||||
|
||||
import "./chatmessages.less";
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string;
|
||||
username: string;
|
||||
message: string;
|
||||
color?: string;
|
||||
userIcon?: string;
|
||||
}
|
||||
|
||||
interface ChatMessagesProps {
|
||||
messages: ChatMessage[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ChatMessages = memo(({ messages, className }: ChatMessagesProps) => {
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const overlayScrollRef = useRef(null);
|
||||
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [messages]);
|
||||
|
||||
return (
|
||||
<OverlayScrollbarsComponent
|
||||
ref={overlayScrollRef}
|
||||
className={clsx("chat-messages", className)}
|
||||
options={{ scrollbars: { autoHide: "leave" } }}
|
||||
>
|
||||
{messages.map(({ id, username, message, color, userIcon }) => (
|
||||
<div key={id} className="chat-message">
|
||||
{userIcon && <img src={userIcon} alt="user icon" className="chat-user-icon" />}
|
||||
<span className="chat-username" style={{ color: color || "var(--main-text-color)" }}>
|
||||
{username}:
|
||||
</span>
|
||||
<span className="chat-text">
|
||||
<Markdown scrollable={false} text={message}></Markdown>
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
<div ref={messagesEndRef} />
|
||||
</OverlayScrollbarsComponent>
|
||||
);
|
||||
});
|
||||
|
||||
ChatMessages.displayName = "ChatMessages";
|
||||
|
||||
export { ChatMessages };
|
Loading…
Reference in New Issue
Block a user