chore: refactor dialog components to simplify header structure

- Removed unnecessary button and icon from dialog headers in AboutDialog, ChangePasswordDialog, CreateAccessTokenDialog, CreateUserDialog, EditUserinfoDialog, and GenerateQRCodeDialog.
- Updated dialog titles to be more straightforward by directly displaying the title text.
- Simplified close button handling in ChangePasswordDialog, EditUserinfoDialog, and GenerateQRCodeDialog by directly using the onClose prop.
- Enhanced Dropdown component to manage its open state internally.
This commit is contained in:
Johnny
2025-12-21 21:22:10 +08:00
parent 347532ff75
commit 73d83de323
8 changed files with 16 additions and 2057 deletions
File diff suppressed because it is too large Load Diff
+1 -8
View File
@@ -1,7 +1,5 @@
import { useTranslation } from "react-i18next";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import Icon from "./Icon";
interface Props {
onClose: () => void;
@@ -15,12 +13,7 @@ const AboutDialog: React.FC<Props> = (props: Props) => {
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="max-w-full w-80 sm:w-96">
<DialogHeader>
<DialogTitle className="flex flex-row justify-between items-center">
<span>{t("common.about")}</span>
<Button variant="ghost" size="icon" onClick={onClose}>
<Icon.X className="w-5 h-auto" />
</Button>
</DialogTitle>
<DialogTitle>{t("common.about")}</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<p>
@@ -7,7 +7,6 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import useLoading from "@/hooks/useLoading";
import { useUserStore } from "@/stores";
import Icon from "./Icon";
interface Props {
onClose: () => void;
@@ -21,10 +20,6 @@ const ChangePasswordDialog: React.FC<Props> = (props: Props) => {
const [newPasswordAgain, setNewPasswordAgain] = useState("");
const requestState = useLoading(false);
const handleCloseBtnClick = () => {
onClose();
};
const handleNewPasswordChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value as string;
setNewPassword(text);
@@ -69,12 +64,7 @@ const ChangePasswordDialog: React.FC<Props> = (props: Props) => {
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="w-80 sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex flex-row justify-between items-center">
<span>Change Password</span>
<Button variant="ghost" size="icon" onClick={handleCloseBtnClick}>
<Icon.X className="w-5 h-auto" />
</Button>
</DialogTitle>
<DialogTitle>Change Password</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
@@ -87,7 +77,7 @@ const ChangePasswordDialog: React.FC<Props> = (props: Props) => {
</div>
</div>
<DialogFooter>
<Button variant="outline" disabled={requestState.isLoading} onClick={handleCloseBtnClick}>
<Button variant="outline" disabled={requestState.isLoading} onClick={onClose}>
{t("common.cancel")}
</Button>
<Button disabled={requestState.isLoading} onClick={handleSaveBtnClick}>
@@ -9,7 +9,6 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { userServiceClient } from "@/grpcweb";
import useLoading from "@/hooks/useLoading";
import { useUserStore } from "@/stores";
import Icon from "./Icon";
interface Props {
onClose: () => void;
@@ -92,12 +91,7 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="w-80 sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex flex-row justify-between items-center">
<span>Create Access Token</span>
<Button variant="ghost" size="icon" onClick={onClose}>
<Icon.X className="w-5 h-auto" />
</Button>
</DialogTitle>
<DialogTitle>Create Access Token</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
@@ -9,8 +9,7 @@ import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import useLoading from "@/hooks/useLoading";
import { useUserStore } from "@/stores";
import { Role, User } from "@/types/proto/api/v1/user_service";
import Icon from "./Icon";
import { Role, type User } from "@/types/proto/api/v1/user_service";
interface Props {
user?: User;
@@ -134,12 +133,7 @@ const CreateUserDialog: React.FC<Props> = (props: Props) => {
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="w-80 sm:w-96">
<DialogHeader>
<DialogTitle className="flex flex-row justify-between items-center">
<span>{isCreating ? "Create User" : "Edit User"}</span>
<Button variant="ghost" size="icon" onClick={onClose}>
<Icon.X className="w-5 h-auto" />
</Button>
</DialogTitle>
<DialogTitle>{isCreating ? "Create User" : "Edit User"}</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
@@ -7,7 +7,6 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import useLoading from "@/hooks/useLoading";
import { useUserStore } from "@/stores";
import Icon from "./Icon";
interface Props {
onClose: () => void;
@@ -22,10 +21,6 @@ const EditUserinfoDialog: React.FC<Props> = (props: Props) => {
const [nickname, setNickname] = useState(currentUser.nickname);
const requestState = useLoading(false);
const handleCloseBtnClick = () => {
onClose();
};
const handleEmailChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value as string;
setEmail(text);
@@ -65,12 +60,7 @@ const EditUserinfoDialog: React.FC<Props> = (props: Props) => {
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="w-80 sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex flex-row justify-between items-center">
<span>Edit Userinfo</span>
<Button variant="ghost" size="icon" onClick={handleCloseBtnClick}>
<Icon.X className="w-5 h-auto" />
</Button>
</DialogTitle>
<DialogTitle>Edit Userinfo</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
@@ -83,7 +73,7 @@ const EditUserinfoDialog: React.FC<Props> = (props: Props) => {
</div>
</div>
<DialogFooter>
<Button variant="outline" disabled={requestState.isLoading} onClick={handleCloseBtnClick}>
<Button variant="outline" disabled={requestState.isLoading} onClick={onClose}>
{t("common.cancel")}
</Button>
<Button disabled={requestState.isLoading} onClick={handleSaveBtnClick}>
@@ -5,7 +5,7 @@ import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { absolutifyLink } from "@/helpers/utils";
import { Shortcut } from "@/types/proto/api/v1/shortcut_service";
import type { Shortcut } from "@/types/proto/api/v1/shortcut_service";
import Icon from "./Icon";
interface Props {
@@ -19,10 +19,6 @@ const GenerateQRCodeDialog: React.FC<Props> = (props: Props) => {
const containerRef = useRef<HTMLDivElement | null>(null);
const shortcutLink = absolutifyLink(`/s/${shortcut.name}`);
const handleCloseBtnClick = () => {
onClose();
};
const handleDownloadQRCodeClick = () => {
const canvas = containerRef.current?.querySelector("canvas");
if (!canvas) {
@@ -34,19 +30,14 @@ const GenerateQRCodeDialog: React.FC<Props> = (props: Props) => {
link.download = `${shortcut.title || shortcut.name}-qrcode.png`;
link.href = canvas.toDataURL();
link.click();
handleCloseBtnClick();
onClose();
};
return (
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="w-64 sm:max-w-xs">
<DialogHeader>
<DialogTitle className="flex flex-row justify-between items-center">
<span>QR Code</span>
<Button variant="ghost" size="icon" onClick={handleCloseBtnClick}>
<Icon.X className="w-5 h-auto" />
</Button>
</DialogTitle>
<DialogTitle>QR Code</DialogTitle>
</DialogHeader>
<div className="space-y-6">
<div ref={containerRef} className="w-full flex flex-row justify-center items-center">
@@ -1,4 +1,4 @@
import { ReactNode } from "react";
import { ReactNode, useState } from "react";
import Icon from "@/components/Icon";
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
@@ -12,8 +12,10 @@ interface Props {
const Dropdown: React.FC<Props> = (props: Props) => {
const { trigger, actions, className, actionsClassName } = props;
const [open, setOpen] = useState(false);
return (
<DropdownMenu>
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger className={className} asChild>
{trigger ? (
<div>{trigger}</div>
@@ -23,7 +25,7 @@ const Dropdown: React.FC<Props> = (props: Props) => {
</button>
)}
</DropdownMenuTrigger>
<DropdownMenuContent className={actionsClassName} align="end">
<DropdownMenuContent className={actionsClassName} align="end" onClick={() => setOpen(false)}>
{actions}
</DropdownMenuContent>
</DropdownMenu>