refactor: update button source

pull/4061/head
Steven 7 months ago
parent 8635aed138
commit 963706aebd

@ -18,8 +18,8 @@
}
</script>
</head>
<body>
<div id="root"></div>
<body class="text-base w-full min-h-[100svh] bg-zinc-100 dark:bg-zinc-900">
<div id="root" class="relative w-full min-h-full"></div>
<script type="module" src="/src/main.tsx"></script>
<!-- memos.metadata.body -->
</body>

@ -19,7 +19,7 @@
"@mui/joy": "5.0.0-beta.48",
"@radix-ui/react-popover": "^1.1.2",
"@reduxjs/toolkit": "^2.3.0",
"@usememos/mui": "0.0.1-alpha.6",
"@usememos/mui": "0.0.1-alpha.10",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"copy-to-clipboard": "^3.3.3",

@ -39,8 +39,8 @@ importers:
specifier: ^2.3.0
version: 2.3.0(react-redux@9.1.2(@types/react@18.3.12)(react@18.3.1)(redux@5.0.1))(react@18.3.1)
'@usememos/mui':
specifier: 0.0.1-alpha.6
version: 0.0.1-alpha.6(lucide-react@0.453.0(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
specifier: 0.0.1-alpha.10
version: 0.0.1-alpha.10(lucide-react@0.453.0(react@18.3.1))(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwind-merge@2.5.4)(tailwindcss@3.4.14)
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@ -1409,12 +1409,15 @@ packages:
'@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
'@usememos/mui@0.0.1-alpha.6':
resolution: {integrity: sha512-CVE3kQ/Uk+T3Zp8jcEOWR4syS6hIxVrQ9UgwpnOiR8d3OEghRFbZBQ6hs4C0sEefIPWS5xsZiEKa0E4BIZezBw==}
'@usememos/mui@0.0.1-alpha.10':
resolution: {integrity: sha512-jyEQ4sgmYCxOWEyuUat7MqQN7Gy4PohQxnLvIje0upqu2zT2AaI0GhOPs/t2HkYK09tFXLAVnhp2I+6jBBhfIg==}
peerDependencies:
lucide-react: ^0.453.0
postcss: ^8.4.47
react: '>=17.0.0'
react-dom: '>=17.0.0'
tailwind-merge: ^2.5.4
tailwindcss: ^3.4.14
'@vitejs/plugin-react@4.3.3':
resolution: {integrity: sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==}
@ -4639,11 +4642,14 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
'@usememos/mui@0.0.1-alpha.6(lucide-react@0.453.0(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@usememos/mui@0.0.1-alpha.10(lucide-react@0.453.0(react@18.3.1))(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwind-merge@2.5.4)(tailwindcss@3.4.14)':
dependencies:
lucide-react: 0.453.0(react@18.3.1)
postcss: 8.4.47
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
tailwind-merge: 2.5.4
tailwindcss: 3.4.14
'@vitejs/plugin-react@4.3.3(vite@5.4.10(@types/node@22.8.0)(less@4.2.0))':
dependencies:

@ -1,4 +1,5 @@
import { Button, IconButton, Input } from "@mui/joy";
import { Input } from "@mui/joy";
import { Button } from "@usememos/mui";
import { XIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
@ -70,9 +71,9 @@ const ChangeMemberPasswordDialog: React.FC<Props> = (props: Props) => {
<p className="title-text">
{t("setting.account-section.change-password")} ({user.nickname})
</p>
<IconButton size="sm" onClick={handleCloseBtnClick}>
<Button size="sm" variant="plain" onClick={handleCloseBtnClick}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container">
<p className="text-sm mb-1">{t("auth.new-password")}</p>
@ -92,7 +93,7 @@ const ChangeMemberPasswordDialog: React.FC<Props> = (props: Props) => {
onChange={handleNewPasswordAgainChanged}
/>
<div className="flex flex-row justify-end items-center mt-4 w-full gap-x-2">
<Button color="neutral" variant="plain" onClick={handleCloseBtnClick}>
<Button variant="plain" onClick={handleCloseBtnClick}>
{t("common.cancel")}
</Button>
<Button color="primary" onClick={handleSaveBtnClick}>

@ -1,116 +0,0 @@
import { Button, IconButton, Input } from "@mui/joy";
import { XIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useCommonContext } from "@/layouts/CommonContextProvider";
import { useUserStore } from "@/store/v1";
import { useTranslate } from "@/utils/i18n";
import { generateDialog } from "./Dialog";
type Props = DialogProps;
const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const t = useTranslate();
const commonContext = useCommonContext();
const currentUser = useCurrentUser();
const userStore = useUserStore();
const [newPassword, setNewPassword] = useState("");
const [newPasswordAgain, setNewPasswordAgain] = useState("");
useEffect(() => {
if (commonContext.profile.mode === "demo") {
toast.error("Demo mode does not support this operation.");
destroy();
}
}, []);
const handleCloseBtnClick = () => {
destroy();
};
const handleNewPasswordChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
setNewPassword(e.target.value);
};
const handleNewPasswordAgainChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
setNewPasswordAgain(e.target.value);
};
const handleSaveBtnClick = async () => {
if (newPassword === "" || newPasswordAgain === "") {
toast.error(t("message.fill-all"));
return;
}
if (newPassword !== newPasswordAgain) {
toast.error(t("message.new-password-not-match"));
setNewPasswordAgain("");
return;
}
try {
await userStore.updateUser(
{
name: currentUser.name,
password: newPassword,
},
["password"],
);
toast.success(t("message.password-changed"));
handleCloseBtnClick();
} catch (error: any) {
toast.error(error.details);
console.error(error);
}
};
return (
<>
<div className="dialog-header-container !w-64">
<p className="title-text">{t("setting.account-section.change-password")}</p>
<IconButton size="sm" onClick={handleCloseBtnClick}>
<XIcon className="w-5 h-auto" />
</IconButton>
</div>
<div className="dialog-content-container">
<p className="text-sm mb-1">{t("auth.new-password")}</p>
<Input
className="w-full"
type="password"
placeholder={t("auth.new-password")}
value={newPassword}
onChange={handleNewPasswordChanged}
/>
<p className="text-sm mb-1 mt-2">{t("auth.repeat-new-password")}</p>
<Input
className="w-full"
type="password"
placeholder={t("auth.repeat-new-password")}
value={newPasswordAgain}
onChange={handleNewPasswordAgainChanged}
/>
<div className="w-full flex flex-row justify-end items-center pt-4 space-x-2">
<Button color="neutral" variant="plain" onClick={handleCloseBtnClick}>
{t("common.cancel")}
</Button>
<Button color="primary" onClick={handleSaveBtnClick}>
{t("common.save")}
</Button>
</div>
</div>
</>
);
};
function showChangePasswordDialog() {
generateDialog(
{
className: "change-password-dialog",
dialogName: "change-password-dialog",
},
ChangePasswordDialog,
);
}
export default showChangePasswordDialog;

@ -1,4 +1,5 @@
import { Button, IconButton, Input, Radio, RadioGroup } from "@mui/joy";
import { Input, Radio, RadioGroup } from "@mui/joy";
import { Button } from "@usememos/mui";
import { XIcon } from "lucide-react";
import React, { useState } from "react";
import { toast } from "react-hot-toast";
@ -86,9 +87,9 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
<>
<div className="dialog-header-container">
<p className="title-text">Create access token</p>
<IconButton size="sm" onClick={() => destroy()}>
<Button size="sm" variant="plain" onClick={() => destroy()}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container !w-80">
<div className="w-full flex flex-col justify-start items-start mb-3">
@ -118,10 +119,10 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
</div>
</div>
<div className="w-full flex flex-row justify-end items-center mt-4 space-x-2">
<Button color="neutral" variant="plain" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={destroy}>
<Button variant="plain" disabled={requestState.isLoading} onClick={destroy}>
{t("common.cancel")}
</Button>
<Button color="primary" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={handleSaveBtnClick}>
<Button color="primary" disabled={requestState.isLoading} onClick={handleSaveBtnClick}>
{t("common.create")}
</Button>
</div>

@ -1,4 +1,5 @@
import { Button, Divider, IconButton, Input, Option, Select, Typography } from "@mui/joy";
import { Divider, Input, Option, Select, Typography } from "@mui/joy";
import { Button } from "@usememos/mui";
import { XIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
@ -244,9 +245,9 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
<>
<div className="dialog-header-container">
<p>{t(isCreating ? "setting.sso-section.create-sso" : "setting.sso-section.update-sso")}</p>
<IconButton size="sm" onClick={handleCloseBtnClick}>
<Button size="sm" variant="plain" onClick={handleCloseBtnClick}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container min-w-[19rem]">
{isCreating && (
@ -420,10 +421,10 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
</>
)}
<div className="mt-2 w-full flex flex-row justify-end items-center space-x-1">
<Button variant="plain" color="neutral" onClick={handleCloseBtnClick}>
<Button variant="plain" onClick={handleCloseBtnClick}>
{t("common.cancel")}
</Button>
<Button onClick={handleConfirmBtnClick} disabled={!allowConfirmAction()}>
<Button color="primary" onClick={handleConfirmBtnClick} disabled={!allowConfirmAction()}>
{t(isCreating ? "common.create" : "common.update")}
</Button>
</div>

@ -1,4 +1,5 @@
import { Button, IconButton, Input } from "@mui/joy";
import { Input } from "@mui/joy";
import { Button } from "@usememos/mui";
import { XIcon } from "lucide-react";
import React, { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
@ -96,9 +97,9 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
<>
<div className="dialog-header-container">
<p className="title-text">{isCreating ? "Create webhook" : "Edit webhook"}</p>
<IconButton size="sm" onClick={() => destroy()}>
<Button size="sm" variant="plain" onClick={() => destroy()}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container !w-80">
<div className="w-full flex flex-col justify-start items-start mb-3">
@ -130,10 +131,10 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
</div>
</div>
<div className="w-full flex flex-row justify-end items-center mt-2 space-x-2">
<Button color="neutral" variant="plain" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={destroy}>
<Button variant="plain" disabled={requestState.isLoading} onClick={destroy}>
{t("common.cancel")}
</Button>
<Button color="primary" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={handleSaveBtnClick}>
<Button color="primary" disabled={requestState.isLoading} onClick={handleSaveBtnClick}>
{t("common.create")}
</Button>
</div>

@ -1,4 +1,5 @@
import { Drawer, IconButton } from "@mui/joy";
import { Drawer } from "@mui/joy";
import { Button } from "@usememos/mui";
import { SearchIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
@ -22,9 +23,9 @@ const ExploreSidebarDrawer = () => {
return (
<>
<IconButton onClick={toggleDrawer(true)}>
<Button variant="plain" className="!bg-transparent px-2" onClick={toggleDrawer(true)}>
<SearchIcon className="w-5 h-auto dark:text-gray-400" />
</IconButton>
</Button>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<ExploreSidebar className="py-4" />

@ -1,4 +1,5 @@
import { Drawer, IconButton } from "@mui/joy";
import { Drawer } from "@mui/joy";
import { Button } from "@usememos/mui";
import { SearchIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
@ -22,9 +23,9 @@ const HomeSidebarDrawer = () => {
return (
<>
<IconButton onClick={toggleDrawer(true)}>
<Button variant="plain" className="!bg-transparent px-2" onClick={toggleDrawer(true)}>
<SearchIcon className="w-5 h-auto dark:text-gray-400" />
</IconButton>
</Button>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<HomeSidebar className="py-4" />

@ -1,4 +1,5 @@
import { Drawer, IconButton } from "@mui/joy";
import { Drawer } from "@mui/joy";
import { Button } from "@usememos/mui";
import { GanttChartIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
@ -26,9 +27,9 @@ const MemoDetailSidebarDrawer = ({ memo }: Props) => {
return (
<>
<IconButton onClick={toggleDrawer(true)}>
<Button variant="plain" className="!bg-transparent px-2" onClick={toggleDrawer(true)}>
<GanttChartIcon className="w-5 h-auto dark:text-gray-400" />
</IconButton>
</Button>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<MemoDetailSidebar className="py-4" memo={memo} />

@ -1,4 +1,5 @@
import { Autocomplete, AutocompleteOption, Button, Checkbox, Chip, IconButton } from "@mui/joy";
import { Autocomplete, AutocompleteOption, Checkbox, Chip } from "@mui/joy";
import { Button } from "@usememos/mui";
import { uniqBy } from "lodash-es";
import { LinkIcon } from "lucide-react";
import React, { useContext, useState } from "react";
@ -129,9 +130,9 @@ const AddMemoRelationPopover = (props: Props) => {
return (
<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
<PopoverTrigger>
<IconButton size="sm" component="div">
<Button className="px-2" variant="plain">
<LinkIcon className="w-5 h-5 mx-auto" />
</IconButton>
</Button>
</PopoverTrigger>
<PopoverContent align="center">
<div className="w-[16rem] flex flex-col justify-start items-start">
@ -173,7 +174,7 @@ const AddMemoRelationPopover = (props: Props) => {
/>
<div className="mt-2 w-full flex flex-row justify-end items-center gap-2">
<Checkbox size="sm" label={"Embed"} checked={embedded} onChange={(e) => setEmbedded(e.target.checked)} />
<Button size="sm" onClick={addMemoRelations} disabled={selectedMemos.length === 0}>
<Button size="sm" color="primary" onClick={addMemoRelations} disabled={selectedMemos.length === 0}>
{t("common.add")}
</Button>
</div>

@ -1,4 +1,5 @@
import { Button, IconButton, Input } from "@mui/joy";
import { Input } from "@mui/joy";
import { Button } from "@usememos/mui";
import { LatLng } from "leaflet";
import { MapPinIcon, XIcon } from "lucide-react";
import { useEffect, useState } from "react";
@ -94,7 +95,7 @@ const LocationSelector = (props: Props) => {
return (
<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
<PopoverTrigger>
<IconButton className="group" size="sm" component="div">
<Button className="group px-2" variant="plain">
<MapPinIcon className="w-5 h-5 mx-auto shrink-0" />
{props.location && (
<>
@ -104,7 +105,7 @@ const LocationSelector = (props: Props) => {
<XIcon className="w-5 h-5 mx-auto shrink-0 hidden group-hover:block opacity-60 hover:opacity-80" onClick={removeLocation} />
</>
)}
</IconButton>
</Button>
</PopoverTrigger>
<PopoverContent align="center">
<div className="min-w-80 sm:w-128 flex flex-col justify-start items-start">
@ -125,7 +126,7 @@ const LocationSelector = (props: Props) => {
/>
<Button
className="shrink-0"
size="sm"
color="primary"
onClick={() => {
props.onChange(
Location.fromPartial({

@ -1,5 +1,5 @@
import { Dropdown, IconButton, Menu, MenuButton, MenuItem } from "@mui/joy";
import { Link } from "@mui/joy";
import { Dropdown, Menu, MenuButton, MenuItem, Link } from "@mui/joy";
import { Button } from "@usememos/mui";
import { CheckSquareIcon, Code2Icon, SquareSlashIcon } from "lucide-react";
import { EditorRefActions } from "../Editor";
@ -60,10 +60,12 @@ const MarkdownMenu = (props: Props) => {
return (
<Dropdown>
<MenuButton
slots={{ root: IconButton }}
slots={{ root: Button }}
slotProps={{
root: {
size: "sm",
variant: "plain",
className: "px-2",
},
}}
>

@ -1,4 +1,5 @@
import { Dropdown, IconButton, Menu, MenuButton } from "@mui/joy";
import { Dropdown, Menu, MenuButton } from "@mui/joy";
import { Button } from "@usememos/mui";
import { HashIcon } from "lucide-react";
import { useRef, useState } from "react";
import useClickAway from "react-use/lib/useClickAway";
@ -41,10 +42,12 @@ const TagSelector = (props: Props) => {
return (
<Dropdown open={open} onOpenChange={(_, isOpen) => setOpen(isOpen)}>
<MenuButton
slots={{ root: IconButton }}
slots={{ root: Button }}
slotProps={{
root: {
size: "sm",
variant: "plain",
className: "px-2",
},
}}
>

@ -1,4 +1,4 @@
import { IconButton } from "@mui/joy";
import { Button } from "@usememos/mui";
import { PaperclipIcon } from "lucide-react";
import { useContext, useRef, useState } from "react";
import toast from "react-hot-toast";
@ -66,7 +66,7 @@ const UploadResourceButton = () => {
};
return (
<IconButton size="sm" disabled={state.uploadingFlag}>
<Button className="px-2 relative" size="sm" variant="plain" disabled={state.uploadingFlag}>
<PaperclipIcon className="w-5 h-5 mx-auto" />
<input
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
@ -78,7 +78,7 @@ const UploadResourceButton = () => {
multiple={true}
accept="*"
/>
</IconButton>
</Button>
);
};

@ -1,6 +1,7 @@
import { Select, Option, Button, Divider } from "@mui/joy";
import { Select, Option, Divider } from "@mui/joy";
import { Button } from "@usememos/mui";
import { isEqual } from "lodash-es";
import { SendIcon } from "lucide-react";
import { LoaderIcon, SendIcon } from "lucide-react";
import React, { useEffect, useMemo, useRef, useState } from "react";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
@ -442,7 +443,7 @@ const MemoEditor = (props: Props) => {
<ResourceListView resourceList={state.resourceList} setResourceList={handleSetResourceList} />
<RelationListView relationList={referenceRelations} setRelationList={handleSetRelationList} />
<div className="relative w-full flex flex-row justify-between items-center pt-2" onFocus={(e) => e.stopPropagation()}>
<div className="flex flex-row justify-start items-center opacity-80 dark:opacity-60">
<div className="flex flex-row justify-start items-center opacity-80 dark:opacity-60 -space-x-1">
<TagSelector editorRef={editorRef} />
<MarkdownMenu editorRef={editorRef} />
<UploadResourceButton />
@ -482,18 +483,13 @@ const MemoEditor = (props: Props) => {
</div>
<div className="shrink-0 flex flex-row justify-end items-center gap-2">
{props.onCancel && (
<Button className="!font-normal" color="neutral" variant="plain" loading={state.isRequesting} onClick={handleCancelBtnClick}>
<Button variant="plain" disabled={state.isRequesting} onClick={handleCancelBtnClick}>
{t("common.cancel")}
</Button>
)}
<Button
className="!font-normal"
disabled={!allowSave}
loading={state.isRequesting}
endDecorator={<SendIcon className="w-4 h-auto" />}
onClick={handleSaveBtnClick}
>
<Button color="primary" disabled={!allowSave || state.isRequesting} onClick={handleSaveBtnClick}>
{t("editor.save")}
{!state.isRequesting ? <SendIcon className="w-4 h-auto ml-1" /> : <LoaderIcon className="w-4 h-auto ml-1 animate-spin" />}
</Button>
</div>
</div>

@ -1,4 +1,5 @@
import { Drawer, IconButton } from "@mui/joy";
import { Drawer } from "@mui/joy";
import { Button } from "@usememos/mui";
import { MenuIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
@ -22,9 +23,9 @@ const NavigationDrawer = () => {
return (
<>
<IconButton onClick={toggleDrawer(true)}>
<Button variant="plain" className="!bg-transparent px-2" onClick={toggleDrawer(true)}>
<MenuIcon className="w-5 h-auto dark:text-gray-400" />
</IconButton>
</Button>
<Drawer anchor="left" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full overflow-auto px-4 bg-zinc-100 dark:bg-zinc-900">
<Navigation />

@ -1,4 +1,4 @@
import { Button } from "@mui/joy";
import { Button } from "@usememos/mui";
import { ArrowDownIcon, LoaderIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts";
@ -62,14 +62,9 @@ const PagedMemoList = (props: Props) => {
)}
{!state.isRequesting && state.nextPageToken && (
<div className="w-full flex flex-row justify-center items-center my-4">
<Button
variant="plain"
color="neutral"
loading={state.isRequesting}
endDecorator={<ArrowDownIcon className="w-4 h-auto" />}
onClick={() => fetchMoreMemos(state.nextPageToken)}
>
<Button variant="plain" onClick={() => fetchMoreMemos(state.nextPageToken)}>
{t("memo.load-more")}
<ArrowDownIcon className="ml-2 w-4 h-auto" />
</Button>
</div>
)}

@ -1,4 +1,6 @@
import { Button, Checkbox, Input } from "@mui/joy";
import { Checkbox, Input } from "@mui/joy";
import { Button } from "@usememos/mui";
import { LoaderIcon } from "lucide-react";
import { ClientError } from "nice-grpc-web";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
@ -108,14 +110,15 @@ const PasswordSignInForm = () => {
</div>
<div className="flex flex-row justify-end items-center w-full mt-6">
<Button
className="w-full"
size="md"
type="submit"
color="primary"
size="lg"
fullWidth
disabled={actionBtnLoadingState.isLoading}
loading={actionBtnLoadingState.isLoading}
onClick={handleSignInButtonClick}
>
{t("common.sign-in")}
{actionBtnLoadingState.isLoading && <LoaderIcon className="w-5 h-auto ml-2 animate-spin opacity-60" />}
</Button>
</div>
</form>

@ -1,4 +1,5 @@
import { Button, IconButton, Input, List, ListItem } from "@mui/joy";
import { Input, List, ListItem } from "@mui/joy";
import { Button } from "@usememos/mui";
import { XIcon } from "lucide-react";
import React, { useState } from "react";
import { toast } from "react-hot-toast";
@ -54,9 +55,9 @@ const RenameTagDialog: React.FC<Props> = (props: Props) => {
<>
<div className="dialog-header-container">
<p className="title-text">{"Rename tag"}</p>
<IconButton size="sm" onClick={() => destroy()}>
<Button size="sm" variant="plain" onClick={() => destroy()}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container max-w-xs">
<div className="w-full flex flex-col justify-start items-start mb-3">
@ -82,10 +83,10 @@ const RenameTagDialog: React.FC<Props> = (props: Props) => {
</List>
</div>
<div className="w-full flex flex-row justify-end items-center space-x-2">
<Button color="neutral" variant="plain" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={destroy}>
<Button variant="plain" disabled={requestState.isLoading} onClick={destroy}>
{t("common.cancel")}
</Button>
<Button color="primary" disabled={requestState.isLoading} loading={requestState.isLoading} onClick={handleConfirm}>
<Button color="primary" disabled={requestState.isLoading} onClick={handleConfirm}>
{t("common.confirm")}
</Button>
</div>

@ -1,4 +1,4 @@
import { Button, IconButton } from "@mui/joy";
import { Button } from "@usememos/mui";
import copy from "copy-to-clipboard";
import { ClipboardIcon, TrashIcon } from "lucide-react";
import { useEffect, useState } from "react";
@ -63,8 +63,7 @@ const AccessTokenSection = () => {
</div>
<div className="mt-4 sm:mt-0">
<Button
variant="outlined"
color="neutral"
color="primary"
onClick={() => {
showCreateAccessTokenDialog(handleCreateAccessTokenDialogConfirm);
}}
@ -101,9 +100,9 @@ const AccessTokenSection = () => {
<tr key={userAccessToken.accessToken}>
<td className="whitespace-nowrap px-3 py-2 text-sm text-gray-900 dark:text-gray-400 flex flex-row justify-start items-center gap-x-1">
<span className="font-mono">{getFormatedAccessToken(userAccessToken.accessToken)}</span>
<IconButton color="neutral" variant="plain" size="sm" onClick={() => copyAccessToken(userAccessToken.accessToken)}>
<Button variant="plain" size="sm" onClick={() => copyAccessToken(userAccessToken.accessToken)}>
<ClipboardIcon className="w-4 h-auto text-gray-400" />
</IconButton>
</Button>
</td>
<td className="whitespace-nowrap py-2 pl-4 pr-3 text-sm text-gray-900 dark:text-gray-400">
{userAccessToken.description}
@ -115,16 +114,15 @@ const AccessTokenSection = () => {
{userAccessToken.expiresAt?.toLocaleString() ?? "Never"}
</td>
<td className="relative whitespace-nowrap py-2 pl-3 pr-4 text-right text-sm">
<IconButton
color="danger"
<Button
variant="plain"
size="sm"
onClick={() => {
handleDeleteAccessToken(userAccessToken.accessToken);
}}
>
<TrashIcon className="w-4 h-auto" />
</IconButton>
<TrashIcon className="text-red-600 w-4 h-auto" />
</Button>
</td>
</tr>
))}

@ -1,4 +1,5 @@
import { Button, Dropdown, Input, Menu, MenuButton, MenuItem, Radio, RadioGroup } from "@mui/joy";
import { Dropdown, Input, Menu, MenuButton, MenuItem, Radio, RadioGroup } from "@mui/joy";
import { Button } from "@usememos/mui";
import { sortBy } from "lodash-es";
import { MoreVerticalIcon } from "lucide-react";
import React, { useEffect, useState } from "react";
@ -158,7 +159,9 @@ const MemberSection = () => {
</RadioGroup>
</div>
<div className="mt-2">
<Button onClick={handleCreateUserBtnClick}>{t("common.create")}</Button>
<Button color="primary" onClick={handleCreateUserBtnClick}>
{t("common.create")}
</Button>
</div>
</div>
<div className="w-full flex flex-row justify-between items-center mt-6">

@ -1,4 +1,5 @@
import { Button, Input, Switch, Select, Option, Chip, ChipDelete } from "@mui/joy";
import { Input, Switch, Select, Option, Chip, ChipDelete } from "@mui/joy";
import { Button } from "@usememos/mui";
import { isEqual, uniq } from "lodash-es";
import { CheckIcon } from "lucide-react";
import { useState } from "react";
@ -179,7 +180,7 @@ const MemoRelatedSettings = () => {
</div>
</div>
<div className="mt-2 w-full flex justify-end">
<Button disabled={isEqual(memoRelatedSetting, originalSetting)} onClick={updateSetting}>
<Button color="primary" disabled={isEqual(memoRelatedSetting, originalSetting)} onClick={updateSetting}>
{t("common.save")}
</Button>
</div>

@ -1,8 +1,9 @@
import { Button, Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
import { Button } from "@usememos/mui";
import { MoreVerticalIcon, PenLineIcon } from "lucide-react";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useTranslate } from "@/utils/i18n";
import showChangePasswordDialog from "../ChangePasswordDialog";
import showChangeMemberPasswordDialog from "../ChangeMemberPasswordDialog";
import showUpdateAccountDialog from "../UpdateAccountDialog";
import UserAvatar from "../UserAvatar";
import AccessTokenSection from "./AccessTokenSection";
@ -25,18 +26,18 @@ const MyAccountSection = () => {
</div>
</div>
<div className="w-full flex flex-row justify-start items-center mt-2 space-x-2">
<Button variant="outlined" color="neutral" size="sm" onClick={showUpdateAccountDialog}>
<Button variant="outlined" size="sm" onClick={showUpdateAccountDialog}>
<PenLineIcon className="w-4 h-4 mx-auto mr-1" />
{t("common.edit")}
</Button>
<Dropdown>
<MenuButton slots={{ root: "div" }}>
<Button variant="outlined" color="neutral" size="sm">
<Button variant="outlined" size="sm">
<MoreVerticalIcon className="w-4 h-4 mx-auto" />
</Button>
</MenuButton>
<Menu className="text-sm" size="sm" placement="bottom">
<MenuItem onClick={showChangePasswordDialog}>{t("setting.account-section.change-password")}</MenuItem>
<MenuItem onClick={() => showChangeMemberPasswordDialog(user)}>{t("setting.account-section.change-password")}</MenuItem>
</Menu>
</Dropdown>
</div>

@ -1,4 +1,5 @@
import { Button, Divider, Dropdown, List, ListItem, Menu, MenuButton, MenuItem } from "@mui/joy";
import { Divider, Dropdown, List, ListItem, Menu, MenuButton, MenuItem } from "@mui/joy";
import { Button } from "@usememos/mui";
import { MoreVerticalIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
@ -42,7 +43,9 @@ const SSOSection = () => {
<span className="font-mono text-gray-400">{t("setting.sso-section.sso-list")}</span>
<LearnMore url="https://usememos.com/docs/advanced-settings/keycloak" />
</div>
<Button onClick={() => showCreateIdentityProviderDialog(undefined, fetchIdentityProviderList)}>{t("common.create")}</Button>
<Button color="primary" onClick={() => showCreateIdentityProviderDialog(undefined, fetchIdentityProviderList)}>
{t("common.create")}
</Button>
</div>
<Divider />
{identityProviderList.map((identityProvider) => (

@ -1,4 +1,5 @@
import { Button, Divider, Input, List, ListItem, Radio, RadioGroup, Tooltip } from "@mui/joy";
import { Divider, Input, List, ListItem, Radio, RadioGroup, Tooltip } from "@mui/joy";
import { Button } from "@usememos/mui";
import { isEqual } from "lodash-es";
import { HelpCircleIcon } from "lucide-react";
import { useMemo, useState } from "react";
@ -183,7 +184,7 @@ const StorageSection = () => {
</>
)}
<div>
<Button disabled={!allowSaveStorageSetting} onClick={saveWorkspaceStorageSetting}>
<Button color="primary" disabled={!allowSaveStorageSetting} onClick={saveWorkspaceStorageSetting}>
{t("common.save")}
</Button>
</div>

@ -1,4 +1,4 @@
import { Button, IconButton } from "@mui/joy";
import { Button } from "@usememos/mui";
import { ExternalLinkIcon, TrashIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
@ -47,8 +47,7 @@ const WebhookSection = () => {
</div>
<div>
<Button
variant="outlined"
color="neutral"
color="primary"
onClick={() => {
showCreateWebhookDialog(handleCreateAccessTokenDialogConfirm);
}}
@ -80,16 +79,15 @@ const WebhookSection = () => {
<td className="whitespace-nowrap px-3 py-2 text-sm text-gray-900 dark:text-gray-400">{webhook.name}</td>
<td className="whitespace-nowrap px-3 py-2 text-sm text-gray-900 dark:text-gray-400">{webhook.url}</td>
<td className="relative whitespace-nowrap px-3 py-2 text-right text-sm">
<IconButton
color="danger"
<Button
variant="plain"
size="sm"
onClick={() => {
handleDeleteWebhook(webhook);
}}
>
<TrashIcon className="w-4 h-auto" />
</IconButton>
<TrashIcon className="text-red-600 w-4 h-auto" />
</Button>
</td>
</tr>
))}

@ -1,4 +1,5 @@
import { Button, Select, Textarea, Option, Divider, Switch } from "@mui/joy";
import { Select, Textarea, Option, Divider, Switch } from "@mui/joy";
import { Button } from "@usememos/mui";
import { isEqual } from "lodash-es";
import { ExternalLinkIcon } from "lucide-react";
import { useEffect, useState } from "react";
@ -57,7 +58,7 @@ const WorkspaceSection = () => {
{t("setting.system-section.server-name")}:{" "}
<span className="font-mono font-bold">{workspaceGeneralSetting.customProfile?.title || "Memos"}</span>
</div>
<Button variant="outlined" color="neutral" onClick={handleUpdateCustomizedProfileButtonClick}>
<Button variant="outlined" onClick={handleUpdateCustomizedProfileButtonClick}>
{t("common.edit")}
</Button>
</div>
@ -147,7 +148,7 @@ const WorkspaceSection = () => {
</Select>
</div>
<div className="mt-2 w-full flex justify-end">
<Button disabled={isEqual(workspaceGeneralSetting, originalSetting)} onClick={handleSaveGeneralSetting}>
<Button color="primary" disabled={isEqual(workspaceGeneralSetting, originalSetting)} onClick={handleSaveGeneralSetting}>
{t("common.save")}
</Button>
</div>

@ -1,4 +1,5 @@
import { Button, IconButton, Input, Textarea } from "@mui/joy";
import { Input, Textarea } from "@mui/joy";
import { Button } from "@usememos/mui";
import { isEqual } from "lodash-es";
import { XIcon } from "lucide-react";
import { useState } from "react";
@ -146,9 +147,9 @@ const UpdateAccountDialog: React.FC<Props> = ({ destroy }: Props) => {
<>
<div className="dialog-header-container !w-64">
<p className="title-text">{t("setting.account-section.update-information")}</p>
<IconButton size="sm" onClick={handleCloseBtnClick}>
<Button size="sm" variant="plain" onClick={handleCloseBtnClick}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container space-y-2">
<div className="w-full flex flex-row justify-start items-center">
@ -203,7 +204,7 @@ const UpdateAccountDialog: React.FC<Props> = ({ destroy }: Props) => {
onChange={handleDescriptionChanged}
/>
<div className="w-full flex flex-row justify-end items-center pt-4 space-x-2">
<Button color="neutral" variant="plain" onClick={handleCloseBtnClick}>
<Button variant="plain" onClick={handleCloseBtnClick}>
{t("common.cancel")}
</Button>
<Button color="primary" onClick={handleSaveBtnClick}>

@ -1,5 +1,6 @@
import { Button, IconButton, Input } from "@mui/joy";
import { Input } from "@mui/joy";
import Textarea from "@mui/joy/Textarea/Textarea";
import { Button } from "@usememos/mui";
import { XIcon } from "lucide-react";
import { useState } from "react";
import { toast } from "react-hot-toast";
@ -102,9 +103,9 @@ const UpdateCustomizedProfileDialog: React.FC<Props> = ({ destroy }: Props) => {
<>
<div className="dialog-header-container">
<p className="title-text">{t("setting.system-section.customize-server.title")}</p>
<IconButton size="sm" onClick={handleCloseButtonClick}>
<Button size="sm" variant="plain" onClick={handleCloseButtonClick}>
<XIcon className="w-5 h-auto" />
</IconButton>
</Button>
</div>
<div className="dialog-content-container min-w-[16rem]">
<p className="text-sm mb-1">{t("setting.system-section.server-name")}</p>
@ -123,11 +124,13 @@ const UpdateCustomizedProfileDialog: React.FC<Props> = ({ destroy }: Props) => {
{t("common.restore")}
</Button>
</div>
<div className="flex flex-row justify-end items-center">
<div className="flex flex-row justify-end items-center gap-2">
<Button variant="plain" onClick={handleCloseButtonClick}>
{t("common.cancel")}
</Button>
<Button onClick={handleSaveButtonClick}>{t("common.save")}</Button>
<Button color="primary" onClick={handleSaveButtonClick}>
{t("common.save")}
</Button>
</div>
</div>
</div>

@ -24,7 +24,7 @@ const UserBanner = (props: Props) => {
const workspaceGeneralSetting =
workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.GENERAL).generalSetting || WorkspaceGeneralSetting.fromPartial({});
const title = (user ? user.nickname || user.username : workspaceGeneralSetting.customProfile?.title) || "Memos";
const avatarUrl = (user ? user.avatarUrl : workspaceGeneralSetting.customProfile?.logoUrl) || "/logo.webp";
const avatarUrl = (user ? user.avatarUrl : workspaceGeneralSetting.customProfile?.logoUrl) || "/full-logo.webp";
const handleSignOut = async () => {
await authServiceClient.signOut({});
@ -37,11 +37,11 @@ const UserBanner = (props: Props) => {
<MenuButton disabled={!user} slots={{ root: "div" }}>
<div
className={clsx(
"py-1 my-1 w-auto flex flex-row justify-start items-center cursor-pointer rounded-2xl border border-transparent text-gray-800 dark:text-gray-400",
"py-1 my-1 w-auto flex flex-row justify-start items-center cursor-pointer text-gray-800 dark:text-gray-400",
collapsed ? "px-1" : "px-3",
)}
>
<UserAvatar className="shadow shrink-0" avatarUrl={avatarUrl} />
<UserAvatar className="shrink-0" avatarUrl={avatarUrl} />
{!collapsed && <span className="ml-2 text-lg font-medium text-slate-800 dark:text-gray-300 shrink truncate">{title}</span>}
</div>
</MenuButton>

@ -1,4 +1,5 @@
import { Divider, IconButton, Tooltip } from "@mui/joy";
import { Divider, Tooltip } from "@mui/joy";
import { Button } from "@usememos/mui";
import clsx from "clsx";
import dayjs from "dayjs";
import { countBy } from "lodash-es";
@ -81,12 +82,20 @@ const UserStatisticsView = () => {
<MoreVerticalIcon className="w-4 h-auto shrink-0 opacity-60" />
</PopoverTrigger>
<PopoverContent className="flex flex-row justify-end items-center" align="end" alignOffset={-12}>
<IconButton size="sm" onClick={() => setVisibleMonthString(dayjs(visibleMonthString).subtract(1, "month").format("YYYY-MM"))}>
<Button
size="sm"
variant="plain"
onClick={() => setVisibleMonthString(dayjs(visibleMonthString).subtract(1, "month").format("YYYY-MM"))}
>
<ChevronLeftIcon className="w-5 h-auto shrink-0 opacity-60" />
</IconButton>
<IconButton size="sm" onClick={() => setVisibleMonthString(dayjs(visibleMonthString).add(1, "month").format("YYYY-MM"))}>
</Button>
<Button
size="sm"
variant="plain"
onClick={() => setVisibleMonthString(dayjs(visibleMonthString).add(1, "month").format("YYYY-MM"))}
>
<ChevronRightIcon className="w-5 h-auto shrink-0 opacity-60" />
</IconButton>
</Button>
</PopoverContent>
</Popover>
</div>

@ -17,7 +17,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={clsx(
"z-[2000] w-auto rounded-md border dark:border-zinc-800 bg-popover p-2 text-popover-foreground 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 dark:border-zinc-800 bg-popover p-2 text-popover-foreground 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}

@ -1,14 +0,0 @@
body {
@apply text-base w-full min-h-[100svh] bg-zinc-100 dark:bg-zinc-900;
}
#root {
@apply relative w-full min-h-full;
}
html.dark {
color-scheme: dark;
scrollbar-color: hsla(0, 0%, 100%, 0.4) hsla(0, 0%, 100%, 0.029);
}
html.light {
color-scheme: light;
}

@ -2,63 +2,6 @@
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 10% 3.9%;
--radius: 0.5rem;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@layer utilities {
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
@ -75,3 +18,10 @@
word-break: normal;
}
}
html.dark {
color-scheme: dark;
}
html.light {
color-scheme: light;
}

@ -1,4 +1,5 @@
import { Button, IconButton, Tooltip } from "@mui/joy";
import { Tooltip } from "@mui/joy";
import { Button } from "@usememos/mui";
import clsx from "clsx";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { Suspense, useEffect, useState } from "react";
@ -55,14 +56,15 @@ const RootLayout = () => {
onClick={() => setCollapsed(!collapsed)}
>
{!collapsed ? (
<Button variant="plain" color="neutral" startDecorator={<ChevronLeftIcon className="w-5 h-auto opacity-70" />}>
<Button className="rounded-xl" variant="plain">
<ChevronLeftIcon className="w-5 h-auto opacity-70 mr-1" />
{t("common.collapse")}
</Button>
) : (
<Tooltip title={t("common.expand")} placement="right" arrow>
<IconButton>
<Button className="rounded-xl" variant="plain">
<ChevronRightIcon className="w-5 h-auto opacity-70" />
</IconButton>
</Button>
</Tooltip>
)}
</div>

@ -1,11 +1,11 @@
import "@github/relative-time-element";
import { CssVarsProvider } from "@mui/joy";
import "@usememos/mui/dist/index.css";
import "leaflet/dist/leaflet.css";
import { createRoot } from "react-dom/client";
import { Toaster } from "react-hot-toast";
import { Provider } from "react-redux";
import { RouterProvider } from "react-router-dom";
import "./css/global.css";
import "./css/tailwind.css";
import "./helpers/polyfill";
import "./i18n";

@ -1,4 +1,4 @@
import { Button } from "@mui/joy";
import { Button } from "@usememos/mui";
import clsx from "clsx";
import { ArrowUpLeftFromCircleIcon, MessageCircleIcon } from "lucide-react";
import { ClientError } from "nice-grpc-web";
@ -36,7 +36,7 @@ const MemoDetail = () => {
const commentRelations =
memo?.relations.filter((relation) => relation.relatedMemo?.name === memo.name && relation.type === MemoRelation_Type.COMMENT) || [];
const comments = commentRelations.map((relation) => memoStore.getMemoByName(relation.memo!.name)).filter((memo) => memo) as any as Memo[];
const showCreateCommentButton = workspaceMemoRelatedSetting.enableComment && currentUser;
const showCreateCommentButton = workspaceMemoRelatedSetting.enableComment && currentUser && !showCommentEditor;
// Prepare memo.
useEffect(() => {
@ -120,27 +120,23 @@ const MemoDetail = () => {
{comments.length === 0 ? (
showCreateCommentButton && (
<div className="w-full flex flex-row justify-center items-center py-6">
<Button
variant="plain"
color="neutral"
endDecorator={<MessageCircleIcon className="w-5 h-auto text-gray-500" />}
onClick={handleShowCommentEditor}
>
<span className="font-normal text-gray-500">{t("memo.comment.write-a-comment")}</span>
<Button variant="plain" color="primary" onClick={handleShowCommentEditor}>
<span className="text-gray-500">{t("memo.comment.write-a-comment")}</span>
<MessageCircleIcon className="ml-2 w-5 h-auto text-gray-500" />
</Button>
</div>
)
) : (
<>
<div className="w-full flex flex-row justify-between items-center px-3 mb-2">
<div className="w-full flex flex-row justify-between items-center h-8 pl-3 mb-2">
<div className="flex flex-row justify-start items-center">
<MessageCircleIcon className="w-5 h-auto text-gray-400 mr-1" />
<span className="text-gray-400 text-sm">{t("memo.comment.self")}</span>
<span className="text-gray-400 text-sm ml-1">({comments.length})</span>
</div>
{showCreateCommentButton && (
<Button variant="plain" color="neutral" onClick={handleShowCommentEditor}>
<span className="font-normal text-gray-500">{t("memo.comment.write-a-comment")}</span>
<Button variant="plain" color="primary" className="text-gray-500" onClick={handleShowCommentEditor}>
{t("memo.comment.write-a-comment")}
</Button>
)}
</div>

@ -1,4 +1,5 @@
import { Divider, IconButton, Input, Tooltip } from "@mui/joy";
import { Divider, Input, Tooltip } from "@mui/joy";
import { Button } from "@usememos/mui";
import dayjs from "dayjs";
import { includes } from "lodash-es";
import { PaperclipIcon, SearchIcon, TrashIcon } from "lucide-react";
@ -132,9 +133,9 @@ const Resources = () => {
<span className="text-gray-600 dark:text-gray-400">Unused resources</span>
<span className="text-gray-500 dark:text-gray-500 opacity-80">({unusedResources.length})</span>
<Tooltip title="Delete all" placement="top">
<IconButton size="sm" onClick={handleDeleteUnusedResources}>
<Button size="sm" variant="plain" onClick={handleDeleteUnusedResources}>
<TrashIcon className="w-4 h-auto opacity-60" />
</IconButton>
</Button>
</Tooltip>
</div>
{unusedResources.map((resource) => {

@ -1,4 +1,5 @@
import { Button, Divider } from "@mui/joy";
import { Divider } from "@mui/joy";
import { Button } from "@usememos/mui";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { Link } from "react-router-dom";
@ -96,10 +97,9 @@ const SignIn = () => {
{identityProviderList.map((identityProvider) => (
<Button
key={identityProvider.name}
color="primary"
variant="outlined"
color="neutral"
className="w-full"
size="md"
fullWidth
onClick={() => handleSignInWithIdentityProvider(identityProvider)}
>
{t("common.sign-in-with", { provider: identityProvider.title })}

@ -1,4 +1,6 @@
import { Button, Input } from "@mui/joy";
import { Input } from "@mui/joy";
import { Button } from "@usememos/mui";
import { LoaderIcon } from "lucide-react";
import { ClientError } from "nice-grpc-web";
import { useState } from "react";
import { toast } from "react-hot-toast";
@ -119,14 +121,15 @@ const SignUp = () => {
</div>
<div className="flex flex-row justify-end items-center w-full mt-6">
<Button
className="w-full"
size="md"
type="submit"
color="primary"
size="lg"
fullWidth
disabled={actionBtnLoadingState.isLoading}
loading={actionBtnLoadingState.isLoading}
onClick={handleSignUpButtonClick}
>
{t("common.sign-up")}
{actionBtnLoadingState.isLoading && <LoaderIcon className="w-5 h-auto ml-2 animate-spin opacity-60" />}
</Button>
</div>
</form>

@ -1,4 +1,4 @@
import { Button } from "@mui/joy";
import { Button } from "@usememos/mui";
import copy from "copy-to-clipboard";
import dayjs from "dayjs";
import { ExternalLinkIcon } from "lucide-react";
@ -88,13 +88,9 @@ const UserProfile = () => {
(user ? (
<>
<div className="my-4 w-full flex justify-end items-center gap-2">
<Button
color="neutral"
variant="outlined"
endDecorator={<ExternalLinkIcon className="w-4 h-auto opacity-60" />}
onClick={handleCopyProfileLink}
>
<Button variant="outlined" onClick={handleCopyProfileLink}>
{t("common.share")}
<ExternalLinkIcon className="ml-1 w-4 h-auto opacity-60" />
</Button>
</div>
<div className="w-full flex flex-col justify-start items-start pt-4 pb-8 px-3">

@ -2,33 +2,12 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: ["./index.html", "./src/**/*.{ts,tsx}"],
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
prefix: "",
theme: {
fontSize: {
xs: ".75rem",
sm: ".875rem",
base: "1rem",
lg: "1.125rem",
xl: "1.25rem",
"2xl": "1.5rem",
"3xl": "1.875rem",
"4xl": "2.25rem",
"5xl": "2.5rem",
"6xl": "3rem",
},
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
spacing: {
112: "28rem",
128: "32rem",
180: "45rem",
},
zIndex: {
1: "1",
@ -41,46 +20,6 @@ module.exports = {
gridTemplateRows: {
7: "repeat(7, minmax(0, 1fr))",
},
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [require("tailwindcss-animate")],

Loading…
Cancel
Save