mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-11 13:23:06 +01:00
styling
This commit is contained in:
parent
87255cf688
commit
af175f68e2
frontend/app/element
@ -9,22 +9,28 @@
|
||||
.list-item {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.list-item-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.list-item-button.clickable {
|
||||
&:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
.list-item-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-item-icon {
|
||||
margin-right: 10px;
|
||||
margin-right: 10px; /* Space between icon and text */
|
||||
}
|
||||
|
||||
.list-item-text {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nested-list {
|
||||
@ -39,3 +45,18 @@
|
||||
.nested-list.closed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-item-button {
|
||||
padding: 10px;
|
||||
color: var(--main-text-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--accent-color);
|
||||
color: var(--button-text-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item-button.clickable:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
import { List } from "./list";
|
||||
import "./list.less";
|
||||
@ -8,36 +11,77 @@ const meta: Meta<typeof List> = {
|
||||
argTypes: {
|
||||
items: { control: "object" },
|
||||
renderItem: { control: false },
|
||||
onClick: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
// Container style for limiting the width to 360px
|
||||
const Container = (props: any) => (
|
||||
<div
|
||||
style={{ width: "360px", margin: "0 auto", border: "1px solid #ccc", padding: "10px", boxSizing: "border-box" }}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const basicItems = [
|
||||
{ text: "Inbox", icon: <i className="fa-sharp fa-solid fa-inbox"></i>, link: "/inbox" },
|
||||
{ text: "Sent Mail", icon: <i className="fa-sharp fa-solid fa-paper-plane"></i>, link: "/sent" },
|
||||
{ text: "Drafts", icon: <i className="fa-sharp fa-solid fa-drafting-compass"></i>, link: "/drafts" },
|
||||
{
|
||||
text: "Inbox",
|
||||
icon: <i className="fa-sharp fa-solid fa-inbox"></i>,
|
||||
onClick: () => console.log("Inbox clicked"),
|
||||
},
|
||||
{
|
||||
text: "Sent Mail",
|
||||
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"),
|
||||
},
|
||||
];
|
||||
|
||||
const nestedItems = [
|
||||
{
|
||||
text: "Inbox",
|
||||
icon: <i className="fa-sharp fa-solid fa-inbox"></i>,
|
||||
onClick: () => console.log("Inbox clicked"),
|
||||
children: [
|
||||
{ text: "Starred", icon: <i className="fa-sharp fa-solid fa-star"></i> },
|
||||
{ text: "Important", icon: <i className="fa-sharp fa-solid fa-star"></i> },
|
||||
{
|
||||
text: "Starred",
|
||||
icon: <i className="fa-sharp fa-solid fa-star"></i>,
|
||||
onClick: () => console.log("Starred clicked"),
|
||||
},
|
||||
{
|
||||
text: "Important",
|
||||
icon: <i className="fa-sharp fa-solid fa-star"></i>,
|
||||
onClick: () => console.log("Important clicked"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{ text: "Sent Mail", icon: <i className="fa-sharp fa-solid fa-paper-plane"></i>, link: "/sent" },
|
||||
{ text: "Drafts", icon: <i className="fa-sharp fa-solid fa-drafting-compass"></i>, link: "/drafts" },
|
||||
{
|
||||
text: "Sent Mail",
|
||||
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"),
|
||||
},
|
||||
];
|
||||
|
||||
const customRenderItem = (item: any, isOpen: boolean, handleClick: () => void) => (
|
||||
<div className="custom-list-item" onClick={handleClick}>
|
||||
<span className="custom-list-item-icon">{item.icon}</span>
|
||||
<span className="custom-list-item-text">{item.link ? <a href={item.link}>{item.text}</a> : item.text}</span>
|
||||
<div className="custom-list-item">
|
||||
<span className="custom-list-item-icon" onClick={handleClick}>
|
||||
{item.icon}
|
||||
</span>
|
||||
<span className="custom-list-item-text" onClick={handleClick}>
|
||||
{item.text}
|
||||
</span>
|
||||
{item.children && <i className={`fa-sharp fa-solid ${isOpen ? "fa-angle-up" : "fa-angle-down"}`}></i>}
|
||||
</div>
|
||||
);
|
||||
@ -46,12 +90,22 @@ export const Default: Story = {
|
||||
args: {
|
||||
items: basicItems,
|
||||
},
|
||||
render: (args) => (
|
||||
<Container>
|
||||
<List {...args} />
|
||||
</Container>
|
||||
),
|
||||
};
|
||||
|
||||
export const NestedList: Story = {
|
||||
args: {
|
||||
items: nestedItems,
|
||||
},
|
||||
render: (args) => (
|
||||
<Container>
|
||||
<List {...args} />
|
||||
</Container>
|
||||
),
|
||||
};
|
||||
|
||||
export const CustomRender: Story = {
|
||||
@ -59,18 +113,31 @@ export const CustomRender: Story = {
|
||||
items: nestedItems,
|
||||
renderItem: customRenderItem,
|
||||
},
|
||||
render: (args) => (
|
||||
<Container>
|
||||
<List {...args} />
|
||||
</Container>
|
||||
),
|
||||
};
|
||||
|
||||
export const WithClickHandlers: Story = {
|
||||
args: {
|
||||
items: basicItems,
|
||||
onClick: (item) => alert(`Item clicked: ${item.text}`),
|
||||
},
|
||||
render: (args) => (
|
||||
<Container>
|
||||
<List {...args} />
|
||||
</Container>
|
||||
),
|
||||
};
|
||||
|
||||
export const NestedWithClickHandlers: Story = {
|
||||
args: {
|
||||
items: nestedItems,
|
||||
onClick: (item) => alert(`Item clicked: ${item.text}`),
|
||||
},
|
||||
render: (args) => (
|
||||
<Container>
|
||||
<List {...args} />
|
||||
</Container>
|
||||
),
|
||||
};
|
||||
|
@ -1,30 +1,30 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import clsx from "clsx";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import "./list.less"; // Assuming you have your LESS styles
|
||||
import "./list.less";
|
||||
|
||||
interface ListItem {
|
||||
text: string;
|
||||
icon: React.ReactNode;
|
||||
link?: string;
|
||||
children?: ListItem[];
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
interface ListProps {
|
||||
items: ListItem[];
|
||||
className?: string;
|
||||
renderItem?: (item: ListItem, isOpen: boolean, handleClick: () => void) => React.ReactNode;
|
||||
onClick?: (item: ListItem) => void;
|
||||
}
|
||||
|
||||
const List = ({ items, renderItem, onClick }: ListProps) => {
|
||||
const List = ({ items, className, renderItem }: ListProps) => {
|
||||
const [open, setOpen] = useState<{ [key: string]: boolean }>({});
|
||||
|
||||
const handleClick = (item: ListItem) => {
|
||||
setOpen((prevState) => ({ ...prevState, [item.text]: !prevState[item.text] }));
|
||||
if (onClick) {
|
||||
onClick(item); // Notify the consumer that the item was clicked
|
||||
if (item.onClick) {
|
||||
item.onClick();
|
||||
}
|
||||
};
|
||||
|
||||
@ -33,15 +33,15 @@ const List = ({ items, renderItem, onClick }: ListProps) => {
|
||||
const hasChildren = item.children && item.children.length > 0;
|
||||
|
||||
return (
|
||||
<li key={index} className="list-item">
|
||||
<li key={index} className={clsx("list-item", className)}>
|
||||
{renderItem ? (
|
||||
renderItem(item, isOpen, () => handleClick(item))
|
||||
) : (
|
||||
<div className="list-item-button" onClick={() => handleClick(item)}>
|
||||
<span className="list-item-icon">{item.icon}</span>
|
||||
<span className="list-item-text">
|
||||
{item.link ? <a href={item.link}>{item.text}</a> : item.text}
|
||||
</span>
|
||||
<div className="list-item-content">
|
||||
<div className="list-item-icon">{item.icon}</div>
|
||||
<div className="list-item-text">{item.text}</div>
|
||||
</div>
|
||||
{hasChildren && (
|
||||
<i className={`fa-sharp fa-solid ${isOpen ? "fa-angle-up" : "fa-angle-down"}`}></i>
|
||||
)}
|
||||
|
@ -147,7 +147,6 @@ export const DefaultRendererLeftPositioned: Story = {
|
||||
},
|
||||
args: {
|
||||
items: items,
|
||||
isVisible: false,
|
||||
},
|
||||
};
|
||||
|
||||
@ -209,7 +208,6 @@ export const DefaultRendererRightPositioned: Story = {
|
||||
},
|
||||
args: {
|
||||
items: items,
|
||||
isVisible: false,
|
||||
},
|
||||
};
|
||||
|
||||
@ -271,7 +269,6 @@ export const DefaultRendererBottomRightPositioned: Story = {
|
||||
},
|
||||
args: {
|
||||
items: items,
|
||||
isVisible: false,
|
||||
},
|
||||
};
|
||||
|
||||
@ -333,7 +330,6 @@ export const DefaultRendererBottomLeftPositioned: Story = {
|
||||
},
|
||||
args: {
|
||||
items: items,
|
||||
isVisible: false,
|
||||
},
|
||||
};
|
||||
|
||||
@ -406,7 +402,6 @@ export const CustomRenderer: Story = {
|
||||
},
|
||||
args: {
|
||||
items: items,
|
||||
isVisible: false,
|
||||
},
|
||||
};
|
||||
|
||||
@ -472,6 +467,5 @@ export const ContextMenu: Story = {
|
||||
},
|
||||
args: {
|
||||
items: items,
|
||||
isVisible: false,
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user