From 916fc4fc10efc27c14cc8a8e3e940b4ea9aab9c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 26 Oct 2025 05:09:44 +0000 Subject: [PATCH 1/2] Initial plan From 3cfecbf9504afec36043eeeec6df29185e12ac40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 26 Oct 2025 05:19:06 +0000 Subject: [PATCH 2/2] Remove unused chat directory and related files - Removed entire frontend/app/view/chat/ directory (13 files) - Removed avatar.tsx, avatar.scss, avatar.stories.tsx - Removed collapsiblemenu.tsx, collapsiblemenu.scss, collapsiblemenu.stories.tsx - Removed avatar-dims-mixin from mixins.scss All files were verified to be unused outside their own directory. Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> --- frontend/app/element/avatar.scss | 57 ----- frontend/app/element/avatar.stories.tsx | 68 ------ frontend/app/element/avatar.tsx | 36 --- frontend/app/element/collapsiblemenu.scss | 62 ----- .../app/element/collapsiblemenu.stories.tsx | 170 ------------- frontend/app/element/collapsiblemenu.tsx | 76 ------ frontend/app/mixins.scss | 57 ----- frontend/app/view/chat/channels.scss | 30 --- frontend/app/view/chat/channels.tsx | 13 - frontend/app/view/chat/chat.scss | 31 --- frontend/app/view/chat/chat.tsx | 66 ----- frontend/app/view/chat/chatbox.tsx | 78 ------ frontend/app/view/chat/chatmessages.scss | 50 ---- .../app/view/chat/chatmessages.stories.tsx | 90 ------- frontend/app/view/chat/chatmessages.tsx | 60 ----- frontend/app/view/chat/data.tsx | 225 ------------------ frontend/app/view/chat/userlist.scss | 35 --- frontend/app/view/chat/userlist.stories.tsx | 58 ----- frontend/app/view/chat/userlist.tsx | 38 --- 19 files changed, 1300 deletions(-) delete mode 100644 frontend/app/element/avatar.scss delete mode 100644 frontend/app/element/avatar.stories.tsx delete mode 100644 frontend/app/element/avatar.tsx delete mode 100644 frontend/app/element/collapsiblemenu.scss delete mode 100644 frontend/app/element/collapsiblemenu.stories.tsx delete mode 100644 frontend/app/element/collapsiblemenu.tsx delete mode 100644 frontend/app/view/chat/channels.scss delete mode 100644 frontend/app/view/chat/channels.tsx delete mode 100644 frontend/app/view/chat/chat.scss delete mode 100644 frontend/app/view/chat/chat.tsx delete mode 100644 frontend/app/view/chat/chatbox.tsx delete mode 100644 frontend/app/view/chat/chatmessages.scss delete mode 100644 frontend/app/view/chat/chatmessages.stories.tsx delete mode 100644 frontend/app/view/chat/chatmessages.tsx delete mode 100644 frontend/app/view/chat/data.tsx delete mode 100644 frontend/app/view/chat/userlist.scss delete mode 100644 frontend/app/view/chat/userlist.stories.tsx delete mode 100644 frontend/app/view/chat/userlist.tsx diff --git a/frontend/app/element/avatar.scss b/frontend/app/element/avatar.scss deleted file mode 100644 index e5495cc44d..0000000000 --- a/frontend/app/element/avatar.scss +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -@use "../mixins.scss"; - -.avatar { - position: relative; - width: 50px; - height: 50px; - border-radius: 50%; - background-color: var(--border-color); - display: flex; - justify-content: center; - align-items: center; - color: var(--main-text-color); - font-size: 18px; - text-transform: uppercase; - - .avatar-image { - width: 100%; - height: 100%; - border-radius: 50%; - object-fit: cover; - } - - .avatar-initials { - font-weight: bold; - } - - .status-indicator { - position: absolute; - bottom: 2px; - right: 2px; - width: 12px; - height: 12px; - border-radius: 50%; - background-color: transparent; - - &.online { - background-color: var(--success-color); - } - - &.offline { - background-color: var(--grey-text-color); - } - - &.busy { - background-color: var(--error-color); - } - - &.away { - background-color: var(--warning-color); - } - } - - @include mixins.avatar-dims-mixin(); -} diff --git a/frontend/app/element/avatar.stories.tsx b/frontend/app/element/avatar.stories.tsx deleted file mode 100644 index c1302ae3ae..0000000000 --- a/frontend/app/element/avatar.stories.tsx +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Meta, StoryObj } from "@storybook/react"; -import { Avatar } from "./avatar"; - -const meta = { - title: "Elements/Avatar", - component: Avatar, - args: { - name: "John Doe", - status: "offline", - imageUrl: "", - }, - argTypes: { - name: { - control: { type: "text" }, - description: "The name of the user", - }, - status: { - control: { type: "select", options: ["online", "offline", "busy", "away"] }, - description: "The status of the user", - }, - imageUrl: { - control: { type: "text" }, - description: "Optional image URL for the avatar", - }, - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -// Default case (without an image, default status: offline) -export const Default: Story = { - args: { - name: "John Doe", - status: "offline", - imageUrl: "", - }, -}; - -// Online status with an image -export const OnlineWithImage: Story = { - args: { - name: "Alice Smith", - status: "online", - imageUrl: "https://i.pravatar.cc/150?u=a042581f4e29026704d", - }, -}; - -// Busy status without an image -export const BusyWithoutImage: Story = { - args: { - name: "Michael Johnson", - status: "busy", - imageUrl: "", - }, -}; - -// Away status with an image -export const AwayWithImage: Story = { - args: { - name: "Sarah Connor", - status: "away", - imageUrl: "https://i.pravatar.cc/150?u=a042581f4e29026704d", - }, -}; diff --git a/frontend/app/element/avatar.tsx b/frontend/app/element/avatar.tsx deleted file mode 100644 index a489262ae3..0000000000 --- a/frontend/app/element/avatar.tsx +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 -import { memo } from "react"; - -import clsx from "clsx"; -import "./avatar.scss"; - -interface AvatarProps { - name: string; - status: "online" | "offline" | "busy" | "away"; - className?: string; - imageUrl?: string; -} - -const Avatar = memo(({ name, status = "offline", className, imageUrl }: AvatarProps) => { - const getInitials = (name: string) => { - const nameParts = name.split(" "); - const initials = nameParts.map((part) => part[0]).join(""); - return initials.toUpperCase(); - }; - - return ( -
- {imageUrl ? ( - {`${name}'s - ) : ( -
{getInitials(name)}
- )} -
-
- ); -}); - -Avatar.displayName = "Avatar"; - -export { Avatar }; diff --git a/frontend/app/element/collapsiblemenu.scss b/frontend/app/element/collapsiblemenu.scss deleted file mode 100644 index f398924360..0000000000 --- a/frontend/app/element/collapsiblemenu.scss +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -@use "../mixins.scss"; - -.collapsible-menu { - list-style: none; - padding: 0; -} - -.collapsible-menu-item { - cursor: pointer; - user-select: none; - padding: 0; -} - -.collapsible-menu-item-button { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; -} - -.collapsible-menu-item-content { - display: flex; - align-items: center; -} - -.collapsible-menu-item-icon { - margin-right: 10px; /* Space between icon and text */ -} - -.collapsible-menu-item-text { - text-decoration: none; -} - -.nested-list { - list-style: none; - padding-left: 20px; -} - -.nested-list.open { - display: block; -} - -.nested-list.closed { - display: none; -} - -.collapsible-menu-item-button { - padding: 10px; - color: var(--main-text-color); - - &:hover { - background-color: var(--button-grey-hover-bg); - border-radius: 4px; - } -} - -.collapsible-menu-item-button.clickable:hover { - background-color: #f0f0f0; -} diff --git a/frontend/app/element/collapsiblemenu.stories.tsx b/frontend/app/element/collapsiblemenu.stories.tsx deleted file mode 100644 index 30d95633c4..0000000000 --- a/frontend/app/element/collapsiblemenu.stories.tsx +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { Meta, StoryObj } from "@storybook/react"; -import { Avatar } from "./avatar"; -import { CollapsibleMenu } from "./collapsiblemenu"; - -const meta: Meta = { - title: "Elements/CollapsibleMenu", - component: CollapsibleMenu, - argTypes: { - items: { control: "object" }, - renderItem: { control: false }, - }, -}; - -export default meta; -type Story = StoryObj; - -// Container style for limiting the width to 360px -const Container = (props: any) => ( -
- {props.children} -
-); - -const basicItems = [ - { - label: "Inbox", - icon: , - onClick: () => console.log("Inbox clicked"), - }, - { - label: "Sent Mail", - icon: , - onClick: () => console.log("Sent Mail clicked"), - }, - { - label: "Drafts", - icon: , - onClick: () => console.log("Drafts clicked"), - }, -]; - -const nestedItems = [ - { - label: "Inbox", - icon: , - onClick: () => console.log("Inbox clicked"), - subItems: [ - { - label: "Starred", - icon: , - onClick: () => console.log("Starred clicked"), - }, - { - label: "Important", - icon: , - onClick: () => console.log("Important clicked"), - }, - ], - }, - { - label: "Sent Mail", - icon: , - onClick: () => console.log("Sent Mail clicked"), - }, - { - label: "Drafts", - icon: , - onClick: () => console.log("Drafts clicked"), - }, -]; - -const customRenderItem = ( - item: MenuItem, - isOpen: boolean, - handleClick: (e: React.MouseEvent, item: MenuItem, itemKey: string) => void -) => ( -
- handleClick(e, item, `${item.label}`)}> - {item.icon} - - handleClick(e, item, `${item.label}`)}> - {item.label} - - {item.subItems && } -
-); - -export const Default: Story = { - args: { - items: basicItems, - }, - render: (args) => ( - - - - ), -}; - -export const NestedList: Story = { - args: { - items: nestedItems, - }, - render: (args) => ( - - - - ), -}; - -export const CustomRender: Story = { - args: { - items: nestedItems, - renderItem: customRenderItem, - }, - render: (args) => ( - - - - ), -}; - -export const WithClickHandlers: Story = { - args: { - items: basicItems, - }, - render: (args) => ( - - - - ), -}; - -export const NestedWithClickHandlers: Story = { - args: { - items: nestedItems, - }, - render: (args) => ( - - - - ), -}; - -const avatarItems = [ - { - label: "John Doe", - icon: , - onClick: () => console.log("John Doe clicked"), - }, - { - label: "Jane Smith", - icon: , - onClick: () => console.log("Jane Smith clicked"), - }, - { - label: "Robert Brown", - icon: , - onClick: () => console.log("Robert Brown clicked"), - }, - { - label: "Alice Lambert", - icon: , - onClick: () => console.log("Alice Lambert clicked"), - }, -]; diff --git a/frontend/app/element/collapsiblemenu.tsx b/frontend/app/element/collapsiblemenu.tsx deleted file mode 100644 index 737dcc8f17..0000000000 --- a/frontend/app/element/collapsiblemenu.tsx +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import clsx from "clsx"; -import React, { memo, useState } from "react"; -import "./collapsiblemenu.scss"; - -interface VerticalNavProps { - items: MenuItem[]; - className?: string; - renderItem?: ( - item: MenuItem, - isOpen: boolean, - handleClick: (e: React.MouseEvent, item: MenuItem, itemKey: string) => void - ) => React.ReactNode; -} - -const CollapsibleMenu = memo(({ items, className, renderItem }: VerticalNavProps) => { - const [open, setOpen] = useState<{ [key: string]: boolean }>({}); - - // Helper function to generate a unique key for each item based on its path in the hierarchy - const getItemKey = (item: MenuItem, path: string) => `${path}-${item.label}`; - - const handleClick = (e: React.MouseEvent, item: MenuItem, itemKey: string) => { - setOpen((prevState) => ({ ...prevState, [itemKey]: !prevState[itemKey] })); - if (item.onClick) { - item.onClick(e); - } - }; - - const renderListItem = (item: MenuItem, index: number, path: string) => { - const itemKey = getItemKey(item, path); - const isOpen = open[itemKey] === true; - const hasChildren = item.subItems && item.subItems.length > 0; - - return ( -
  • - {renderItem ? ( - renderItem(item, isOpen, (e) => handleClick(e, item, itemKey)) - ) : ( -
    handleClick(e, item, itemKey)}> -
    - {item.icon &&
    {item.icon}
    } -
    {item.label}
    -
    - {hasChildren && ( - - )} -
    - )} - {hasChildren && ( -
      - {item.subItems.map((child, childIndex) => - renderListItem(child, childIndex, `${path}-${index}`) - )} -
    - )} -
  • - ); - }; - - return ( -
      - {items.map((item, index) => renderListItem(item, index, "root"))} -
    - ); -}); - -CollapsibleMenu.displayName = "CollapsibleMenu"; - -export { CollapsibleMenu }; diff --git a/frontend/app/mixins.scss b/frontend/app/mixins.scss index cbfc93f286..0d624abf5b 100644 --- a/frontend/app/mixins.scss +++ b/frontend/app/mixins.scss @@ -7,60 +7,3 @@ overflow: hidden; text-overflow: ellipsis; } - -@mixin avatar-dims-mixin() { - &.size-xs { - width: 20px; - height: 20px; - font-size: 7px; // 18px * (20 / 50) - - .status-indicator { - width: 5px; // scaled indicator size - height: 5px; - } - } - - &.size-sm { - width: 30px; - height: 30px; - font-size: 11px; // 18px * (30 / 50) - - .status-indicator { - width: 7px; - height: 7px; - } - } - - &.size-md { - width: 40px; - height: 40px; - font-size: 14px; // 18px * (40 / 50) - - .status-indicator { - width: 9px; - height: 9px; - } - } - - &.size-lg { - width: 45px; - height: 45px; - font-size: 16px; // 18px * (45 / 50) - - .status-indicator { - width: 10px; - height: 10px; - } - } - - &.size-xl { - width: 50px; - height: 50px; - font-size: 18px; // base size - - .status-indicator { - width: 12px; - height: 12px; - } - } -} diff --git a/frontend/app/view/chat/channels.scss b/frontend/app/view/chat/channels.scss deleted file mode 100644 index eed93867b0..0000000000 --- a/frontend/app/view/chat/channels.scss +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -.channel-list { - width: 180px; - background-color: rgba(255, 255, 255, 0.025); - overflow-x: hidden; - padding: 5px; - - .menu-item-button { - padding: 5px 7px; - } - - .nested-list { - padding-left: 10px; - } - - .menu-item-text { - color: rgb(from var(--main-text-color) r g b / 0.7); - } - - .has-children .menu-item-text { - font-size: 14px; - } - - .is-open .menu-item-text { - color: var(--main-text-color); - font-weight: bold; - } -} diff --git a/frontend/app/view/chat/channels.tsx b/frontend/app/view/chat/channels.tsx deleted file mode 100644 index ee354e225e..0000000000 --- a/frontend/app/view/chat/channels.tsx +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { CollapsibleMenu } from "@/app/element/collapsiblemenu"; -import { memo } from "react"; - -import "./channels.scss"; - -const Channels = memo(({ channels }: { channels: MenuItem[] }) => { - return ; -}); - -export { Channels }; diff --git a/frontend/app/view/chat/chat.scss b/frontend/app/view/chat/chat.scss deleted file mode 100644 index 0e7d49fb4b..0000000000 --- a/frontend/app/view/chat/chat.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -.chat-view { - display: flex; - flex-direction: row; - width: 100%; - height: 100%; - - .chat-section { - display: flex; - flex-direction: column; - flex-grow: 1; - - .message-wrapper { - flex-grow: 1; // Make the ChatMessages take up available height - display: flex; - flex-direction: column; - overflow: hidden; // Ensure content doesn't overflow - } - - .chatbox { - display: flex; - align-items: center; - - textarea { - border: none; - } - } - } -} diff --git a/frontend/app/view/chat/chat.tsx b/frontend/app/view/chat/chat.tsx deleted file mode 100644 index c83f42ff3b..0000000000 --- a/frontend/app/view/chat/chat.tsx +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { ChatMessage, ChatMessages } from "@/app/view/chat/chatmessages"; -import { UserStatus } from "@/app/view/chat/userlist"; -import * as jotai from "jotai"; -import { memo } from "react"; -import { Channels } from "./channels"; -import { ChatBox } from "./chatbox"; -import { channels, messages, users } from "./data"; -import { UserList } from "./userlist"; - -import "./chat.scss"; - -class ChatModel { - viewType: string; - channels: MenuItem[]; - users: UserStatus[]; - messagesAtom: jotai.PrimitiveAtom; - - constructor(blockId: string) { - this.viewType = "chat"; - this.channels = channels; - this.users = users; - this.messagesAtom = jotai.atom(messages); - } - - addMessageAtom = jotai.atom(null, (get, set, newMessage: ChatMessage) => { - const currentMessages = get(this.messagesAtom); - set(this.messagesAtom, [...currentMessages, newMessage]); - }); -} - -interface ChatProps { - model: ChatModel; -} - -const Chat = memo(({ model }: ChatProps) => { - const { channels, users } = model; - const messages = jotai.useAtomValue(model.messagesAtom); - const [, appendMessage] = jotai.useAtom(model.addMessageAtom); - - const handleSendMessage = (message: string) => { - const newMessage: ChatMessage = { - id: `${Date.now()}`, - username: "currentUser", - message: message, - }; - appendMessage(newMessage); - }; - - return ( -
    - -
    -
    - -
    - handleSendMessage(message)} /> -
    - -
    - ); -}); - -export { Chat, ChatModel }; diff --git a/frontend/app/view/chat/chatbox.tsx b/frontend/app/view/chat/chatbox.tsx deleted file mode 100644 index fa09a7645e..0000000000 --- a/frontend/app/view/chat/chatbox.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { EmojiPalette, type EmojiItem } from "@/app/element/emojipalette"; -import { InputGroup } from "@/app/element/input"; -import { MultiLineInput } from "@/app/element/multilineinput"; -import * as keyutil from "@/util/keyutil"; -import React, { memo, useRef, useState } from "react"; -import { throttle } from "throttle-debounce"; - -interface ChatBoxProps { - onSendMessage: (message: string) => void; -} - -const ChatBox = memo(({ onSendMessage }: ChatBoxProps) => { - const [message, setMessage] = useState(""); - const multiLineInputRef = useRef(null); - - const handleInputChange = (e: React.ChangeEvent) => { - setMessage(e.target.value); - }; - - const handleKeyDown = (waveEvent: WaveKeyboardEvent): boolean => { - if (keyutil.checkKeyPressed(waveEvent, "Enter") && !waveEvent.shift && message.trim() !== "") { - onSendMessage(message); - setMessage(""); - return true; - } - return false; - }; - - const handleEmojiSelect = (emojiItem: EmojiItem) => { - if (multiLineInputRef.current) { - const { selectionStart, selectionEnd } = multiLineInputRef.current; - const currentValue = multiLineInputRef.current.value; - - // Insert emoji at the current cursor position - const newValue = - currentValue.substring(0, selectionStart) + emojiItem.emoji + currentValue.substring(selectionEnd); - - // Update the message state and textarea value - setMessage(newValue); - - // Set the textarea value manually - multiLineInputRef.current.value = newValue; - - // Move cursor after the inserted emoji - const cursorPosition = selectionStart + emojiItem.emoji.length; - - // Use setTimeout to ensure the cursor positioning happens after rendering the new value - throttle(0, () => { - if (multiLineInputRef.current) { - multiLineInputRef.current.selectionStart = multiLineInputRef.current.selectionEnd = cursorPosition; - multiLineInputRef.current.focus(); // Make sure the textarea remains focused - } - })(); - - // Trigger onChange manually - multiLineInputRef.current.dispatchEvent(new Event("change", { bubbles: true })); - } - }; - - return ( - - keyutil.keydownWrapper(handleKeyDown)(e)} - placeholder="Type a message..." - /> - - - ); -}); - -export { ChatBox }; diff --git a/frontend/app/view/chat/chatmessages.scss b/frontend/app/view/chat/chatmessages.scss deleted file mode 100644 index 153b7ecdcf..0000000000 --- a/frontend/app/view/chat/chatmessages.scss +++ /dev/null @@ -1,50 +0,0 @@ -// 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: 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 */ -} diff --git a/frontend/app/view/chat/chatmessages.stories.tsx b/frontend/app/view/chat/chatmessages.stories.tsx deleted file mode 100644 index a96baf4853..0000000000 --- a/frontend/app/view/chat/chatmessages.stories.tsx +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Meta, StoryObj } from "@storybook/react"; -import { ChatMessages } from "./chatmessages"; -import "./chatmessages.scss"; - -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; - -export default meta; -type Story = StoryObj; - -export const Messages: Story = { - render: (args) => ( -
    - -
    - ), -}; - -export const ScrollableMessages: Story = { - render: (args) => ( -
    - -
    - ), - 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", - })), - }, -}; diff --git a/frontend/app/view/chat/chatmessages.tsx b/frontend/app/view/chat/chatmessages.tsx deleted file mode 100644 index 2c9023ebc7..0000000000 --- a/frontend/app/view/chat/chatmessages.tsx +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2025, 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.scss"; - -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(null); - const overlayScrollRef = useRef(null); - - const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); - }; - - useEffect(() => { - // scrollToBottom(); - }, [messages]); - - return ( - - {messages.map(({ id, username, message, color, userIcon }) => ( -
    - {userIcon && user icon} - - {username}: - - - - -
    - ))} -
    - - ); -}); - -ChatMessages.displayName = "ChatMessages"; - -export { ChatMessages }; diff --git a/frontend/app/view/chat/data.tsx b/frontend/app/view/chat/data.tsx deleted file mode 100644 index b507ea672f..0000000000 --- a/frontend/app/view/chat/data.tsx +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 -import { ChatMessage } from "@/app/view/chat/chatmessages"; -import { UserStatus } from "@/app/view/chat/userlist"; - -export const channels: MenuItem[] = [ - { - label: "Aurora Streams", - icon: "#", - onClick: () => console.log("Aurora Streams clicked"), - }, - { - label: "Crimson Oasis", - onClick: () => console.log("Crimson Oasis clicked"), - subItems: [ - { - label: "Golden Dunes", - icon: "#", - onClick: () => console.log("Golden Dunes clicked"), - }, - { - label: "Emerald Springs", - icon: "#", - onClick: () => console.log("Emerald Springs clicked"), - }, - { - label: "Ruby Cascades", - icon: "#", - onClick: () => console.log("Ruby Cascades clicked"), - }, - { - label: "Sapphire Falls", - icon: "#", - onClick: () => console.log("Sapphire Falls clicked"), - }, - ], - }, - { - label: "Velvet Horizon", - onClick: () => console.log("Velvet Horizon clicked"), - subItems: [ - { - label: "Amber Skies", - icon: "#", - onClick: () => console.log("Amber Skies clicked"), - }, - ], - }, - { - label: "Mystic Meadows", - icon: "#", - onClick: () => console.log("Mystic Meadows clicked"), - }, - { - label: "Celestial Grove", - icon: "#", - onClick: () => console.log("Celestial Grove clicked"), - }, - { - label: "Twilight Whisper", - icon: "#", - onClick: () => console.log("Twilight Whisper clicked"), - }, - { - label: "Starlit Haven", - onClick: () => console.log("Starlit Haven clicked"), - subItems: [ - { - label: "Moonlit Trail", - icon: "#", - onClick: () => console.log("Moonlit Trail clicked"), - }, - ], - }, - { - label: "Silver Mist", - icon: "#", - onClick: () => console.log("Silver Mist clicked"), - }, - { - label: "Eclipse Haven", - onClick: () => console.log("Eclipse Haven clicked"), - subItems: [ - { - label: "Obsidian Wave", - icon: "#", - onClick: () => console.log("Obsidian Wave clicked"), - }, - { - label: "Ivory Shore", - icon: "#", - onClick: () => console.log("Ivory Shore clicked"), - }, - { - label: "Azure Tide", - icon: "#", - onClick: () => console.log("Azure Tide clicked"), - }, - ], - }, - { - label: "Dragon's Peak", - icon: "#", - onClick: () => console.log("Dragon's Peak clicked"), - }, - { - label: "Seraph's Wing", - icon: "#", - onClick: () => console.log("Seraph's Wing clicked"), - }, - { - label: "Frozen Abyss", - icon: "#", - onClick: () => console.log("Frozen Abyss clicked"), - }, - { - label: "Radiant Blossom", - icon: "#", - onClick: () => console.log("Radiant Blossom clicked"), - }, - { - label: "Whispering Pines", - icon: "#", - onClick: () => console.log("Whispering Pines clicked"), - subItems: [ - { - label: "Cedar Haven", - icon: "#", - onClick: () => console.log("Cedar Haven clicked"), - }, - ], - }, - { - label: "Scarlet Veil", - icon: "#", - onClick: () => console.log("Scarlet Veil clicked"), - }, - { - label: "Onyx Spire", - icon: "#", - onClick: () => console.log("Onyx Spire clicked"), - }, - { - label: "Violet Enclave", - onClick: () => console.log("Violet Enclave clicked"), - subItems: [ - { - label: "Indigo Haven", - icon: "#", - onClick: () => console.log("Indigo Haven clicked"), - }, - { - label: "Amethyst Hollow", - icon: "#", - onClick: () => console.log("Amethyst Hollow clicked"), - }, - { - label: "Crimson Glow", - icon: "#", - onClick: () => console.log("Crimson Glow clicked"), - }, - ], - }, -]; - -export const users: UserStatus[] = [ - { - label: "John Doe", - status: "online", - avatarUrl: "https://via.placeholder.com/50", - onClick: () => console.log("John Doe clicked"), - }, - { - label: "Jane Smith", - status: "busy", - onClick: () => console.log("Jane Smith clicked"), - }, - { - label: "Robert Brown", - status: "away", - avatarUrl: "https://via.placeholder.com/50", - onClick: () => console.log("Robert Brown clicked"), - }, - { - label: "Alice Lambert", - status: "offline", - onClick: () => console.log("Alice Lambert clicked"), - }, -]; - -export const messages: ChatMessage[] = [ - { - 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", - }, -]; diff --git a/frontend/app/view/chat/userlist.scss b/frontend/app/view/chat/userlist.scss deleted file mode 100644 index b9a46b0e98..0000000000 --- a/frontend/app/view/chat/userlist.scss +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -.user-list { - display: flex; - flex-direction: column; - max-width: 250px; - background-color: rgba(255, 255, 255, 0.025); - padding: 5px; -} - -.user-status-item { - display: flex; - align-items: center; - padding: 8px; - margin-bottom: 6px; - cursor: pointer; - transition: background-color 0.3s ease; -} - -.user-status-item:hover { - background-color: var(--button-grey-hover-bg); - border-radius: 4px; -} - -.user-status-icon { - margin-right: 10px; - display: flex; - align-items: center; -} - -.user-status-text { - font-size: 1em; - font-weight: bold; -} diff --git a/frontend/app/view/chat/userlist.stories.tsx b/frontend/app/view/chat/userlist.stories.tsx deleted file mode 100644 index 7c4f7ac4ee..0000000000 --- a/frontend/app/view/chat/userlist.stories.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import type { Meta, StoryObj } from "@storybook/react"; -import { UserList } from "./userlist"; - -import "./userlist.scss"; - -export interface UserStatus { - text: string; - status: "online" | "busy" | "away" | "offline"; - onClick: () => void; -} - -const meta = { - title: "Elements/UserList", - component: UserList, - args: { - users: [ - { - label: "John Doe", - status: "online", - onClick: () => console.log("John Doe clicked"), - }, - { - label: "Jane Smith", - status: "busy", - onClick: () => console.log("Jane Smith clicked"), - }, - { - label: "Robert Brown", - status: "away", - onClick: () => console.log("Robert Brown clicked"), - }, - { - label: "Alice Lambert", - status: "offline", - onClick: () => console.log("Alice Lambert clicked"), - }, - ], - }, - argTypes: { - users: { - description: "Array of user statuses to be displayed", - }, - }, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - render: (args) => ( -
    - -
    - ), -}; diff --git a/frontend/app/view/chat/userlist.tsx b/frontend/app/view/chat/userlist.tsx deleted file mode 100644 index 9758224ded..0000000000 --- a/frontend/app/view/chat/userlist.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2025, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import clsx from "clsx"; -import { memo } from "react"; -import { Avatar } from "../../element/avatar"; -import "./userlist.scss"; - -export interface UserStatus { - label: string; - status: "online" | "busy" | "away" | "offline"; - onClick: () => void; - avatarUrl?: string; -} - -interface UserListProps { - users: UserStatus[]; - className?: string; -} - -const UserList = memo(({ users, className }: UserListProps) => { - return ( -
    - {users.map(({ label, status, onClick, avatarUrl }, index) => ( -
    -
    - -
    -
    {label}
    -
    - ))} -
    - ); -}); - -UserList.displayName = "UserList"; - -export { UserList };