diff --git a/frontend/app/element/contextmenu.stories.tsx b/frontend/app/element/contextmenu.stories.tsx index 797a46bc8..e59ba28c3 100644 --- a/frontend/app/element/contextmenu.stories.tsx +++ b/frontend/app/element/contextmenu.stories.tsx @@ -1,3 +1,6 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + import type { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; import { useEffect, useRef, useState } from "react"; diff --git a/frontend/app/element/contextmenu.tsx b/frontend/app/element/contextmenu.tsx index 9bb146a85..0bfb09b7f 100644 --- a/frontend/app/element/contextmenu.tsx +++ b/frontend/app/element/contextmenu.tsx @@ -8,7 +8,7 @@ import ReactDOM from "react-dom"; import { useDimensionsWithExistingRef } from "@/app/hook/useDimensions"; import "./contextmenu.less"; -type MenuItem = { +export type MenuItem = { label: string; subItems?: MenuItem[]; onClick?: (e) => void; diff --git a/frontend/app/element/dropdown.stories.tsx b/frontend/app/element/dropdown.stories.tsx new file mode 100644 index 000000000..da7cf42e7 --- /dev/null +++ b/frontend/app/element/dropdown.stories.tsx @@ -0,0 +1,60 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import type { Meta, StoryObj } from "@storybook/react"; +import { useRef } from "react"; + +import { MenuItem } from "./contextmenu"; +import { Dropdown } from "./dropdown"; + +const items: MenuItem[] = [ + { label: "Option 1", onClick: () => console.log("Clicked Option 1") }, + { + label: "Option 2", + subItems: [ + { label: "Option 2.1", onClick: () => console.log("Clicked Option 2.1") }, + { label: "Option 2.2", onClick: () => console.log("Clicked Option 2.2") }, + ], + }, + { label: "Option 3", onClick: () => console.log("Clicked Option 3") }, +]; + +const meta: Meta = { + title: "Elements/Dropdown", + component: Dropdown, + args: { + label: "Dropdown Label", + items: items, + className: "", + }, + argTypes: { + label: { + description: "Label for the dropdown button", + }, + items: { + description: "Menu items for the dropdown", + }, + className: { + description: "Custom class for dropdown styling", + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const DefaultDropdown: Story = { + render: (args) => { + const scopeRef = useRef(null); + + return ( +
+ +
+ ); + }, + args: { + label: "Options", + items: items, + }, +}; diff --git a/frontend/app/element/dropdown.tsx b/frontend/app/element/dropdown.tsx index e69de29bb..53ef8561d 100644 --- a/frontend/app/element/dropdown.tsx +++ b/frontend/app/element/dropdown.tsx @@ -0,0 +1,64 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import clsx from "clsx"; +import { memo, useRef, useState } from "react"; +import { Button } from "./button"; +import { ContextMenu, MenuItem } from "./contextmenu"; + +import "./dropdown.less"; + +interface DropdownProps { + label: string; + items: MenuItem[]; + scopeRef: React.RefObject; + className?: string; +} + +const Dropdown = memo(({ label, className, items, scopeRef }: DropdownProps) => { + const anchorRef = useRef(null); + const [isMenuVisible, setIsMenuVisible] = useState(false); + + const handleAnchorClick = () => { + setIsMenuVisible((prev) => !prev); + }; + + const mapItemsWithClick = (items: any[]) => { + return items.map((item) => ({ + ...item, + onClick: () => { + if (item.onClick) { + item.onClick(); + setIsMenuVisible(false); + } + }, + subItems: item.subItems ? mapItemsWithClick(item.subItems) : undefined, + })); + }; + + return ( +
+ + {isMenuVisible && ( + setIsMenuVisible(visible)} + anchorRef={anchorRef} + scopeRef={scopeRef} + /> + )} +
+ ); +}); + +Dropdown.displayName = "Dropdown"; + +export { Dropdown }; diff --git a/frontend/app/view/chatview/channels.tsx b/frontend/app/view/chatview/channels.tsx index e69de29bb..a79bebadd 100644 --- a/frontend/app/view/chatview/channels.tsx +++ b/frontend/app/view/chatview/channels.tsx @@ -0,0 +1,22 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import "channels.less"; + +const channels = [ + { + text: "Channel 1", + icon: , + onClick: () => console.log("Inbox clicked"), + }, + { + text: "Channel 2", + icon: , + onClick: () => console.log("Sent Mail clicked"), + }, + { + text: "Drafts", + icon: , + onClick: () => console.log("Drafts clicked"), + }, +]; diff --git a/frontend/app/view/chatview/chatview.tsx b/frontend/app/view/chatview/chatview.tsx index 6b31a2652..df7b10174 100644 --- a/frontend/app/view/chatview/chatview.tsx +++ b/frontend/app/view/chatview/chatview.tsx @@ -1,248 +1,23 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 +import { Avatar } from "@/app/element/avatar" +import { List } from "@/app/element/list" +import { ChatItem } from "./chatitem" +import type { Channel, Message, User } from "./data" import "./Layout.css"; -const channels = [ - { - text: "Channel 1", - icon: , - onClick: () => console.log("Channel 1 clicked"), - }, - { - text: "Channel 2", - icon: , - onClick: () => console.log("Channel 2 clicked"), - children: [ - { - text: "Channel 2.1", - icon: , - onClick: () => console.log("Channel 2.1 clicked"), - children: [ - { - text: "Channel 2.1.1", - icon: , - onClick: () => console.log("Channel 2.1.1 clicked"), - }, - { - text: "Channel 2.1.2", - icon: , - onClick: () => console.log("Channel 2.1.2 clicked"), - }, - ], - }, - { - text: "Channel 2.2", - icon: , - onClick: () => console.log("Channel 2.2 clicked"), - }, - ], - }, - { - text: "Channel 3", - icon: , - onClick: () => console.log("Channel 3 clicked"), - children: [ - { - text: "Channel 3.1", - icon: , - onClick: () => console.log("Channel 3.1 clicked"), - }, - ], - }, - { - text: "Channel 4", - icon: , - onClick: () => console.log("Channel 4 clicked"), - }, - { - text: "Channel 5", - icon: , - onClick: () => console.log("Channel 5 clicked"), - children: [ - { - text: "Channel 5.1", - icon: , - onClick: () => console.log("Channel 5.1 clicked"), - children: [ - { - text: "Channel 5.1.1", - icon: , - onClick: () => console.log("Channel 5.1.1 clicked"), - }, - { - text: "Channel 5.1.2", - icon: , - onClick: () => console.log("Channel 5.1.2 clicked"), - children: [ - { - text: "Channel 5.1.2.1", - icon: , - onClick: () => console.log("Channel 5.1.2.1 clicked"), - }, - ], - }, - ], - }, - ], - }, - { - text: "Channel 6", - icon: , - onClick: () => console.log("Channel 6 clicked"), - }, - { - text: "Channel 7", - icon: , - onClick: () => console.log("Channel 7 clicked"), - children: [ - { - text: "Channel 7.1", - icon: , - onClick: () => console.log("Channel 7.1 clicked"), - }, - ], - }, - { - text: "Channel 8", - icon: , - onClick: () => console.log("Channel 8 clicked"), - }, - { - text: "Channel 9", - icon: , - onClick: () => console.log("Channel 9 clicked"), - children: [ - { - text: "Channel 9.1", - icon: , - onClick: () => console.log("Channel 9.1 clicked"), - children: [ - { - text: "Channel 9.1.1", - icon: , - onClick: () => console.log("Channel 9.1.1 clicked"), - }, - { - text: "Channel 9.1.2", - icon: , - onClick: () => console.log("Channel 9.1.2 clicked"), - }, - ], - }, - ], - }, - { - text: "Channel 10", - icon: , - onClick: () => console.log("Channel 10 clicked"), - }, - { - text: "Channel 11", - icon: , - onClick: () => console.log("Channel 11 clicked"), - }, - { - text: "Channel 12", - icon: , - onClick: () => console.log("Channel 12 clicked"), - }, - { - text: "Channel 13", - icon: , - onClick: () => console.log("Channel 13 clicked"), - }, - { - text: "Channel 14", - icon: , - onClick: () => console.log("Channel 14 clicked"), - children: [ - { - text: "Channel 14.1", - icon: , - onClick: () => console.log("Channel 14.1 clicked"), - }, - ], - }, - { - text: "Channel 15", - icon: , - onClick: () => console.log("Channel 15 clicked"), - }, - { - text: "Channel 16", - icon: , - onClick: () => console.log("Channel 16 clicked"), - }, - { - text: "Channel 17", - icon: , - onClick: () => console.log("Channel 17 clicked"), - children: [ - { - text: "Channel 17.1", - icon: , - onClick: () => console.log("Channel 17.1 clicked"), - children: [ - { - text: "Channel 17.1.1", - icon: , - onClick: () => console.log("Channel 17.1.1 clicked"), - }, - { - text: "Channel 17.1.2", - icon: , - onClick: () => console.log("Channel 17.1.2 clicked"), - }, - ], - }, - ], - }, - { - text: "Channel 18", - icon: , - onClick: () => console.log("Channel 18 clicked"), - }, - { - text: "Channel 19", - icon: , - onClick: () => console.log("Channel 19 clicked"), - }, - { - text: "Channel 20", - icon: , - onClick: () => console.log("Channel 20 clicked"), - }, - { - text: "Channel 21", - icon: , - onClick: () => console.log("Channel 21 clicked"), - }, - { - text: "Channel 22", - icon: , - onClick: () => console.log("Channel 22 clicked"), - }, - { - text: "Channel 23", - icon: , - onClick: () => console.log("Channel 23 clicked"), - }, - { - text: "Channel 24", - icon: , - onClick: () => console.log("Channel 24 clicked"), - }, - { - text: "Channel 25", - icon: , - onClick: () => console.log("Channel 25 clicked"), - }, -]; +interface ChatViewProps { + channels: Channel[]; + users: User[]; + messages: Message[]; +} + +const ChatView = ({ channels, users, messages }: ChatViewProps) => { + const renderChatItem = -const Layout = ({ columns }) => { return ( -
+
{columns.map((column, index) => (
{ {column.content}
))} + +
+ }> +
); }; -export default Layout; +export { ChatView };