feat: sub menu

This commit is contained in:
Tristan Yang
2023-06-13 21:21:34 +08:00
parent 1ebb8d74ce
commit e415ee1e2e
5 changed files with 116 additions and 5 deletions
+1
View File
@@ -25,6 +25,7 @@
"remove_account": "Remove account",
"remove_account_desc": "Are you sure remove this account?",
"remove_from_channel": "Remove from channel",
"roles": "Roles",
"set_admin": "Set as admin",
"set_normal": "Set as normal user",
+1
View File
@@ -24,6 +24,7 @@
"remove_account": "注销账号",
"remove_account_desc": "确定永久注销该账号?",
"remove_from_channel": "从频道移除",
"roles": "设置角色",
"set_admin": "设置为管理员",
"set_normal": "设置为普通用户",
+8
View File
@@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="#475467" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_18505_74130" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_18505_74130)">
<path d="M4.76666 14.0667C4.6 13.9 4.51666 13.7028 4.51666 13.475C4.51666 13.2472 4.6 13.05 4.76666 12.8834L9.65 8.00002L4.75 3.10002C4.59444 2.94446 4.51666 2.75002 4.51666 2.51669C4.51666 2.28335 4.6 2.08335 4.76666 1.91669C4.93333 1.75002 5.13055 1.66669 5.35833 1.66669C5.58611 1.66669 5.78333 1.75002 5.95 1.91669L11.55 7.53335C11.6167 7.60002 11.6639 7.67224 11.6917 7.75002C11.7194 7.8278 11.7333 7.91113 11.7333 8.00002C11.7333 8.08891 11.7194 8.17224 11.6917 8.25002C11.6639 8.3278 11.6167 8.40002 11.55 8.46669L5.93333 14.0834C5.77777 14.2389 5.58611 14.3167 5.35833 14.3167C5.13055 14.3167 4.93333 14.2334 4.76666 14.0667Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 953 B

+92 -3
View File
@@ -1,18 +1,82 @@
import { FC, ReactElement } from "react";
import Tippy from "@tippyjs/react";
import IconArrow from "@/assets/icons/arrow.right.svg";
import IconChecked from "@/assets/icons/check.sign.svg";
export interface Item {
title: string;
icon?: string | ReactElement;
handler: (param: any) => void;
handler?: (param: any) => void;
underline?: boolean;
danger?: boolean;
checked?: boolean;
subs?: Item[];
}
interface Props {
items: Item[];
hideMenu?: () => void;
}
const WrapWithSubmenu = ({
items,
hideMenu,
child
}: {
items: Item[];
hideMenu: () => void | null;
child: ReactElement;
}) => {
return (
<Tippy
interactive
placement="right-start"
trigger="mouseenter focus"
content={
<ul className="context-menu">
{items.map((sub) => {
const {
title,
icon = null,
handler = (evt) => {
evt.preventDefault();
if (hideMenu) {
hideMenu();
}
},
underline = false,
danger = false,
checked = false
} = sub;
return (
<li
className={`item ${underline ? "bottom_line" : ""} ${danger ? "danger" : ""}`}
key={title}
onClick={(evt) => {
evt.stopPropagation();
evt.preventDefault();
if (checked) return;
handler(evt);
if (hideMenu) {
hideMenu();
}
}}
>
{icon}
{title}
{checked && (
<IconChecked className="group-hover:fill-white dark:fill-gray-300 absolute right-2 top-2" />
)}
</li>
);
})}
</ul>
}
>
{child}
</Tippy>
);
};
const ContextMenu: FC<Props> = ({ items = [], hideMenu = null }) => {
return (
<ul className="context-menu">
@@ -28,8 +92,33 @@ const ContextMenu: FC<Props> = ({ items = [], hideMenu = null }) => {
}
},
underline = false,
danger = false
danger = false,
subs = []
} = item;
if (subs.length > 0)
return (
<WrapWithSubmenu
items={subs}
hideMenu={hideMenu}
child={
<li
className={`item group ${underline ? "bottom_line" : ""} ${
danger ? "danger" : ""
}`}
key={title}
onClick={(evt) => {
evt.stopPropagation();
evt.preventDefault();
}}
>
{icon}
{title}
<IconArrow className="group-hover:fill-white dark:fill-gray-300 absolute right-2 top-2" />
</li>
}
></WrapWithSubmenu>
);
return (
<li
className={`item ${underline ? "bottom_line" : ""} ${danger ? "danger" : ""}`}
+14 -2
View File
@@ -60,8 +60,20 @@ const UserContextMenu: FC<Props> = ({ enable = false, uid, cid, visible, hide, c
handler: copyEmail
},
canUpdateRole && {
title: isAdmin ? t("set_normal") : t("set_admin"),
handler: updateRole
title: t("roles"),
handler: updateRole,
subs: [
{
title: t("set_normal"),
checked: !isAdmin,
handler: updateRole
},
{
title: t("set_admin"),
checked: isAdmin,
handler: updateRole
}
]
},
canRemoveFromChannel && {
danger: true,