mirror of https://github.com/usememos/memos.git
chore: use popover instead of dropdown/menu
This commit is contained in:
parent
522da2a114
commit
f2a01d9ccb
|
|
@ -1,4 +1,4 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem, Tooltip } from "@mui/joy";
|
||||
import { Tooltip } from "@mui/joy";
|
||||
import { Edit3Icon, MoreVerticalIcon, TrashIcon, PlusIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { shortcutServiceClient } from "@/grpcweb";
|
||||
|
|
@ -10,6 +10,7 @@ import { Shortcut } from "@/types/proto/api/v1/shortcut_service";
|
|||
import { cn } from "@/utils";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import showCreateShortcutDialog from "../CreateShortcutDialog";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/Popover";
|
||||
|
||||
const emojiRegex = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F)$/u;
|
||||
|
||||
|
|
@ -56,21 +57,29 @@ const ShortcutsSection = observer(() => {
|
|||
{emoji && <span className="text-base mr-1">{emoji}</span>}
|
||||
{title.trim()}
|
||||
</span>
|
||||
<Dropdown>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<MoreVerticalIcon className="w-4 h-auto shrink-0 opacity-40" />
|
||||
</MenuButton>
|
||||
<Menu size="sm" placement="bottom-start">
|
||||
<MenuItem onClick={() => showCreateShortcutDialog({ shortcut })}>
|
||||
<Edit3Icon className="w-4 h-auto" />
|
||||
{t("common.edit")}
|
||||
</MenuItem>
|
||||
<MenuItem color="danger" onClick={() => handleDeleteShortcut(shortcut)}>
|
||||
<TrashIcon className="w-4 h-auto" />
|
||||
{t("common.delete")}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<MoreVerticalIcon className="w-4 h-auto shrink-0 opacity-40 cursor-pointer hover:opacity-70" />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" sideOffset={2}>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<button
|
||||
onClick={() => showCreateShortcutDialog({ shortcut })}
|
||||
className="flex items-center gap-1 px-2 py-1 text-sm text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<Edit3Icon className="w-4 h-auto" />
|
||||
{t("common.edit")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteShortcut(shortcut)}
|
||||
className="flex items-center gap-1 px-2 py-1 text-sm text-left text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<TrashIcon className="w-4 h-auto" />
|
||||
{t("common.delete")}
|
||||
</button>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||
import { Switch } from "@usememos/mui";
|
||||
import { Edit3Icon, HashIcon, MoreVerticalIcon, TagsIcon, TrashIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
|
@ -75,24 +74,32 @@ const TagsSection = observer((props: Props) => {
|
|||
key={tag}
|
||||
className="shrink-0 w-auto max-w-full text-sm rounded-md leading-6 flex flex-row justify-start items-center select-none hover:opacity-80 text-gray-600 dark:text-gray-400 dark:border-zinc-800"
|
||||
>
|
||||
<Dropdown>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<div className="shrink-0 group">
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<div className="shrink-0 group cursor-pointer">
|
||||
<HashIcon className="group-hover:hidden w-4 h-auto shrink-0 opacity-40" />
|
||||
<MoreVerticalIcon className="hidden group-hover:block w-4 h-auto shrink-0 opacity-60" />
|
||||
</div>
|
||||
</MenuButton>
|
||||
<Menu size="sm" placement="bottom-start">
|
||||
<MenuItem onClick={() => showRenameTagDialog({ tag: tag })}>
|
||||
<Edit3Icon className="w-4 h-auto" />
|
||||
{t("common.rename")}
|
||||
</MenuItem>
|
||||
<MenuItem color="danger" onClick={() => handleDeleteTag(tag)}>
|
||||
<TrashIcon className="w-4 h-auto" />
|
||||
{t("common.delete")}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" sideOffset={2}>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<button
|
||||
onClick={() => showRenameTagDialog({ tag: tag })}
|
||||
className="flex items-center gap-1 px-2 py-1 text-sm text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<Edit3Icon className="w-4 h-auto" />
|
||||
{t("common.rename")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteTag(tag)}
|
||||
className="flex items-center gap-1 px-2 py-1 text-sm text-left text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<TrashIcon className="w-4 h-auto" />
|
||||
{t("common.delete")}
|
||||
</button>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<div
|
||||
className={cn("inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]")}
|
||||
onClick={() => handleTagClick(tag)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||
import copy from "copy-to-clipboard";
|
||||
import {
|
||||
ArchiveIcon,
|
||||
|
|
@ -22,6 +21,7 @@ import { NodeType } from "@/types/proto/api/v1/markdown_service";
|
|||
import { Memo } from "@/types/proto/api/v1/memo_service";
|
||||
import { cn } from "@/utils";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "./ui/Popover";
|
||||
|
||||
interface Props {
|
||||
memo: Memo;
|
||||
|
|
@ -163,55 +163,75 @@ const MemoActionMenu = observer((props: Props) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Dropdown>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<span className={cn("flex justify-center items-center rounded-full hover:opacity-70", props.className)}>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<span className={cn("flex justify-center items-center rounded-full hover:opacity-70 cursor-pointer", props.className)}>
|
||||
<MoreVerticalIcon className="w-4 h-4 mx-auto text-gray-500 dark:text-gray-400" />
|
||||
</span>
|
||||
</MenuButton>
|
||||
<Menu className="text-sm" size="sm" placement="bottom-end">
|
||||
{!readonly && !isArchived && (
|
||||
<>
|
||||
{!isComment && (
|
||||
<MenuItem onClick={handleTogglePinMemoBtnClick}>
|
||||
{memo.pinned ? <BookmarkMinusIcon className="w-4 h-auto" /> : <BookmarkPlusIcon className="w-4 h-auto" />}
|
||||
{memo.pinned ? t("common.unpin") : t("common.pin")}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={handleEditMemoClick}>
|
||||
<Edit3Icon className="w-4 h-auto" />
|
||||
{t("common.edit")}
|
||||
</MenuItem>
|
||||
</>
|
||||
)}
|
||||
{!isArchived && (
|
||||
<MenuItem onClick={handleCopyLink}>
|
||||
<CopyIcon className="w-4 h-auto" />
|
||||
{t("memo.copy-link")}
|
||||
</MenuItem>
|
||||
)}
|
||||
{!readonly && (
|
||||
<>
|
||||
{!isArchived && !isComment && hasCompletedTaskList && (
|
||||
<MenuItem color="warning" onClick={handleRemoveCompletedTaskListItemsClick}>
|
||||
<SquareCheckIcon className="w-4 h-auto" />
|
||||
{t("memo.remove-completed-task-list-items")}
|
||||
</MenuItem>
|
||||
)}
|
||||
{!isComment && (
|
||||
<MenuItem color="warning" onClick={handleToggleMemoStatusClick}>
|
||||
{isArchived ? <ArchiveRestoreIcon className="w-4 h-auto" /> : <ArchiveIcon className="w-4 h-auto" />}
|
||||
{isArchived ? t("common.restore") : t("common.archive")}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem color="danger" onClick={handleDeleteMemoClick}>
|
||||
<TrashIcon className="w-4 h-auto" />
|
||||
{t("common.delete")}
|
||||
</MenuItem>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" sideOffset={2}>
|
||||
<div className="flex flex-col text-sm gap-0.5">
|
||||
{!readonly && !isArchived && (
|
||||
<>
|
||||
{!isComment && (
|
||||
<button
|
||||
onClick={handleTogglePinMemoBtnClick}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{memo.pinned ? <BookmarkMinusIcon className="w-4 h-auto" /> : <BookmarkPlusIcon className="w-4 h-auto" />}
|
||||
{memo.pinned ? t("common.unpin") : t("common.pin")}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={handleEditMemoClick}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<Edit3Icon className="w-4 h-auto" />
|
||||
{t("common.edit")}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{!isArchived && (
|
||||
<button
|
||||
onClick={handleCopyLink}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<CopyIcon className="w-4 h-auto" />
|
||||
{t("memo.copy-link")}
|
||||
</button>
|
||||
)}
|
||||
{!readonly && (
|
||||
<>
|
||||
{!isArchived && !isComment && hasCompletedTaskList && (
|
||||
<button
|
||||
onClick={handleRemoveCompletedTaskListItemsClick}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left text-amber-600 dark:text-amber-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<SquareCheckIcon className="w-4 h-auto" />
|
||||
{t("memo.remove-completed-task-list-items")}
|
||||
</button>
|
||||
)}
|
||||
{!isComment && (
|
||||
<button
|
||||
onClick={handleToggleMemoStatusClick}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left text-amber-600 dark:text-amber-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{isArchived ? <ArchiveRestoreIcon className="w-4 h-auto" /> : <ArchiveIcon className="w-4 h-auto" />}
|
||||
{isArchived ? t("common.restore") : t("common.archive")}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={handleDeleteMemoClick}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
<TrashIcon className="w-4 h-auto" />
|
||||
{t("common.delete")}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const MemoDisplaySettingMenu = observer(({ className }: Props) => {
|
|||
<Settings2Icon className="w-4 h-auto shrink-0" />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" alignOffset={-12} sideOffset={14}>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-col gap-2 p-1">
|
||||
<div className="w-full flex flex-row justify-between items-center">
|
||||
<span className="text-sm shrink-0 mr-3 dark:text-zinc-400">{t("memo.direction")}</span>
|
||||
<Select
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem, Link } from "@mui/joy";
|
||||
import { Link } from "@mui/joy";
|
||||
import { Button } from "@usememos/mui";
|
||||
import { CheckSquareIcon, Code2Icon, SquareSlashIcon } from "lucide-react";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/Popover";
|
||||
import { EditorRefActions } from "../Editor";
|
||||
|
||||
interface Props {
|
||||
|
|
@ -61,28 +62,34 @@ const MarkdownMenu = (props: Props) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Dropdown>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="plain" className="p-0">
|
||||
<SquareSlashIcon className="w-5 h-5" />
|
||||
</Button>
|
||||
</MenuButton>
|
||||
<Menu className="text-sm" size="sm" placement="bottom-start">
|
||||
<MenuItem onClick={handleCodeBlockClick}>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="text-sm p-1">
|
||||
<button
|
||||
onClick={handleCodeBlockClick}
|
||||
className="w-full flex items-center gap-2 px-2 py-1.5 text-left text-sm hover:bg-gray-100 rounded-md"
|
||||
>
|
||||
<Code2Icon className="w-4 h-auto" />
|
||||
<span>{t("markdown.code-block")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleCheckboxClick}>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCheckboxClick}
|
||||
className="w-full flex items-center gap-2 px-2 py-1.5 text-left text-sm hover:bg-gray-100 rounded-md"
|
||||
>
|
||||
<CheckSquareIcon className="w-4 h-auto" />
|
||||
<span>{t("markdown.checkbox")}</span>
|
||||
</MenuItem>
|
||||
</button>
|
||||
<div className="-mt-0.5 pl-2">
|
||||
<Link fontSize={12} href="https://www.usememos.com/docs/getting-started/content-syntax" target="_blank">
|
||||
{t("markdown.content-syntax")}
|
||||
</Link>
|
||||
</div>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Dropdown, Menu, MenuButton } from "@mui/joy";
|
||||
import { Button } from "@usememos/mui";
|
||||
import { HashIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
|
@ -7,6 +6,7 @@ import useClickAway from "react-use/lib/useClickAway";
|
|||
import OverflowTip from "@/components/kit/OverflowTip";
|
||||
import { userStore } from "@/store/v2";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/Popover";
|
||||
import { EditorRefActions } from "../Editor";
|
||||
|
||||
interface Props {
|
||||
|
|
@ -41,13 +41,13 @@ const TagSelector = observer((props: Props) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Dropdown open={open} onOpenChange={(_, isOpen) => setOpen(isOpen)}>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="plain" className="p-0">
|
||||
<HashIcon className="w-5 h-5" />
|
||||
</Button>
|
||||
</MenuButton>
|
||||
<Menu className="relative" component="div" size="sm" placement="bottom-start">
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" sideOffset={2}>
|
||||
<div ref={containerRef}>
|
||||
{tags.length > 0 ? (
|
||||
<div className="flex flex-row justify-start items-start flex-wrap px-3 py-1 max-w-48 h-auto max-h-48 overflow-y-auto gap-x-2 gap-y-1">
|
||||
|
|
@ -69,8 +69,8 @@ const TagSelector = observer((props: Props) => {
|
|||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Dropdown, Menu, MenuButton } from "@mui/joy";
|
||||
import { SmilePlusIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useRef, useState } from "react";
|
||||
|
|
@ -8,6 +7,7 @@ import useCurrentUser from "@/hooks/useCurrentUser";
|
|||
import { memoStore, workspaceStore } from "@/store/v2";
|
||||
import { Memo } from "@/types/proto/api/v1/memo_service";
|
||||
import { cn } from "@/utils";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "./ui/Popover";
|
||||
|
||||
interface Props {
|
||||
memo: Memo;
|
||||
|
|
@ -55,18 +55,18 @@ const ReactionSelector = observer((props: Props) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Dropdown open={open} onOpenChange={(_, isOpen) => setOpen(isOpen)}>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<span
|
||||
className={cn(
|
||||
"h-7 w-7 flex justify-center items-center rounded-full border border-zinc-200 dark:border-zinc-700 hover:opacity-70",
|
||||
"h-7 w-7 flex justify-center items-center rounded-full border border-zinc-200 dark:border-zinc-700 hover:opacity-70 cursor-pointer",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<SmilePlusIcon className="w-4 h-4 mx-auto text-gray-500 dark:text-gray-400" />
|
||||
</span>
|
||||
</MenuButton>
|
||||
<Menu className="relative" component="div" size="sm" placement="bottom-start">
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" sideOffset={2}>
|
||||
<div ref={containerRef}>
|
||||
<div className="flex flex-row flex-wrap py-0.5 px-2 h-auto gap-1 max-w-56">
|
||||
{workspaceMemoRelatedSetting.reactions.map((reactionType) => {
|
||||
|
|
@ -85,8 +85,8 @@ const ReactionSelector = observer((props: Props) => {
|
|||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem, Radio, RadioGroup } from "@mui/joy";
|
||||
import { Radio, RadioGroup } from "@mui/joy";
|
||||
import { Button, Input } from "@usememos/mui";
|
||||
import { sortBy } from "lodash-es";
|
||||
import { MoreVerticalIcon } from "lucide-react";
|
||||
|
|
@ -12,6 +12,7 @@ import { State } from "@/types/proto/api/v1/common";
|
|||
import { User, User_Role } from "@/types/proto/api/v1/user_service";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import showCreateUserDialog from "../CreateUserDialog";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/Popover";
|
||||
|
||||
interface LocalState {
|
||||
creatingUser: User;
|
||||
|
|
@ -214,22 +215,46 @@ const MemberSection = observer(() => {
|
|||
{currentUser?.name === user.name ? (
|
||||
<span>{t("common.yourself")}</span>
|
||||
) : (
|
||||
<Dropdown>
|
||||
<MenuButton size="sm">
|
||||
<MoreVerticalIcon className="w-4 h-auto" />
|
||||
</MenuButton>
|
||||
<Menu placement="bottom-end" size="sm">
|
||||
<MenuItem onClick={() => showCreateUserDialog(user, () => fetchUsers())}>{t("common.update")}</MenuItem>
|
||||
{user.state === State.NORMAL ? (
|
||||
<MenuItem onClick={() => handleArchiveUserClick(user)}>{t("setting.member-section.archive-member")}</MenuItem>
|
||||
) : (
|
||||
<>
|
||||
<MenuItem onClick={() => handleRestoreUserClick(user)}>{t("common.restore")}</MenuItem>
|
||||
<MenuItem onClick={() => handleDeleteUserClick(user)}>{t("setting.member-section.delete-member")}</MenuItem>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button className="flex items-center justify-center p-1 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded">
|
||||
<MoreVerticalIcon className="w-4 h-auto" />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" sideOffset={2}>
|
||||
<div className="flex flex-col gap-0.5 text-sm">
|
||||
<button
|
||||
onClick={() => showCreateUserDialog(user, () => fetchUsers())}
|
||||
className="flex items-center gap-2 px-2 py-1.5 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{t("common.update")}
|
||||
</button>
|
||||
{user.state === State.NORMAL ? (
|
||||
<button
|
||||
onClick={() => handleArchiveUserClick(user)}
|
||||
className="flex items-center gap-2 px-2 py-1.5 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{t("setting.member-section.archive-member")}
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
onClick={() => handleRestoreUserClick(user)}
|
||||
className="flex items-center gap-2 px-2 py-1.5 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{t("common.restore")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteUserClick(user)}
|
||||
className="flex items-center gap-2 px-2 py-1.5 text-left text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{t("setting.member-section.delete-member")}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||
import { Button } from "@usememos/mui";
|
||||
import { MoreVerticalIcon, PenLineIcon } from "lucide-react";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
|
|
@ -6,6 +5,7 @@ import { useTranslate } from "@/utils/i18n";
|
|||
import showChangeMemberPasswordDialog from "../ChangeMemberPasswordDialog";
|
||||
import showUpdateAccountDialog from "../UpdateAccountDialog";
|
||||
import UserAvatar from "../UserAvatar";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/Popover";
|
||||
import AccessTokenSection from "./AccessTokenSection";
|
||||
|
||||
const MyAccountSection = () => {
|
||||
|
|
@ -30,16 +30,21 @@ const MyAccountSection = () => {
|
|||
<PenLineIcon className="w-4 h-4 mx-auto mr-1" />
|
||||
{t("common.edit")}
|
||||
</Button>
|
||||
<Dropdown>
|
||||
<MenuButton slots={{ root: "div" }}>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outlined">
|
||||
<MoreVerticalIcon className="w-4 h-4 mx-auto" />
|
||||
</Button>
|
||||
</MenuButton>
|
||||
<Menu className="text-sm" size="sm" placement="bottom">
|
||||
<MenuItem onClick={() => showChangeMemberPasswordDialog(user)}>{t("setting.account-section.change-password")}</MenuItem>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="text-sm p-1">
|
||||
<button
|
||||
onClick={() => showChangeMemberPasswordDialog(user)}
|
||||
className="w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-gray-100 rounded-md"
|
||||
>
|
||||
{t("setting.account-section.change-password")}
|
||||
</button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
<AccessTokenSection />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Divider, Dropdown, List, ListItem, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||
import { Divider, List, ListItem } from "@mui/joy";
|
||||
import { Button } from "@usememos/mui";
|
||||
import { MoreVerticalIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
|
@ -9,6 +9,7 @@ import { IdentityProvider } from "@/types/proto/api/v1/idp_service";
|
|||
import { useTranslate } from "@/utils/i18n";
|
||||
import showCreateIdentityProviderDialog from "../CreateIdentityProviderDialog";
|
||||
import LearnMore from "../LearnMore";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/Popover";
|
||||
|
||||
const SSOSection = () => {
|
||||
const t = useTranslate();
|
||||
|
|
@ -60,17 +61,29 @@ const SSOSection = () => {
|
|||
</p>
|
||||
</div>
|
||||
<div className="flex flex-row items-center">
|
||||
<Dropdown>
|
||||
<MenuButton size="sm">
|
||||
<MoreVerticalIcon className="w-4 h-auto" />
|
||||
</MenuButton>
|
||||
<Menu placement="bottom-end" size="sm">
|
||||
<MenuItem onClick={() => showCreateIdentityProviderDialog(identityProvider, fetchIdentityProviderList)}>
|
||||
{t("common.edit")}
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => handleDeleteIdentityProvider(identityProvider)}>{t("common.delete")}</MenuItem>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button className="flex items-center justify-center p-1 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded">
|
||||
<MoreVerticalIcon className="w-4 h-auto" />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" sideOffset={2}>
|
||||
<div className="flex flex-col gap-0.5 text-sm">
|
||||
<button
|
||||
onClick={() => showCreateIdentityProviderDialog(identityProvider, fetchIdentityProviderList)}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{t("common.edit")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDeleteIdentityProvider(identityProvider)}
|
||||
className="flex items-center gap-2 px-2 py-1 text-left text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-zinc-700 outline-none rounded transition-colors"
|
||||
>
|
||||
{t("common.delete")}
|
||||
</button>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||
import { ArchiveIcon, LogOutIcon, User2Icon, SquareUserIcon, SettingsIcon, BellIcon } from "lucide-react";
|
||||
import { authServiceClient } from "@/grpcweb";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
|
|
@ -7,6 +6,7 @@ import { Routes } from "@/router";
|
|||
import { cn } from "@/utils";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import UserAvatar from "./UserAvatar";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "./ui/Popover";
|
||||
|
||||
interface Props {
|
||||
collapsed?: boolean;
|
||||
|
|
@ -25,8 +25,8 @@ const UserBanner = (props: Props) => {
|
|||
|
||||
return (
|
||||
<div className="relative w-full h-auto px-1 shrink-0">
|
||||
<Dropdown>
|
||||
<MenuButton disabled={!currentUser} slots={{ root: "div" }}>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild disabled={!currentUser}>
|
||||
<div
|
||||
className={cn(
|
||||
"w-auto flex flex-row justify-start items-center cursor-pointer text-gray-800 dark:text-gray-400",
|
||||
|
|
@ -44,30 +44,45 @@ const UserBanner = (props: Props) => {
|
|||
</span>
|
||||
)}
|
||||
</div>
|
||||
</MenuButton>
|
||||
<Menu size="sm" placement="bottom-start" style={{ zIndex: "9999" }}>
|
||||
<MenuItem onClick={() => navigateTo(`/u/${encodeURIComponent(currentUser.username)}`)}>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="p-1" style={{ zIndex: "9999" }}>
|
||||
<button
|
||||
onClick={() => navigateTo(`/u/${encodeURIComponent(currentUser.username)}`)}
|
||||
className="w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-gray-100 rounded-md outline-none"
|
||||
>
|
||||
<SquareUserIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.profile")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigateTo(Routes.ARCHIVED)}>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => navigateTo(Routes.ARCHIVED)}
|
||||
className="w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-gray-100 rounded-md outline-none"
|
||||
>
|
||||
<ArchiveIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.archived")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigateTo(Routes.INBOX)}>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => navigateTo(Routes.INBOX)}
|
||||
className="w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-gray-100 rounded-md outline-none"
|
||||
>
|
||||
<BellIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.inbox")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigateTo(Routes.SETTING)}>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => navigateTo(Routes.SETTING)}
|
||||
className="w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-gray-100 rounded-md outline-none"
|
||||
>
|
||||
<SettingsIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.settings")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleSignOut}>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSignOut}
|
||||
className="w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-gray-100 rounded-md outline-none"
|
||||
>
|
||||
<LogOutIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.sign-out")}</span>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const PopoverContent = React.forwardRef<
|
|||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-2000 w-auto rounded-md bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 p-2 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"z-2000 w-auto rounded-md bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 p-1 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
Loading…
Reference in New Issue