mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-02-12 01:01:50 +01:00
dropdown stopries
This commit is contained in:
parent
0525efc1ce
commit
f7d8ff3665
@ -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";
|
||||
|
@ -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;
|
||||
|
60
frontend/app/element/dropdown.stories.tsx
Normal file
60
frontend/app/element/dropdown.stories.tsx
Normal file
@ -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<typeof Dropdown> = {
|
||||
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<typeof Dropdown>;
|
||||
|
||||
export const DefaultDropdown: Story = {
|
||||
render: (args) => {
|
||||
const scopeRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<div ref={scopeRef} style={{ padding: "20px", height: "300px", border: "2px solid black" }}>
|
||||
<Dropdown {...args} scopeRef={scopeRef} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
args: {
|
||||
label: "Options",
|
||||
items: items,
|
||||
},
|
||||
};
|
@ -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<any>;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const Dropdown = memo(({ label, className, items, scopeRef }: DropdownProps) => {
|
||||
const anchorRef = useRef<HTMLButtonElement>(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 (
|
||||
<div className={clsx("dropdown", className)}>
|
||||
<Button
|
||||
ref={anchorRef}
|
||||
className="grey border-radius-3 vertical-padding-6 horizontal-padding-8"
|
||||
style={{ borderColor: isMenuVisible ? "var(--accent-color)" : "transparent" }}
|
||||
onClick={handleAnchorClick}
|
||||
>
|
||||
{label}
|
||||
<i className="fa-sharp fa-solid fa-angle-down" style={{ marginLeft: 4 }}></i>
|
||||
</Button>
|
||||
{isMenuVisible && (
|
||||
<ContextMenu
|
||||
items={items}
|
||||
setVisibility={(visible) => setIsMenuVisible(visible)}
|
||||
anchorRef={anchorRef}
|
||||
scopeRef={scopeRef}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Dropdown.displayName = "Dropdown";
|
||||
|
||||
export { Dropdown };
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import "channels.less";
|
||||
|
||||
const channels = [
|
||||
{
|
||||
text: "Channel 1",
|
||||
icon: <i className="fa-sharp fa-solid fa-door-open"></i>,
|
||||
onClick: () => console.log("Inbox clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 2",
|
||||
icon: <i className="fa-sharp fa-solid fa-paper-plane"></i>,
|
||||
onClick: () => console.log("Sent Mail clicked"),
|
||||
},
|
||||
{
|
||||
text: "Drafts",
|
||||
icon: <i className="fa-sharp fa-solid fa-drafting-compass"></i>,
|
||||
onClick: () => console.log("Drafts clicked"),
|
||||
},
|
||||
];
|
@ -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: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 1 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 2",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 2 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 2.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 2.1 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 2.1.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 2.1.1 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 2.1.2",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 2.1.2 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 2.2",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 2.2 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 3",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 3 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 3.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 3.1 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 4",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 4 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 5",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 5 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 5.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 5.1 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 5.1.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 5.1.1 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 5.1.2",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 5.1.2 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 5.1.2.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 5.1.2.1 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 6",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 6 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 7",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 7 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 7.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 7.1 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 8",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 8 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 9",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 9 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 9.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 9.1 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 9.1.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 9.1.1 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 9.1.2",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 9.1.2 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 10",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 10 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 11",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 11 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 12",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 12 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 13",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 13 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 14",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 14 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 14.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 14.1 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 15",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 15 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 16",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 16 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 17",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 17 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 17.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 17.1 clicked"),
|
||||
children: [
|
||||
{
|
||||
text: "Channel 17.1.1",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 17.1.1 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 17.1.2",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 17.1.2 clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Channel 18",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 18 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 19",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 19 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 20",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 20 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 21",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 21 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 22",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 22 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 23",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 23 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 24",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
onClick: () => console.log("Channel 24 clicked"),
|
||||
},
|
||||
{
|
||||
text: "Channel 25",
|
||||
icon: <i className="fa-sharp fa-solid fa-wave"></i>,
|
||||
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 (
|
||||
<div className="layout">
|
||||
<div className="chat-view">
|
||||
{columns.map((column, index) => (
|
||||
<div
|
||||
key={index}
|
||||
@ -256,8 +31,12 @@ const Layout = ({ columns }) => {
|
||||
{column.content}
|
||||
</div>
|
||||
))}
|
||||
<List items={channels}></List>
|
||||
<div className="chat-section">
|
||||
<List items={messages} renderItem={<ChatItem />}></List>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
export { ChatView };
|
||||
|
Loading…
Reference in New Issue
Block a user