Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
91be2f68
Unverified
Commit
91be2f68
authored
Jul 04, 2025
by
Johnny
Committed by
GitHub
Jul 04, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: variant colors (#4816)
parent
b164c159
Changes
99
Hide whitespace changes
Inline
Side-by-side
Showing
99 changed files
with
410 additions
and
423 deletions
+410
-423
index.html
web/index.html
+1
-1
ActivityCalendar.tsx
web/src/components/ActivityCalendar/ActivityCalendar.tsx
+8
-8
BrandBanner.tsx
web/src/components/BrandBanner.tsx
+2
-2
ChangeMemberPasswordDialog.tsx
web/src/components/ChangeMemberPasswordDialog.tsx
+1
-1
CreateAccessTokenDialog.tsx
web/src/components/CreateAccessTokenDialog.tsx
+3
-3
CreateIdentityProviderDialog.tsx
web/src/components/CreateIdentityProviderDialog.tsx
+10
-10
CreateShortcutDialog.tsx
web/src/components/CreateShortcutDialog.tsx
+3
-3
CreateUserDialog.tsx
web/src/components/CreateUserDialog.tsx
+1
-1
CreateWebhookDialog.tsx
web/src/components/CreateWebhookDialog.tsx
+3
-3
DateTimeInput.tsx
web/src/components/DateTimeInput.tsx
+1
-1
BaseDialog.tsx
web/src/components/Dialog/BaseDialog.tsx
+1
-1
Empty.tsx
web/src/components/Empty.tsx
+1
-1
HomeSidebarDrawer.tsx
web/src/components/HomeSidebar/HomeSidebarDrawer.tsx
+2
-2
ShortcutsSection.tsx
web/src/components/HomeSidebar/ShortcutsSection.tsx
+5
-5
TagsSection.tsx
web/src/components/HomeSidebar/TagsSection.tsx
+7
-7
MemoCommentMessage.tsx
web/src/components/Inbox/MemoCommentMessage.tsx
+7
-7
LearnMore.tsx
web/src/components/LearnMore.tsx
+1
-1
MemoActionMenu.tsx
web/src/components/MemoActionMenu.tsx
+7
-10
MemoAttachment.tsx
web/src/components/MemoAttachment.tsx
+1
-1
MemoAttachmentListView.tsx
web/src/components/MemoAttachmentListView.tsx
+2
-2
Blockquote.tsx
web/src/components/MemoContent/Blockquote.tsx
+1
-1
Code.tsx
web/src/components/MemoContent/Code.tsx
+1
-1
CodeBlock.tsx
web/src/components/MemoContent/CodeBlock.tsx
+3
-3
EmbeddedMemo.tsx
...c/components/MemoContent/EmbeddedContent/EmbeddedMemo.tsx
+3
-3
Error.tsx
web/src/components/MemoContent/EmbeddedContent/Error.tsx
+1
-1
Link.tsx
web/src/components/MemoContent/Link.tsx
+2
-2
Error.tsx
web/src/components/MemoContent/ReferencedContent/Error.tsx
+1
-1
ReferencedMemo.tsx
...mponents/MemoContent/ReferencedContent/ReferencedMemo.tsx
+1
-1
Spoiler.tsx
web/src/components/MemoContent/Spoiler.tsx
+1
-1
Table.tsx
web/src/components/MemoContent/Table.tsx
+5
-5
Tag.tsx
web/src/components/MemoContent/Tag.tsx
+1
-1
index.tsx
web/src/components/MemoContent/index.tsx
+3
-3
MemoDetailSidebar.tsx
web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx
+13
-13
MemoDetailSidebarDrawer.tsx
.../components/MemoDetailSidebar/MemoDetailSidebarDrawer.tsx
+2
-2
MemoDisplaySettingMenu.tsx
web/src/components/MemoDisplaySettingMenu.tsx
+3
-5
AddMemoRelationPopover.tsx
...onents/MemoEditor/ActionButton/AddMemoRelationPopover.tsx
+4
-4
MarkdownMenu.tsx
web/src/components/MemoEditor/ActionButton/MarkdownMenu.tsx
+3
-3
TagSelector.tsx
web/src/components/MemoEditor/ActionButton/TagSelector.tsx
+1
-1
VisibilitySelector.tsx
...components/MemoEditor/ActionButton/VisibilitySelector.tsx
+5
-5
AttachmentListView.tsx
web/src/components/MemoEditor/AttachmentListView.tsx
+1
-1
TagSuggestions.tsx
web/src/components/MemoEditor/Editor/TagSuggestions.tsx
+3
-3
index.tsx
web/src/components/MemoEditor/Editor/index.tsx
+1
-1
RelationListView.tsx
web/src/components/MemoEditor/RelationListView.tsx
+1
-1
index.tsx
web/src/components/MemoEditor/index.tsx
+4
-6
MemoFilters.tsx
web/src/components/MemoFilters.tsx
+4
-4
MemoLocationView.tsx
web/src/components/MemoLocationView.tsx
+1
-1
MemoRelationForceGraph.tsx
...ponents/MemoRelationForceGraph/MemoRelationForceGraph.tsx
+1
-1
MemoRelationListView.tsx
web/src/components/MemoRelationListView.tsx
+9
-9
MemoView.tsx
web/src/components/MemoView.tsx
+9
-9
MobileHeader.tsx
web/src/components/MobileHeader.tsx
+1
-1
Navigation.tsx
web/src/components/Navigation.tsx
+2
-2
NavigationDrawer.tsx
web/src/components/NavigationDrawer.tsx
+2
-2
PagedMemoList.tsx
web/src/components/PagedMemoList/PagedMemoList.tsx
+2
-2
PasswordSignInForm.tsx
web/src/components/PasswordSignInForm.tsx
+4
-4
ReactionSelector.tsx
web/src/components/ReactionSelector.tsx
+4
-4
ReactionView.tsx
web/src/components/ReactionView.tsx
+3
-3
RenameTagDialog.tsx
web/src/components/RenameTagDialog.tsx
+1
-1
RequiredBadge.tsx
web/src/components/RequiredBadge.tsx
+1
-1
SearchBar.tsx
web/src/components/SearchBar.tsx
+3
-5
AccessTokenSection.tsx
web/src/components/Settings/AccessTokenSection.tsx
+15
-15
MemberSection.tsx
web/src/components/Settings/MemberSection.tsx
+15
-15
MemoRelatedSettings.tsx
web/src/components/Settings/MemoRelatedSettings.tsx
+5
-5
MyAccountSection.tsx
web/src/components/Settings/MyAccountSection.tsx
+3
-3
PreferencesSection.tsx
web/src/components/Settings/PreferencesSection.tsx
+2
-2
SSOSection.tsx
web/src/components/Settings/SSOSection.tsx
+7
-11
SectionMenuItem.tsx
web/src/components/Settings/SectionMenuItem.tsx
+1
-1
StorageSection.tsx
web/src/components/Settings/StorageSection.tsx
+11
-11
UserSessionsSection.tsx
web/src/components/Settings/UserSessionsSection.tsx
+16
-16
WebhookSection.tsx
web/src/components/Settings/WebhookSection.tsx
+11
-11
WorkspaceSection.tsx
web/src/components/Settings/WorkspaceSection.tsx
+3
-3
MonthNavigator.tsx
web/src/components/StatisticsView/MonthNavigator.tsx
+1
-1
StatCard.tsx
web/src/components/StatisticsView/StatCard.tsx
+2
-2
StatisticsView.tsx
web/src/components/StatisticsView/StatisticsView.tsx
+1
-1
TagTree.tsx
web/src/components/TagTree.tsx
+5
-5
UpdateAccountDialog.tsx
web/src/components/UpdateAccountDialog.tsx
+4
-4
UpdateCustomizedProfileDialog.tsx
web/src/components/UpdateCustomizedProfileDialog.tsx
+1
-1
UserAvatar.tsx
web/src/components/UserAvatar.tsx
+1
-1
UserBanner.tsx
web/src/components/UserBanner.tsx
+7
-10
VisibilityIcon.tsx
web/src/components/VisibilityIcon.tsx
+1
-1
badge.tsx
web/src/components/ui/badge.tsx
+1
-1
button.tsx
web/src/components/ui/button.tsx
+1
-1
dialog.tsx
web/src/components/ui/dialog.tsx
+1
-1
sheet.tsx
web/src/components/ui/sheet.tsx
+1
-1
HomeLayout.tsx
web/src/layouts/HomeLayout.tsx
+1
-1
RootLayout.tsx
web/src/layouts/RootLayout.tsx
+1
-1
main.tsx
web/src/main.tsx
+1
-1
AdminSignIn.tsx
web/src/pages/AdminSignIn.tsx
+2
-2
Attachments.tsx
web/src/pages/Attachments.tsx
+9
-9
AuthCallback.tsx
web/src/pages/AuthCallback.tsx
+1
-1
Inboxes.tsx
web/src/pages/Inboxes.tsx
+5
-5
Loading.tsx
web/src/pages/Loading.tsx
+1
-1
MemoDetail.tsx
web/src/pages/MemoDetail.tsx
+7
-7
NotFound.tsx
web/src/pages/NotFound.tsx
+1
-1
PermissionDenied.tsx
web/src/pages/PermissionDenied.tsx
+1
-1
Setting.tsx
web/src/pages/Setting.tsx
+3
-3
SignIn.tsx
web/src/pages/SignIn.tsx
+5
-5
SignUp.tsx
web/src/pages/SignUp.tsx
+10
-10
UserProfile.tsx
web/src/pages/UserProfile.tsx
+2
-2
style.css
web/src/style.css
+66
-63
No files found.
web/index.html
View file @
91be2f68
...
...
@@ -11,7 +11,7 @@
<!-- memos.metadata.head -->
<title>
Memos
</title>
</head>
<body
class=
"text-base w-full min-h-svh
bg-zinc-50 dark:bg-zinc-900
"
>
<body
class=
"text-base w-full min-h-svh"
>
<div
id=
"root"
class=
"relative w-full min-h-full"
></div>
<script
type=
"module"
src=
"/src/main.tsx"
></script>
<!-- memos.metadata.body -->
...
...
web/src/components/ActivityCalendar/ActivityCalendar.tsx
View file @
91be2f68
...
...
@@ -9,10 +9,10 @@ import { useTranslate } from "@/utils/i18n";
const
getCellOpacity
=
(
ratio
:
number
):
string
=>
{
if
(
ratio
===
0
)
return
""
;
if
(
ratio
>
0.75
)
return
"bg-
green-700/90 text-gray-50 dark:bg-green-400/80
"
;
if
(
ratio
>
0.5
)
return
"bg-
green-700/70 text-gray-100 dark:bg-green-400/60
"
;
if
(
ratio
>
0.25
)
return
"bg-
green-700/70 text-gray-100 dark:bg-green-400/40
"
;
return
"bg-
green-700/50 text-gray-100 dark:bg-green-400/20
"
;
if
(
ratio
>
0.75
)
return
"bg-
primary/90 text-primary-foreground
"
;
if
(
ratio
>
0.5
)
return
"bg-
primary/70 text-primary-foreground
"
;
if
(
ratio
>
0.25
)
return
"bg-
primary/50 text-primary-foreground
"
;
return
"bg-
primary/30 text-primary-foreground
"
;
};
const
CalendarCell
=
memo
(
...
...
@@ -37,10 +37,10 @@ const CalendarCell = memo(
<
div
className=
{
cn
(
"w-6 h-6 text-xs lg:text-[13px] flex justify-center items-center cursor-default"
,
"rounded-lg border-2 text-
gray-400
transition-all duration-200"
,
"rounded-lg border-2 text-
muted-foreground
transition-all duration-200"
,
dayInfo
.
isCurrentMonth
&&
getCellOpacity
(
count
/
maxCount
),
dayInfo
.
isCurrentMonth
&&
isToday
&&
"border-
zinc-400
"
,
dayInfo
.
isCurrentMonth
&&
isSelected
&&
"font-medium border-
zinc-400
"
,
dayInfo
.
isCurrentMonth
&&
isToday
&&
"border-
border
"
,
dayInfo
.
isCurrentMonth
&&
isSelected
&&
"font-medium border-
border
"
,
dayInfo
.
isCurrentMonth
&&
!
isToday
&&
!
isSelected
&&
"border-transparent"
,
count
>
0
&&
"cursor-pointer hover:scale-110"
,
)
}
...
...
@@ -52,7 +52,7 @@ const CalendarCell = memo(
if
(
!
dayInfo
.
isCurrentMonth
)
{
return
(
<
div
className=
{
cn
(
"w-6 h-6 text-xs lg:text-[13px] flex justify-center items-center cursor-default opacity-60 text-
gray-400
"
)
}
>
<
div
className=
{
cn
(
"w-6 h-6 text-xs lg:text-[13px] flex justify-center items-center cursor-default opacity-60 text-
muted-foreground
"
)
}
>
{
dayInfo
.
day
}
</
div
>
);
...
...
web/src/components/BrandBanner.tsx
View file @
91be2f68
...
...
@@ -16,9 +16,9 @@ const BrandBanner = observer((props: Props) => {
return
(
<
div
className=
{
cn
(
"relative w-full h-auto shrink-0"
,
props
.
className
)
}
>
<
div
className=
{
cn
(
"w-auto flex flex-row justify-start items-center text-
gray-800 dark:text-gray-400
"
,
collapsed
?
"px-1"
:
"px-3"
)
}
>
<
div
className=
{
cn
(
"w-auto flex flex-row justify-start items-center text-
foreground
"
,
collapsed
?
"px-1"
:
"px-3"
)
}
>
<
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
>
}
{
!
collapsed
&&
<
span
className=
"ml-2 text-lg font-medium text-
foreground
shrink truncate"
>
{
title
}
</
span
>
}
</
div
>
</
div
>
);
...
...
web/src/components/ChangeMemberPasswordDialog.tsx
View file @
91be2f68
...
...
@@ -65,7 +65,7 @@ const ChangeMemberPasswordDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
>
{
t
(
"setting.account-section.change-password"
)
}
(
{
user
.
displayName
}
)
...
...
web/src/components/CreateAccessTokenDialog.tsx
View file @
91be2f68
...
...
@@ -88,7 +88,7 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center w-full mb-4 gap-2"
>
<
p
>
{
t
(
"setting.access-token-section.create-dialog.create-access-token"
)
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
()
=>
destroy
()
}
>
...
...
@@ -98,7 +98,7 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
<
div
className=
"flex flex-col justify-start items-start w-80!"
>
<
div
className=
"w-full flex flex-col justify-start items-start mb-3"
>
<
span
className=
"mb-2"
>
{
t
(
"setting.access-token-section.create-dialog.description"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
{
t
(
"setting.access-token-section.create-dialog.description"
)
}
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
span
>
<
div
className=
"relative w-full"
>
<
Input
...
...
@@ -112,7 +112,7 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-start mb-3"
>
<
span
className=
"mb-2"
>
{
t
(
"setting.access-token-section.create-dialog.expiration"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
{
t
(
"setting.access-token-section.create-dialog.expiration"
)
}
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
span
>
<
div
className=
"w-full flex flex-row justify-start items-center text-base"
>
<
RadioGroup
value=
{
state
.
expiration
.
toString
()
}
onValueChange=
{
handleRoleInputChange
}
className=
"flex flex-row gap-4"
>
...
...
web/src/components/CreateIdentityProviderDialog.tsx
View file @
91be2f68
...
...
@@ -244,7 +244,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
>
{
t
(
isCreating
?
"setting.sso-section.create-sso"
:
"setting.sso-section.update-sso"
)
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
handleCloseBtnClick
}
>
...
...
@@ -285,7 +285,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
)
}
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"common.name"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -314,13 +314,13 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
{
type
===
"OAUTH2"
&&
(
<>
{
isCreating
&&
(
<
p
className=
"border border-
zinc-100 dark:border-zinc-700
rounded-md p-2 text-sm w-full mb-2 break-all"
>
<
p
className=
"border border-
border
rounded-md p-2 text-sm w-full mb-2 break-all"
>
{
t
(
"setting.sso-section.redirect-url"
)
}
:
{
absolutifyLink
(
"/auth/callback"
)
}
</
p
>
)
}
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.client-id"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -330,7 +330,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
/>
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.client-secret"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -340,7 +340,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
/>
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.authorization-endpoint"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -350,7 +350,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
/>
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.token-endpoint"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -360,7 +360,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
/>
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.user-endpoint"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -370,7 +370,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
/>
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.scopes"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
@@ -381,7 +381,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
<
Separator
className=
"my-2"
/>
<
p
className=
"mb-1 text-sm font-medium"
>
{
t
(
"setting.sso-section.identifier"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
p
>
<
Input
className=
"mb-2 w-full"
...
...
web/src/components/CreateShortcutDialog.tsx
View file @
91be2f68
...
...
@@ -73,7 +73,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
className=
"title-text"
>
{
`${isCreating ? t("common.create") : t("common.edit")} ${t("common.shortcuts")}`
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
()
=>
destroy
()
}
>
...
...
@@ -98,7 +98,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<
ul
className=
"list-disc list-inside text-sm pl-2 mt-1"
>
<
li
>
<
a
className=
"text-sm text-
blue-600
hover:underline"
className=
"text-sm text-
primary
hover:underline"
href=
"https://www.usememos.com/docs/getting-started/shortcuts"
target=
"_blank"
>
...
...
@@ -107,7 +107,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
</
li
>
<
li
>
<
a
className=
"text-sm text-
blue-600
hover:underline"
className=
"text-sm text-
primary
hover:underline"
href=
"https://www.usememos.com/docs/getting-started/shortcuts#how-to-write-a-filter"
target=
"_blank"
>
...
...
web/src/components/CreateUserDialog.tsx
View file @
91be2f68
...
...
@@ -65,7 +65,7 @@ const CreateUserDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
className=
"title-text"
>
{
`${isCreating ? t("common.create") : t("common.edit")} ${t("common.user")}`
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
()
=>
destroy
()
}
>
...
...
web/src/components/CreateWebhookDialog.tsx
View file @
91be2f68
...
...
@@ -104,7 +104,7 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
className=
"title-text"
>
{
isCreating
?
t
(
"setting.webhook-section.create-dialog.create-webhook"
)
:
t
(
"setting.webhook-section.create-dialog.edit-webhook"
)
}
...
...
@@ -116,7 +116,7 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
<
div
className=
"flex flex-col justify-start items-start w-80!"
>
<
div
className=
"w-full flex flex-col justify-start items-start mb-3"
>
<
span
className=
"mb-2"
>
{
t
(
"setting.webhook-section.create-dialog.title"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
{
t
(
"setting.webhook-section.create-dialog.title"
)
}
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
span
>
<
div
className=
"relative w-full"
>
<
Input
...
...
@@ -130,7 +130,7 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-start mb-3"
>
<
span
className=
"mb-2"
>
{
t
(
"setting.webhook-section.create-dialog.payload-url"
)
}
<
span
className=
"text-
red-600
"
>
*
</
span
>
{
t
(
"setting.webhook-section.create-dialog.payload-url"
)
}
<
span
className=
"text-
destructive
"
>
*
</
span
>
</
span
>
<
div
className=
"relative w-full"
>
<
Input
...
...
web/src/components/DateTimeInput.tsx
View file @
91be2f68
...
...
@@ -20,7 +20,7 @@ const DateTimeInput: React.FC<Props> = ({ value, onChange }) => {
type=
"text"
className=
{
cn
(
"px-1 bg-transparent rounded text-xs transition-all"
,
"border-transparent outline-none focus:border-
gray-300 dark:focus:border-zinc-700
"
,
"border-transparent outline-none focus:border-
border
"
,
"border"
,
)
}
defaultValue=
{
formatDate
(
value
)
}
...
...
web/src/components/Dialog/BaseDialog.tsx
View file @
91be2f68
...
...
@@ -52,7 +52,7 @@ const BaseDialog = observer((props: Props) => {
return
(
<
div
className=
{
cn
(
"fixed top-0 left-0 flex flex-col justify-start items-center w-full h-full pt-16 pb-8 px-4 z-1000 overflow-x-hidden overflow-y-scroll transition-all hide-scrollbar bg-
black
/60"
,
"fixed top-0 left-0 flex flex-col justify-start items-center w-full h-full pt-16 pb-8 px-4 z-1000 overflow-x-hidden overflow-y-scroll transition-all hide-scrollbar bg-
foreground
/60"
,
className
,
)
}
onMouseDown=
{
handleSpaceClicked
}
...
...
web/src/components/Empty.tsx
View file @
91be2f68
...
...
@@ -3,7 +3,7 @@ import { BirdIcon } from "lucide-react";
const
Empty
=
()
=>
{
return
(
<
div
className=
"mx-auto"
>
<
BirdIcon
strokeWidth=
{
0.5
}
absoluteStrokeWidth=
{
true
}
className=
"w-24 h-auto text-
gray-500 dark:text-gray-400
"
/>
<
BirdIcon
strokeWidth=
{
0.5
}
absoluteStrokeWidth=
{
true
}
className=
"w-24 h-auto text-
muted-foreground
"
/>
</
div
>
);
};
...
...
web/src/components/HomeSidebar/HomeSidebarDrawer.tsx
View file @
91be2f68
...
...
@@ -17,10 +17,10 @@ const HomeSidebarDrawer = () => {
<
Sheet
open=
{
open
}
onOpenChange=
{
setOpen
}
>
<
SheetTrigger
asChild
>
<
Button
variant=
"ghost"
className=
"bg-transparent! px-2"
>
<
MenuIcon
className=
"w-6 h-auto
dark:text-gray-400
"
/>
<
MenuIcon
className=
"w-6 h-auto
text-foreground
"
/>
</
Button
>
</
SheetTrigger
>
<
SheetContent
side=
"right"
className=
"w-full sm:w-80 bg-
zinc-100 dark:bg-zinc-900
"
>
<
SheetContent
side=
"right"
className=
"w-full sm:w-80 bg-
secondary
"
>
<
HomeSidebar
className=
"px-4 py-4"
/>
</
SheetContent
>
</
Sheet
>
...
...
web/src/components/HomeSidebar/ShortcutsSection.tsx
View file @
91be2f68
...
...
@@ -38,7 +38,7 @@ const ShortcutsSection = observer(() => {
return
(
<
div
className=
"w-full flex flex-col justify-start items-start mt-3 px-1 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
<
div
className=
"flex flex-row justify-between items-center w-full gap-1 mb-1 text-sm leading-6 text-
gray-400
select-none"
>
<
div
className=
"flex flex-row justify-between items-center w-full gap-1 mb-1 text-sm leading-6 text-
muted-foreground
select-none"
>
<
span
>
{
t
(
"common.shortcuts"
)
}
</
span
>
<
TooltipProvider
>
<
Tooltip
>
...
...
@@ -61,10 +61,10 @@ const ShortcutsSection = observer(() => {
return
(
<
div
key=
{
shortcutId
}
className=
"shrink-0 w-full text-sm rounded-md leading-6 flex flex-row justify-between items-center select-none gap-2 text-
gray-600 dark:text-gray-400 dark:border-zinc-800
"
className=
"shrink-0 w-full text-sm rounded-md leading-6 flex flex-row justify-between items-center select-none gap-2 text-
muted-foreground
"
>
<
span
className=
{
cn
(
"truncate cursor-pointer
dark:
opacity-80"
,
selected
&&
"text-primary font-medium"
)
}
className=
{
cn
(
"truncate cursor-pointer opacity-80"
,
selected
&&
"text-primary font-medium"
)
}
onClick=
{
()
=>
(
selected
?
memoFilterStore
.
setShortcut
(
undefined
)
:
memoFilterStore
.
setShortcut
(
shortcutId
))
}
>
{
emoji
&&
<
span
className=
"text-base mr-1"
>
{
emoji
}
</
span
>
}
...
...
@@ -78,14 +78,14 @@ const ShortcutsSection = observer(() => {
<
div
className=
"flex flex-col text-sm gap-0.5"
>
<
button
onClick=
{
()
=>
showCreateShortcutDialog
({
shortcut
})
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
<
Edit3Icon
className=
"w-4 h-auto"
/>
{
t
(
"common.edit"
)
}
</
button
>
<
button
onClick=
{
()
=>
handleDeleteShortcut
(
shortcut
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
destructive hover:bg-muted
outline-none rounded"
>
<
TrashIcon
className=
"w-4 h-auto"
/>
{
t
(
"common.delete"
)
}
...
...
web/src/components/HomeSidebar/TagsSection.tsx
View file @
91be2f68
...
...
@@ -48,7 +48,7 @@ const TagsSection = observer((props: Props) => {
return
(
<
div
className=
"flex flex-col justify-start items-start w-full mt-3 px-1 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
<
div
className=
"flex flex-row justify-between items-center w-full gap-1 mb-1 text-sm leading-6 text-
gray-400
select-none"
>
<
div
className=
"flex flex-row justify-between items-center w-full gap-1 mb-1 text-sm leading-6 text-
muted-foreground
select-none"
>
<
span
>
{
t
(
"common.tags"
)
}
</
span
>
{
tags
.
length
>
0
&&
(
<
Popover
>
...
...
@@ -57,7 +57,7 @@ const TagsSection = observer((props: Props) => {
</
PopoverTrigger
>
<
PopoverContent
align=
"end"
alignOffset=
{
-
12
}
>
<
div
className=
"w-auto flex flex-row justify-between items-center gap-2 p-1"
>
<
span
className=
"text-sm shrink-0
dark:text-zinc-400
"
>
{
t
(
"common.tree-mode"
)
}
</
span
>
<
span
className=
"text-sm shrink-0"
>
{
t
(
"common.tree-mode"
)
}
</
span
>
<
Switch
checked=
{
treeMode
}
onCheckedChange=
{
(
checked
)
=>
setTreeMode
(
checked
)
}
/>
</
div
>
</
PopoverContent
>
...
...
@@ -72,7 +72,7 @@ const TagsSection = observer((props: Props) => {
{
tags
.
map
(([
tag
,
amount
])
=>
(
<
div
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
"
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-
muted-foreground
"
>
<
Popover
>
<
PopoverTrigger
asChild
>
...
...
@@ -85,14 +85,14 @@ const TagsSection = observer((props: Props) => {
<
div
className=
"flex flex-col text-sm gap-0.5"
>
<
button
onClick=
{
()
=>
showRenameTagDialog
({
tag
:
tag
})
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
<
Edit3Icon
className=
"w-4 h-auto"
/>
{
t
(
"common.rename"
)
}
</
button
>
<
button
onClick=
{
()
=>
handleDeleteTag
(
tag
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
destructive hover:bg-muted
outline-none rounded"
>
<
TrashIcon
className=
"w-4 h-auto"
/>
{
t
(
"common.delete"
)
}
...
...
@@ -104,7 +104,7 @@ const TagsSection = observer((props: Props) => {
className=
{
cn
(
"inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]"
)
}
onClick=
{
()
=>
handleTagClick
(
tag
)
}
>
<
span
className=
"truncate
dark:
opacity-80"
>
{
tag
}
</
span
>
<
span
className=
"truncate opacity-80"
>
{
tag
}
</
span
>
{
amount
>
1
&&
<
span
className=
"opacity-60 shrink-0"
>
(
{
amount
}
)
</
span
>
}
</
div
>
</
div
>
...
...
@@ -113,7 +113,7 @@ const TagsSection = observer((props: Props) => {
)
)
:
(
!
props
.
readonly
&&
(
<
div
className=
"p-2 border border-dashed
border-zinc-200 dark:border-zinc-800 rounded-md flex flex-row justify-start items-start gap-1 text-gray-400 dark:text-gray-500
"
>
<
div
className=
"p-2 border border-dashed
rounded-md flex flex-row justify-start items-start gap-1 text-muted-foreground
"
>
<
TagsIcon
/>
<
p
className=
"mt-0.5 text-sm leading-snug italic"
>
{
t
(
"tag.create-tags-guide"
)
}
</
p
>
</
div
>
...
...
web/src/components/Inbox/MemoCommentMessage.tsx
View file @
91be2f68
...
...
@@ -75,8 +75,8 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
className=
{
cn
(
"shrink-0 mt-2 p-2 rounded-full border"
,
inbox
.
status
===
Inbox_Status
.
UNREAD
?
"border-
blue-600 text-blue-600 bg-blue-50 dark:bg-zinc-80
0"
:
"border-
gray-500 text-gray-500 bg-gray-50 dark:bg-zinc-800
"
,
?
"border-
primary text-primary bg-primary/1
0"
:
"border-
muted-foreground text-muted-foreground bg-secondary
"
,
)
}
>
<
TooltipProvider
>
...
...
@@ -92,21 +92,21 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
</
div
>
<
div
className=
{
cn
(
"border w-full p-2 px-3 rounded-lg flex flex-col justify-start items-start gap-1
dark:border-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-700
"
,
"border w-full p-2 px-3 rounded-lg flex flex-col justify-start items-start gap-1
border-border hover:bg-secondary
"
,
inbox
.
status
!==
Inbox_Status
.
UNREAD
&&
"opacity-60"
,
)
}
>
{
initialized
?
(
<>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-sm text-
gray-500
"
>
{
inbox
.
createTime
?.
toLocaleString
()
}
</
span
>
<
span
className=
"text-sm text-
muted-foreground
"
>
{
inbox
.
createTime
?.
toLocaleString
()
}
</
span
>
<
div
>
{
inbox
.
status
===
Inbox_Status
.
UNREAD
&&
(
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
>
<
InboxIcon
className=
"w-4 h-auto cursor-pointer text-
gray-400 hover:text-blue-600
"
className=
"w-4 h-auto cursor-pointer text-
muted-foreground hover:text-primary
"
onClick=
{
()
=>
handleArchiveMessage
()
}
/>
</
TooltipTrigger
>
...
...
@@ -119,7 +119,7 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
</
div
>
</
div
>
<
p
className=
"text-base leading-tight cursor-pointer text-
gray-500 dark:text-gray-400 hover:underline hover:text-blue-600
"
className=
"text-base leading-tight cursor-pointer text-
muted-foreground hover:underline hover:text-primary
"
onClick=
{
handleNavigateToMemo
}
>
{
t
(
"inbox.memo-comment"
,
{
...
...
@@ -131,7 +131,7 @@ const MemoCommentMessage = observer(({ inbox }: Props) => {
</>
)
:
(
<
div
className=
"w-full flex flex-row justify-center items-center my-2"
>
<
LoaderIcon
className=
"animate-spin text-
zinc-500
"
/>
<
LoaderIcon
className=
"animate-spin text-
muted-foreground
"
/>
</
div
>
)
}
</
div
>
...
...
web/src/components/LearnMore.tsx
View file @
91be2f68
...
...
@@ -16,7 +16,7 @@ const LearnMore: React.FC<Props> = (props: Props) => {
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
a
className=
{
`text-
gray-500 dark:text-gray-400 hover:text-blue-600
${className}`
}
href=
{
url
}
target=
"_blank"
>
<
a
className=
{
`text-
muted-foreground hover:text-primary
${className}`
}
href=
{
url
}
target=
"_blank"
>
<
ExternalLinkIcon
className=
"w-4 h-auto"
/>
</
a
>
</
TooltipTrigger
>
...
...
web/src/components/MemoActionMenu.tsx
View file @
91be2f68
...
...
@@ -166,7 +166,7 @@ const MemoActionMenu = observer((props: Props) => {
<
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
"
/>
<
MoreVerticalIcon
className=
"w-4 h-4 mx-auto text-
muted-foreground
"
/>
</
span
>
</
PopoverTrigger
>
<
PopoverContent
align=
"end"
sideOffset=
{
2
}
>
...
...
@@ -176,7 +176,7 @@ const MemoActionMenu = observer((props: Props) => {
{
!
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
{
memo
.
pinned
?
<
BookmarkMinusIcon
className=
"w-4 h-auto"
/>
:
<
BookmarkPlusIcon
className=
"w-4 h-auto"
/>
}
{
memo
.
pinned
?
t
(
"common.unpin"
)
:
t
(
"common.pin"
)
}
...
...
@@ -184,7 +184,7 @@ const MemoActionMenu = observer((props: Props) => {
)
}
<
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
<
Edit3Icon
className=
"w-4 h-auto"
/>
{
t
(
"common.edit"
)
}
...
...
@@ -192,10 +192,7 @@ const MemoActionMenu = observer((props: Props) => {
</>
)
}
{
!
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"
>
<
button
onClick=
{
handleCopyLink
}
className=
"flex items-center gap-2 px-2 py-1 text-left hover:bg-muted outline-none rounded"
>
<
CopyIcon
className=
"w-4 h-auto"
/>
{
t
(
"memo.copy-link"
)
}
</
button
>
...
...
@@ -205,7 +202,7 @@ const MemoActionMenu = observer((props: Props) => {
{
!
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
primary hover:bg-muted
outline-none rounded"
>
<
SquareCheckIcon
className=
"w-4 h-auto"
/>
{
t
(
"memo.remove-completed-task-list-items"
)
}
...
...
@@ -214,7 +211,7 @@ const MemoActionMenu = observer((props: Props) => {
{
!
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
primary hover:bg-muted
outline-none rounded"
>
{
isArchived
?
<
ArchiveRestoreIcon
className=
"w-4 h-auto"
/>
:
<
ArchiveIcon
className=
"w-4 h-auto"
/>
}
{
isArchived
?
t
(
"common.restore"
)
:
t
(
"common.archive"
)
}
...
...
@@ -222,7 +219,7 @@ const MemoActionMenu = observer((props: Props) => {
)
}
<
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
destructive hover:bg-muted
outline-none rounded"
>
<
TrashIcon
className=
"w-4 h-auto"
/>
{
t
(
"common.delete"
)
}
...
...
web/src/components/MemoAttachment.tsx
View file @
91be2f68
...
...
@@ -16,7 +16,7 @@ const MemoAttachment: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
{
`w-auto flex flex-row justify-start items-center text-
gray-500 dark:text-gray-400
hover:opacity-80 ${className}`
}
>
<
div
className=
{
`w-auto flex flex-row justify-start items-center text-
muted-foreground
hover:opacity-80 ${className}`
}
>
{
attachment
.
type
.
startsWith
(
"audio"
)
?
(
<
audio
src=
{
attachmentUrl
}
controls
></
audio
>
)
:
(
...
...
web/src/components/MemoAttachmentListView.tsx
View file @
91be2f68
...
...
@@ -35,7 +35,7 @@ const MemoAttachmentListView = ({ attachments = [] }: { attachments: Attachment[
return
(
<
img
className=
{
cn
(
"cursor-pointer h-full w-auto rounded-lg border border-
zinc-200 dark:border-zinc-800
object-contain hover:opacity-80"
,
"cursor-pointer h-full w-auto rounded-lg border border-
border
object-contain hover:opacity-80"
,
className
,
)
}
src=
{
attachment
.
externalLink
?
attachmentUrl
:
attachmentUrl
+
"?thumbnail=true"
}
...
...
@@ -48,7 +48,7 @@ const MemoAttachmentListView = ({ attachments = [] }: { attachments: Attachment[
return
(
<
video
className=
{
cn
(
"cursor-pointer h-full w-auto rounded-lg border border-
zinc-200 dark:border-zinc-800 object-contain bg-zinc-100 dark:bg-zinc-800
"
,
"cursor-pointer h-full w-auto rounded-lg border border-
border object-contain bg-secondary
"
,
className
,
)
}
preload=
"metadata"
...
...
web/src/components/MemoContent/Blockquote.tsx
View file @
91be2f68
...
...
@@ -8,7 +8,7 @@ interface Props extends BaseProps {
const
Blockquote
:
React
.
FC
<
Props
>
=
({
children
}:
Props
)
=>
{
return
(
<
blockquote
className=
"p-2 border-s-4 rounded border-
gray-300 bg-gray-50 dark:border-gray-500 dark:bg-zinc-700
"
>
<
blockquote
className=
"p-2 border-s-4 rounded border-
muted bg-muted
"
>
{
children
.
map
((
child
,
index
)
=>
(
<
Renderer
key=
{
`${child.type}-${index}`
}
index=
{
String
(
index
)
}
node=
{
child
}
/>
))
}
...
...
web/src/components/MemoContent/Code.tsx
View file @
91be2f68
...
...
@@ -3,7 +3,7 @@ interface Props {
}
const
Code
:
React
.
FC
<
Props
>
=
({
content
}:
Props
)
=>
{
return
<
code
className=
"inline break-all px-1 font-mono text-sm rounded opacity-80 bg-
gray-100 dark:bg-zinc-700
"
>
{
content
}
</
code
>;
return
<
code
className=
"inline break-all px-1 font-mono text-sm rounded opacity-80 bg-
muted
"
>
{
content
}
</
code
>;
};
export
default
Code
;
web/src/components/MemoContent/CodeBlock.tsx
View file @
91be2f68
...
...
@@ -59,14 +59,14 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
},
[
content
]);
return
(
<
div
className=
"w-full my-1 bg-a
mber-100 border-l-4 border-amber-400 rounded hover:shadow dark:bg-zinc-600 dark:border-zinc-400
relative"
>
<
div
className=
"w-full px-2 py-1 flex flex-row justify-between items-center text-a
mber-500 dark:text-zinc-400
"
>
<
div
className=
"w-full my-1 bg-a
ccent/10 border-l-4 border-accent rounded hover:shadow
relative"
>
<
div
className=
"w-full px-2 py-1 flex flex-row justify-between items-center text-a
ccent-foreground
"
>
<
span
className=
"text-sm font-mono"
>
{
formatedLanguage
}
</
span
>
<
CopyIcon
className=
"w-4 h-auto cursor-pointer hover:opacity-80"
onClick=
{
handleCopyButtonClick
}
/>
</
div
>
<
div
className=
"overflow-auto"
>
<
pre
className=
{
cn
(
"no-wrap overflow-auto"
,
"w-full p-2 bg-a
mber-50 dark:bg-zinc-700
relative"
)
}
>
<
pre
className=
{
cn
(
"no-wrap overflow-auto"
,
"w-full p-2 bg-a
ccent/5
relative"
)
}
>
<
code
className=
{
cn
(
`language-${formatedLanguage}`
,
"block text-sm leading-5"
)
}
dangerouslySetInnerHTML=
{
{
__html
:
highlightedCode
}
}
...
...
web/src/components/MemoContent/EmbeddedContent/EmbeddedMemo.tsx
View file @
91be2f68
...
...
@@ -45,7 +45,7 @@ const EmbeddedMemo = observer(({ resourceId: uid, params: paramsStr }: Props) =>
// Add the memo to the set of embedded memos. This is used to prevent infinite loops when a memo embeds itself.
context
.
embeddedMemos
.
add
(
memoName
);
const
contentNode
=
useSnippet
?
(
<
div
className=
{
cn
(
"text-
gray-800 dark:text-gray-400
"
,
inlineMode
?
""
:
"line-clamp-3"
)
}
>
{
memo
.
snippet
}
</
div
>
<
div
className=
{
cn
(
"text-
muted-foreground
"
,
inlineMode
?
""
:
"line-clamp-3"
)
}
>
{
memo
.
snippet
}
</
div
>
)
:
(
<>
<
MemoContent
...
...
@@ -67,8 +67,8 @@ const EmbeddedMemo = observer(({ resourceId: uid, params: paramsStr }: Props) =>
};
return
(
<
div
className=
"relative flex flex-col justify-start items-start w-full px-3 py-2 bg-
zinc-50 dark:bg-zinc-900 rounded-lg border border-zinc-200 dark:border-zinc-700
hover:shadow"
>
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center text-
gray-400 dark:text-gray-500
"
>
<
div
className=
"relative flex flex-col justify-start items-start w-full px-3 py-2 bg-
secondary rounded-lg border border-border
hover:shadow"
>
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center text-
muted-foreground
"
>
<
div
className=
"text-sm leading-5 select-none"
>
<
relative
-
time
datetime=
{
memo
.
displayTime
?.
toISOString
()
}
format=
"datetime"
></
relative
-
time
>
</
div
>
...
...
web/src/components/MemoContent/EmbeddedContent/Error.tsx
View file @
91be2f68
...
...
@@ -3,7 +3,7 @@ interface Props {
}
const
Error
=
({
message
}:
Props
)
=>
{
return
<
p
className=
"font-mono text-sm text-
red-600 dark:text-red-700
"
>
{
message
}
</
p
>;
return
<
p
className=
"font-mono text-sm text-
destructive
"
>
{
message
}
</
p
>;
};
export
default
Error
;
web/src/components/MemoContent/Link.tsx
View file @
91be2f68
...
...
@@ -47,7 +47,7 @@ const Link: React.FC<Props> = ({ content, url }: Props) => {
<
Tooltip
open=
{
showTooltip
}
>
<
TooltipTrigger
asChild
>
<
a
className=
"underline text-
blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-30
0"
className=
"underline text-
primary hover:text-primary/8
0"
target=
"_blank"
href=
{
url
}
rel=
"noopener noreferrer"
...
...
@@ -62,7 +62,7 @@ const Link: React.FC<Props> = ({ content, url }: Props) => {
<
div
className=
"w-full flex flex-col"
>
<
div
className=
"w-full flex flex-row justify-start items-center gap-1"
>
<
img
className=
"w-5 h-5 rounded"
src=
{
getFaviconWithGoogleS2
(
url
)
}
alt=
{
linkMetadata
?.
title
}
/>
<
h3
className=
"text-base truncate
dark:opacity-90
"
>
{
linkMetadata
?.
title
}
</
h3
>
<
h3
className=
"text-base truncate"
>
{
linkMetadata
?.
title
}
</
h3
>
</
div
>
{
linkMetadata
.
description
&&
(
<
p
className=
"mt-1 w-full text-sm leading-snug opacity-80 line-clamp-3"
>
{
linkMetadata
.
description
}
</
p
>
...
...
web/src/components/MemoContent/ReferencedContent/Error.tsx
View file @
91be2f68
...
...
@@ -3,7 +3,7 @@ interface Props {
}
const
Error
=
({
message
}:
Props
)
=>
{
return
<
p
className=
"font-mono text-sm text-
red-600 dark:text-red-700
"
>
{
message
}
</
p
>;
return
<
p
className=
"font-mono text-sm text-
destructive
"
>
{
message
}
</
p
>;
};
export
default
Error
;
web/src/components/MemoContent/ReferencedContent/ReferencedMemo.tsx
View file @
91be2f68
...
...
@@ -44,7 +44,7 @@ const ReferencedMemo = observer(({ resourceId: uid, params: paramsStr }: Props)
return
(
<
span
className=
"text-
blue-600 whitespace-nowrap dark:text-blue-400
cursor-pointer underline break-all hover:opacity-80 decoration-1"
className=
"text-
primary whitespace-nowrap
cursor-pointer underline break-all hover:opacity-80 decoration-1"
onClick=
{
handleGotoMemoDetailPage
}
>
{
displayContent
}
...
...
web/src/components/MemoContent/Spoiler.tsx
View file @
91be2f68
...
...
@@ -10,7 +10,7 @@ const Spoiler: React.FC<Props> = ({ content }: Props) => {
return
(
<
span
className=
{
cn
(
"inline cursor-pointer select-none"
,
isRevealed
?
""
:
"bg-
gray-200 dark:bg-zinc-700
"
)
}
className=
{
cn
(
"inline cursor-pointer select-none"
,
isRevealed
?
""
:
"bg-
muted
"
)
}
onClick=
{
()
=>
setIsRevealed
(
!
isRevealed
)
}
>
<
span
className=
{
cn
(
isRevealed
?
"opacity-100"
:
"opacity-0"
)
}
>
{
content
}
</
span
>
...
...
web/src/components/MemoContent/Table.tsx
View file @
91be2f68
...
...
@@ -9,9 +9,9 @@ interface Props {
const
Table
=
({
header
,
rows
}:
Props
)
=>
{
return
(
<
table
className=
"w-auto max-w-full border border-
zinc-200 dark:border-zinc-600 divide-y divide-zinc-200 dark:divide-zinc-600
"
>
<
thead
className=
"text-sm font-medium leading-5 text-left text-
gray-900 dark:text-gray-400
"
>
<
tr
className=
"divide-x divide-
zinc-200 dark:divide-zinc-600
"
>
<
table
className=
"w-auto max-w-full border border-
border divide-y divide-border
"
>
<
thead
className=
"text-sm font-medium leading-5 text-left text-
foreground
"
>
<
tr
className=
"divide-x divide-
border
"
>
{
header
.
map
((
h
,
i
)
=>
(
<
th
key=
{
i
}
className=
"py-1 px-2"
>
<
Renderer
key=
{
`${h.type}-${i}`
}
index=
{
String
(
i
)
}
node=
{
h
}
/>
...
...
@@ -19,9 +19,9 @@ const Table = ({ header, rows }: Props) => {
))
}
</
tr
>
</
thead
>
<
tbody
className=
"divide-y divide-
zinc-200 dark:divide-zinc-600 text-sm leading-5 text-left text-gray-900 dark:text-gray-400
"
>
<
tbody
className=
"divide-y divide-
border text-sm leading-5 text-left text-foreground
"
>
{
rows
.
map
((
row
,
i
)
=>
(
<
tr
key=
{
i
}
className=
"divide-x divide-
zinc-200 dark:divide-zinc-600
"
>
<
tr
key=
{
i
}
className=
"divide-x divide-
border
"
>
{
row
.
cells
.
map
((
r
,
j
)
=>
(
<
td
key=
{
j
}
className=
"py-1 px-2"
>
<
Renderer
key=
{
`${r.type}-${i}-${j}`
}
index=
{
String
(
j
)
}
node=
{
r
}
/>
...
...
web/src/components/MemoContent/Tag.tsx
View file @
91be2f68
...
...
@@ -45,7 +45,7 @@ const Tag = observer(({ content }: Props) => {
return
(
<
span
className=
{
cn
(
"inline-block w-auto text-
blue-600 dark:text-blue-400
"
,
context
.
disableFilter
?
""
:
"cursor-pointer hover:opacity-80"
)
}
className=
{
cn
(
"inline-block w-auto text-
primary
"
,
context
.
disableFilter
?
""
:
"cursor-pointer hover:opacity-80"
)
}
onClick=
{
handleTagClick
}
>
#
{
content
}
...
...
web/src/components/MemoContent/index.tsx
View file @
91be2f68
...
...
@@ -83,7 +83,7 @@ const MemoContent = observer((props: Props) => {
parentPage
:
props
.
parentPage
,
}
}
>
<
div
className=
{
`w-full flex flex-col justify-start items-start text-
gray-800 dark:text-gray-400
${className || ""}`
}
>
<
div
className=
{
`w-full flex flex-col justify-start items-start text-
foreground
${className || ""}`
}
>
<
div
ref=
{
memoContentContainerRef
}
className=
{
cn
(
...
...
@@ -104,13 +104,13 @@ const MemoContent = observer((props: Props) => {
return
<
Renderer
key=
{
`${node.type}-${index}`
}
index=
{
String
(
index
)
}
node=
{
node
}
/>;
})
}
{
showCompactMode
==
"ALL"
&&
(
<
div
className=
"absolute bottom-0 left-0 w-full h-12 bg-linear-to-b from-transparent
dark:to-zinc-800 to-white
pointer-events-none"
></
div
>
<
div
className=
"absolute bottom-0 left-0 w-full h-12 bg-linear-to-b from-transparent
to-background
pointer-events-none"
></
div
>
)
}
</
div
>
{
showCompactMode
!=
undefined
&&
(
<
div
className=
"w-full mt-1"
>
<
span
className=
"w-auto flex flex-row justify-start items-center cursor-pointer text-sm text-
blue-600 dark:text-blue-400
hover:opacity-80"
className=
"w-auto flex flex-row justify-start items-center cursor-pointer text-sm text-
primary
hover:opacity-80"
onClick=
{
()
=>
{
setShowCompactMode
(
compactStates
[
showCompactMode
].
nextState
as
ContentCompactView
);
}
}
...
...
web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx
View file @
91be2f68
...
...
@@ -23,7 +23,7 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
>
<
div
className=
"flex flex-col justify-start items-start w-full px-1 gap-2 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
{
shouldShowRelationGraph
&&
(
<
div
className=
"relative w-full h-36 border border-
zinc-200 rounded-lg bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800
"
>
<
div
className=
"relative w-full h-36 border border-
border rounded-lg bg-muted
"
>
<
MemoRelationForceGraph
className=
"w-full h-full"
memo=
{
memo
}
parentPage=
{
parentPage
}
/>
<
div
className=
"absolute top-1 left-2 text-xs opacity-60 font-mono gap-1 flex flex-row items-center"
>
<
span
>
{
t
(
"common.relations"
)
}
</
span
>
...
...
@@ -32,27 +32,27 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
</
div
>
)
}
<
div
className=
"w-full flex flex-col"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
gray-400 dark:text-gray-500
select-none"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
muted-foreground
select-none"
>
<
span
>
{
t
(
"common.created-at"
)
}
</
span
>
</
p
>
<
p
className=
"text-sm text-
gray-500 dark:text-gray-400
"
>
{
memo
.
createTime
?.
toLocaleString
()
}
</
p
>
<
p
className=
"text-sm text-
muted-foreground
"
>
{
memo
.
createTime
?.
toLocaleString
()
}
</
p
>
</
div
>
{
!
isEqual
(
memo
.
createTime
,
memo
.
updateTime
)
&&
(
<
div
className=
"w-full flex flex-col"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
gray-400 dark:text-gray-500
select-none"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
muted-foreground
select-none"
>
<
span
>
{
t
(
"common.last-updated-at"
)
}
</
span
>
</
p
>
<
p
className=
"text-sm text-
gray-500 dark:text-gray-400
"
>
{
memo
.
updateTime
?.
toLocaleString
()
}
</
p
>
<
p
className=
"text-sm text-
muted-foreground
"
>
{
memo
.
updateTime
?.
toLocaleString
()
}
</
p
>
</
div
>
)
}
{
hasSpecialProperty
&&
(
<
div
className=
"w-full flex flex-col"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
gray-400 dark:text-gray-500
select-none"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
muted-foreground
select-none"
>
<
span
>
{
t
(
"common.properties"
)
}
</
span
>
</
p
>
<
div
className=
"w-full flex flex-row justify-start items-center gap-x-2 gap-y-1 flex-wrap text-
gray-500 dark:text-gray-400
"
>
<
div
className=
"w-full flex flex-row justify-start items-center gap-x-2 gap-y-1 flex-wrap text-
muted-foreground
"
>
{
property
.
hasLink
&&
(
<
div
className=
"w-auto border border-
zinc-200 dark:border-zinc-800
pl-1 pr-1.5 rounded-md flex justify-between items-center"
>
<
div
className=
"w-auto border border-
border
pl-1 pr-1.5 rounded-md flex justify-between items-center"
>
<
div
className=
"w-auto flex justify-start items-center mr-1"
>
<
LinkIcon
className=
"w-4 h-auto mr-1"
/>
<
span
className=
"block text-sm"
>
{
t
(
"memo.links"
)
}
</
span
>
...
...
@@ -60,7 +60,7 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
</
div
>
)
}
{
property
.
hasTaskList
&&
(
<
div
className=
"w-auto border border-
zinc-200 dark:border-zinc-800
pl-1 pr-1.5 rounded-md flex justify-between items-center"
>
<
div
className=
"w-auto border border-
border
pl-1 pr-1.5 rounded-md flex justify-between items-center"
>
<
div
className=
"w-auto flex justify-start items-center mr-1"
>
<
CheckCircleIcon
className=
"w-4 h-auto mr-1"
/>
<
span
className=
"block text-sm"
>
{
t
(
"memo.to-do"
)
}
</
span
>
...
...
@@ -68,7 +68,7 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
</
div
>
)
}
{
property
.
hasCode
&&
(
<
div
className=
"w-auto border border-
zinc-200 dark:border-zinc-800
pl-1 pr-1.5 rounded-md flex justify-between items-center"
>
<
div
className=
"w-auto border border-
border
pl-1 pr-1.5 rounded-md flex justify-between items-center"
>
<
div
className=
"w-auto flex justify-start items-center mr-1"
>
<
Code2Icon
className=
"w-4 h-auto mr-1"
/>
<
span
className=
"block text-sm"
>
{
t
(
"memo.code"
)
}
</
span
>
...
...
@@ -80,7 +80,7 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
)
}
{
memo
.
tags
.
length
>
0
&&
(
<
div
className=
"w-full"
>
<
div
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
gray-400 dark:text-gray-500
select-none"
>
<
div
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-
muted-foreground
select-none"
>
<
span
>
{
t
(
"common.tags"
)
}
</
span
>
<
span
className=
"shrink-0"
>
(
{
memo
.
tags
.
length
}
)
</
span
>
</
div
>
...
...
@@ -88,11 +88,11 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
{
memo
.
tags
.
map
((
tag
)
=>
(
<
div
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
"
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-
muted-foreground
"
>
<
HashIcon
className=
"group-hover:hidden w-4 h-auto shrink-0 opacity-40"
/>
<
div
className=
{
cn
(
"inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]"
)
}
>
<
span
className=
"truncate
dark:
opacity-80"
>
{
tag
}
</
span
>
<
span
className=
"truncate opacity-80"
>
{
tag
}
</
span
>
</
div
>
</
div
>
))
}
...
...
web/src/components/MemoDetailSidebar/MemoDetailSidebarDrawer.tsx
View file @
91be2f68
...
...
@@ -23,10 +23,10 @@ const MemoDetailSidebarDrawer = ({ memo, parentPage }: Props) => {
<
Sheet
open=
{
open
}
onOpenChange=
{
setOpen
}
>
<
SheetTrigger
asChild
>
<
Button
variant=
"ghost"
className=
"bg-transparent! px-2"
>
<
GanttChartIcon
className=
"w-5 h-auto
dark:text-gray-400
"
/>
<
GanttChartIcon
className=
"w-5 h-auto
text-muted-foreground
"
/>
</
Button
>
</
SheetTrigger
>
<
SheetContent
side=
"right"
className=
"w-full sm:w-80 px-4 bg-
zinc-100 dark:bg-zinc-900
"
>
<
SheetContent
side=
"right"
className=
"w-full sm:w-80 px-4 bg-
secondary
"
>
<
MemoDetailSidebar
className=
"py-4"
memo=
{
memo
}
parentPage=
{
parentPage
}
/>
</
SheetContent
>
</
Sheet
>
...
...
web/src/components/MemoDisplaySettingMenu.tsx
View file @
91be2f68
...
...
@@ -16,15 +16,13 @@ const MemoDisplaySettingMenu = observer(({ className }: Props) => {
return
(
<
Popover
>
<
PopoverTrigger
className=
{
cn
(
className
,
isApplying
?
"text-teal-600 bg-teal-100 dark:text-teal-500 dark:bg-teal-900 rounded"
:
"opacity-40"
)
}
>
<
PopoverTrigger
className=
{
cn
(
className
,
isApplying
?
"text-primary bg-primary/10 rounded"
:
"opacity-40"
)
}
>
<
Settings2Icon
className=
"w-4 h-auto shrink-0"
/>
</
PopoverTrigger
>
<
PopoverContent
align=
"end"
alignOffset=
{
-
12
}
sideOffset=
{
14
}
>
<
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
>
<
span
className=
"text-sm shrink-0 mr-3
text-foreground
"
>
{
t
(
"memo.direction"
)
}
</
span
>
<
Select
value=
{
viewStore
.
state
.
orderByTimeAsc
.
toString
()
}
onValueChange=
{
(
value
)
=>
...
...
@@ -43,7 +41,7 @@ const MemoDisplaySettingMenu = observer(({ className }: Props) => {
</
Select
>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-sm shrink-0 mr-3
dark:text-zinc-400
"
>
{
t
(
"common.layout"
)
}
</
span
>
<
span
className=
"text-sm shrink-0 mr-3
text-foreground
"
>
{
t
(
"common.layout"
)
}
</
span
>
<
Select
value=
{
viewStore
.
state
.
layout
}
onValueChange=
{
(
value
)
=>
...
...
web/src/components/MemoEditor/ActionButton/AddMemoRelationPopover.tsx
View file @
91be2f68
...
...
@@ -144,11 +144,11 @@ const AddMemoRelationPopover = (props: Props) => {
{
selectedMemos
.
map
((
memo
)
=>
(
<
Badge
key=
{
memo
.
name
}
variant=
"outline"
className=
"max-w-full flex items-center gap-1 p-2"
>
<
div
className=
"flex-1 min-w-0"
>
<
p
className=
"text-xs text-
gray-400
select-none"
>
{
memo
.
displayTime
?.
toLocaleString
()
}
</
p
>
<
p
className=
"text-xs text-
muted-foreground
select-none"
>
{
memo
.
displayTime
?.
toLocaleString
()
}
</
p
>
<
span
className=
"text-sm leading-5 truncate block"
>
{
memo
.
content
}
</
span
>
</
div
>
<
X
className=
"w-3 h-3 cursor-pointer hover:text-
red-500
flex-shrink-0"
className=
"w-3 h-3 cursor-pointer hover:text-
destructive
flex-shrink-0"
onClick=
{
()
=>
setSelectedMemos
((
memos
)
=>
memos
.
filter
((
m
)
=>
m
.
name
!==
memo
.
name
))
}
/>
</
Badge
>
...
...
@@ -166,7 +166,7 @@ const AddMemoRelationPopover = (props: Props) => {
/>
<
div
className=
"max-h-[200px] overflow-y-auto"
>
{
filteredMemos
.
length
===
0
?
(
<
div
className=
"py-6 text-center text-sm text-
gray-500
"
>
{
isFetching
?
"Loading..."
:
t
(
"reference.no-memos-found"
)
}
</
div
>
<
div
className=
"py-6 text-center text-sm text-
muted-foreground
"
>
{
isFetching
?
"Loading..."
:
t
(
"reference.no-memos-found"
)
}
</
div
>
)
:
(
filteredMemos
.
map
((
memo
)
=>
(
<
div
...
...
@@ -177,7 +177,7 @@ const AddMemoRelationPopover = (props: Props) => {
}
}
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
p
className=
"text-xs text-
gray-400
select-none"
>
{
memo
.
displayTime
?.
toLocaleString
()
}
</
p
>
<
p
className=
"text-xs text-
muted-foreground
select-none"
>
{
memo
.
displayTime
?.
toLocaleString
()
}
</
p
>
<
p
className=
"mt-0.5 text-sm leading-5 line-clamp-2"
>
{
searchText
?
getHighlightedContent
(
memo
.
content
)
:
memo
.
snippet
}
</
p
>
...
...
web/src/components/MemoEditor/ActionButton/MarkdownMenu.tsx
View file @
91be2f68
...
...
@@ -70,21 +70,21 @@ const MarkdownMenu = (props: Props) => {
<
div
className=
"flex flex-col text-sm gap-0.5"
>
<
button
onClick=
{
handleCodeBlockClick
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-secondary
outline-none rounded"
>
<
Code2Icon
className=
"w-4 h-auto"
/>
<
span
>
{
t
(
"markdown.code-block"
)
}
</
span
>
</
button
>
<
button
onClick=
{
handleCheckboxClick
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-secondary
outline-none rounded"
>
<
CheckSquareIcon
className=
"w-4 h-auto"
/>
<
span
>
{
t
(
"markdown.checkbox"
)
}
</
span
>
</
button
>
<
div
className=
"pl-2"
>
<
a
className=
"text-xs text-
blue-600
hover:underline"
className=
"text-xs text-
primary
hover:underline"
href=
"https://www.usememos.com/docs/getting-started/content-syntax"
target=
"_blank"
rel=
"noopener noreferrer"
...
...
web/src/components/MemoEditor/ActionButton/TagSelector.tsx
View file @
91be2f68
...
...
@@ -46,7 +46,7 @@ const TagSelector = observer((props: Props) => {
return
(
<
div
key=
{
tag
}
className=
"inline-flex w-auto max-w-full cursor-pointer text-base leading-6 text-
gray-500 dark:text-gray-400
hover:opacity-80"
className=
"inline-flex w-auto max-w-full cursor-pointer text-base leading-6 text-
muted-foreground
hover:opacity-80"
onClick=
{
()
=>
handleTagClick
(
tag
)
}
>
<
OverflowTip
>
#
{
tag
}
</
OverflowTip
>
...
...
web/src/components/MemoEditor/ActionButton/VisibilitySelector.tsx
View file @
91be2f68
...
...
@@ -43,14 +43,14 @@ const VisibilitySelector = (props: Props) => {
<
PopoverTrigger
asChild
>
<
button
className=
{
cn
(
`flex items-center justify-center gap-1 px-0.5 text-xs rounded hover:bg-
gray-100 dark:hover:bg-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500
focus-visible:ring-offset-1 transition-colors`
,
`flex items-center justify-center gap-1 px-0.5 text-xs rounded hover:bg-
muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary
focus-visible:ring-offset-1 transition-colors`
,
props
.
className
,
)
}
type=
"button"
>
<
VisibilityIcon
className=
"w-3 h-3"
visibility=
{
value
}
/>
<
span
className=
"dark:text-zinc-300"
>
{
currentOption
?.
label
}
</
span
>
<
ChevronDownIcon
className=
"w-3 h-3 opacity-60
dark:text-zinc-300
"
/>
<
span
>
{
currentOption
?.
label
}
</
span
>
<
ChevronDownIcon
className=
"w-3 h-3 opacity-60"
/>
</
button
>
</
PopoverTrigger
>
<
PopoverContent
className=
"p-1!"
align=
"end"
sideOffset=
{
2
}
alignOffset=
{
-
4
}
>
...
...
@@ -60,8 +60,8 @@ const VisibilitySelector = (props: Props) => {
key=
{
option
.
value
}
onClick=
{
()
=>
handleSelect
(
option
.
value
)
}
className=
{
cn
(
`flex items-center gap-1 px-1 py-1 text-xs text-left
dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500
focus-visible:ring-offset-1 rounded transition-colors`
,
option
.
value
===
value
?
"bg-
gray-50 dark:bg-zinc-800
"
:
""
,
`flex items-center gap-1 px-1 py-1 text-xs text-left
hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary
focus-visible:ring-offset-1 rounded transition-colors`
,
option
.
value
===
value
?
"bg-
muted
"
:
""
,
)
}
>
<
VisibilityIcon
className=
"w-3 h-3"
visibility=
{
option
.
value
}
/>
...
...
web/src/components/MemoEditor/AttachmentListView.tsx
View file @
91be2f68
...
...
@@ -38,7 +38,7 @@ const AttachmentListView = (props: Props) => {
return
(
<
div
key=
{
attachment
.
name
}
className=
"max-w-full w-auto flex flex-row justify-start items-center flex-nowrap gap-x-1 bg-
zinc-100 dark:bg-zinc-900 px-2 py-1 rounded hover:shadow-sm text-gray-500 dark:text-gray-400
"
className=
"max-w-full w-auto flex flex-row justify-start items-center flex-nowrap gap-x-1 bg-
secondary px-2 py-1 rounded hover:shadow-sm text-muted-foreground
"
>
<
SortableItem
id=
{
attachment
.
name
}
className=
"flex flex-row justify-start items-center gap-x-1"
>
<
AttachmentIcon
attachment=
{
attachment
}
className=
"w-4! h-4! opacity-100!"
/>
...
...
web/src/components/MemoEditor/Editor/TagSuggestions.tsx
View file @
91be2f68
...
...
@@ -108,7 +108,7 @@ const TagSuggestions = observer(({ editorRef, editorActions }: Props) => {
if
(
!
isVisibleRef
.
current
||
!
position
)
return
null
;
return
(
<
div
className=
"z-20 p-1 mt-1 -ml-2 absolute max-w-48 gap-px rounded font-mono flex flex-col justify-start items-start overflow-auto shadow bg-
zinc-100 dark:bg-zinc-700
"
className=
"z-20 p-1 mt-1 -ml-2 absolute max-w-48 gap-px rounded font-mono flex flex-col justify-start items-start overflow-auto shadow bg-
popover
"
style=
{
{
left
:
position
.
left
,
top
:
position
.
top
+
position
.
height
}
}
>
{
suggestionsRef
.
current
.
map
((
tag
,
i
)
=>
(
...
...
@@ -116,8 +116,8 @@ const TagSuggestions = observer(({ editorRef, editorActions }: Props) => {
key=
{
tag
}
onMouseDown=
{
()
=>
autocomplete
(
tag
)
}
className=
{
cn
(
"rounded p-1 px-2 w-full truncate text-sm
dark:text-gray-300 cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-800
"
,
i
===
selected
?
"bg-
zinc-300 dark:bg-zinc-600
"
:
""
,
"rounded p-1 px-2 w-full truncate text-sm
cursor-pointer hover:bg-accent hover:text-accent-foreground
"
,
i
===
selected
?
"bg-
accent text-accent-foreground
"
:
""
,
)
}
>
<
OverflowTip
>
#
{
tag
}
</
OverflowTip
>
...
...
web/src/components/MemoEditor/Editor/index.tsx
View file @
91be2f68
...
...
@@ -214,7 +214,7 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
return
(
<
div
className=
{
cn
(
"flex flex-col justify-start items-start relative w-full h-auto max-h-[50vh] bg-inherit
dark:text-gray-300
"
,
className
)
}
className=
{
cn
(
"flex flex-col justify-start items-start relative w-full h-auto max-h-[50vh] bg-inherit"
,
className
)
}
>
<
textarea
className=
"w-full h-full my-1 text-base resize-none overflow-x-hidden overflow-y-auto bg-transparent outline-none placeholder:opacity-70 whitespace-pre-wrap break-words"
...
...
web/src/components/MemoEditor/RelationListView.tsx
View file @
91be2f68
...
...
@@ -37,7 +37,7 @@ const RelationListView = observer((props: Props) => {
return
(
<
div
key=
{
memo
.
name
}
className=
"w-auto max-w-xs overflow-hidden flex flex-row justify-start items-center bg-
zinc-100 dark:bg-zinc-900 hover:opacity-80 rounded-md text-sm p-1 px-2 text-gray-500 dark:text-gray-400
cursor-pointer hover:line-through"
className=
"w-auto max-w-xs overflow-hidden flex flex-row justify-start items-center bg-
secondary hover:opacity-80 rounded-md text-sm p-1 px-2 text-muted-foreground
cursor-pointer hover:line-through"
onClick=
{
()
=>
handleDeleteRelation
(
memo
)
}
>
<
LinkIcon
className=
"w-4 h-auto shrink-0 opacity-80"
/>
...
...
web/src/components/MemoEditor/index.tsx
View file @
91be2f68
...
...
@@ -484,10 +484,8 @@ const MemoEditor = observer((props: Props) => {
>
<
div
className=
{
cn
(
"group relative w-full flex flex-col justify-start items-start bg-white dark:bg-zinc-800 px-4 pt-3 pb-2 rounded-lg border"
,
state
.
isDraggingFile
?
"border-dashed border-gray-400 dark:border-primary-400 cursor-copy"
:
"border-gray-200 dark:border-zinc-700 cursor-auto"
,
"group relative w-full flex flex-col justify-start items-start bg-background px-4 pt-3 pb-2 rounded-lg border"
,
state
.
isDraggingFile
?
"border-dashed border-muted-foreground cursor-copy"
:
"border-border cursor-auto"
,
className
,
)
}
tabIndex=
{
0
}
...
...
@@ -503,7 +501,7 @@ const MemoEditor = observer((props: Props) => {
<
AttachmentListView
attachmentList=
{
state
.
attachmentList
}
setAttachmentList=
{
handleSetAttachmentList
}
/>
<
RelationListView
relationList=
{
referenceRelations
}
setRelationList=
{
handleSetRelationList
}
/>
<
div
className=
"relative w-full flex flex-row justify-between items-center py-1"
onFocus=
{
(
e
)
=>
e
.
stopPropagation
()
}
>
<
div
className=
"flex flex-row justify-start items-center opacity-80
dark:opacity-60
-space-x-2"
>
<
div
className=
"flex flex-row justify-start items-center opacity-80 -space-x-2"
>
<
TagSelector
editorRef=
{
editorRef
}
/>
<
MarkdownMenu
editorRef=
{
editorRef
}
/>
<
UploadAttachmentButton
isUploading=
{
state
.
isUploadingAttachment
}
/>
...
...
@@ -550,7 +548,7 @@ const MemoEditor = observer((props: Props) => {
{
/* Show memo metadata if memoName is provided */
}
{
memoName
&&
(
<
div
className=
"w-full -mt-1 mb-4 text-xs leading-5 px-4 opacity-60 font-mono text-
gray-500 dark:text-zinc-500
"
>
<
div
className=
"w-full -mt-1 mb-4 text-xs leading-5 px-4 opacity-60 font-mono text-
muted-foreground
"
>
<
div
className=
"grid grid-cols-[auto_1fr] gap-x-4 gap-y-0.5 items-center"
>
{
!
isEqual
(
createTime
,
updateTime
)
&&
updateTime
&&
(
<>
...
...
web/src/components/MemoFilters.tsx
View file @
91be2f68
...
...
@@ -49,12 +49,12 @@ const MemoFilters = observer(() => {
{
filters
.
map
((
filter
:
MemoFilter
)
=>
(
<
div
key=
{
getMemoFilterKey
(
filter
)
}
className=
"w-auto leading-7 h-7 shrink-0 flex flex-row items-center gap-1 bg-
white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700
pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
className=
"w-auto leading-7 h-7 shrink-0 flex flex-row items-center gap-1 bg-
background border
pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
onClick=
{
()
=>
memoFilterStore
.
removeFilter
((
f
:
MemoFilter
)
=>
isEqual
(
f
,
filter
))
}
>
<
FactorIcon
className=
"w-4 h-auto text-
gray-500 dark:text-gray-400
opacity-60"
factor=
{
filter
.
factor
}
/>
<
span
className=
"text-
gray-500 dark:text-gray-400
text-sm max-w-32 truncate"
>
{
getFilterDisplayText
(
filter
)
}
</
span
>
<
button
className=
"text-
gray-500 dark:text-gray-300
opacity-60 hover:opacity-100"
>
<
FactorIcon
className=
"w-4 h-auto text-
muted-foreground
opacity-60"
factor=
{
filter
.
factor
}
/>
<
span
className=
"text-
muted-foreground
text-sm max-w-32 truncate"
>
{
getFilterDisplayText
(
filter
)
}
</
span
>
<
button
className=
"text-
muted-foreground
opacity-60 hover:opacity-100"
>
<
XIcon
className=
"w-4 h-auto"
/>
</
button
>
</
div
>
...
...
web/src/components/MemoLocationView.tsx
View file @
91be2f68
...
...
@@ -16,7 +16,7 @@ const MemoLocationView: React.FC<Props> = (props: Props) => {
return
(
<
Popover
open=
{
popoverOpen
}
onOpenChange=
{
setPopoverOpen
}
>
<
PopoverTrigger
asChild
>
<
p
className=
"w-full flex flex-row gap-0.5 items-center text-
gray-500
"
>
<
p
className=
"w-full flex flex-row gap-0.5 items-center text-
muted-foreground
"
>
<
MapPinIcon
className=
"w-4 h-auto shrink-0"
/>
<
span
className=
"text-sm font-normal text-ellipsis whitespace-nowrap overflow-hidden"
>
{
location
.
placeholder
?
location
.
placeholder
:
`[${location.latitude}, ${location.longitude}]`
}
...
...
web/src/components/MemoRelationForceGraph/MemoRelationForceGraph.tsx
View file @
91be2f68
...
...
@@ -57,7 +57,7 @@ const MemoRelationForceGraph = ({ className, memo, parentPage }: Props) => {
};
return
(
<
div
ref=
{
containerRef
}
className=
{
cn
(
"
dark:
opacity-80"
,
className
)
}
>
<
div
ref=
{
containerRef
}
className=
{
cn
(
"opacity-80"
,
className
)
}
>
<
ForceGraph2D
ref=
{
graphRef
}
width=
{
graphSize
.
width
}
...
...
web/src/components/MemoRelationListView.tsx
View file @
91be2f68
...
...
@@ -30,13 +30,13 @@ const MemoRelationListView = (props: Props) => {
}
return
(
<
div
className=
"relative flex flex-col justify-start items-start w-full px-2 pt-2 pb-1.5 bg-
zinc-50 dark:bg-zinc-900 rounded-lg border border-zinc-200 dark:border-zinc-700
"
>
<
div
className=
"relative flex flex-col justify-start items-start w-full px-2 pt-2 pb-1.5 bg-
secondary rounded-lg border border-border
"
>
<
div
className=
"w-full flex flex-row justify-start items-center mb-1 gap-3 opacity-60"
>
{
referencingMemoList
.
length
>
0
&&
(
<
button
className=
{
cn
(
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-
gray-500
"
,
selectedTab
===
"referencing"
&&
"text-
gray-800 dark:text-gray-400
"
,
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-
muted-foreground
"
,
selectedTab
===
"referencing"
&&
"text-
foreground
"
,
)
}
onClick=
{
()
=>
setSelectedTab
(
"referencing"
)
}
>
...
...
@@ -48,8 +48,8 @@ const MemoRelationListView = (props: Props) => {
{
referencedMemoList
.
length
>
0
&&
(
<
button
className=
{
cn
(
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-
gray-500
"
,
selectedTab
===
"referenced"
&&
"text-
gray-800 dark:text-gray-400
"
,
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-
muted-foreground
"
,
selectedTab
===
"referenced"
&&
"text-
foreground
"
,
)
}
onClick=
{
()
=>
setSelectedTab
(
"referenced"
)
}
>
...
...
@@ -65,14 +65,14 @@ const MemoRelationListView = (props: Props) => {
return
(
<
Link
key=
{
memo
.
name
}
className=
"w-auto max-w-full flex flex-row justify-start items-center text-sm leading-5 text-
gray-600 dark:text-gray-400 dark:border-zinc-700 dark:bg-zinc-900
hover:underline"
className=
"w-auto max-w-full flex flex-row justify-start items-center text-sm leading-5 text-
muted-foreground
hover:underline"
to=
{
`/${memo.name}`
}
viewTransition
state=
{
{
from
:
parentPage
,
}
}
>
<
span
className=
"text-xs opacity-60 leading-4 border border-
zinc-200 font-mono px-1 rounded-full mr-1 dark:border-zinc-700
"
>
<
span
className=
"text-xs opacity-60 leading-4 border border-
border font-mono px-1 rounded-full mr-1
"
>
{
extractMemoIdFromName
(
memo
.
name
).
slice
(
0
,
6
)
}
</
span
>
<
span
className=
"truncate"
>
{
memo
.
snippet
}
</
span
>
...
...
@@ -87,14 +87,14 @@ const MemoRelationListView = (props: Props) => {
return
(
<
Link
key=
{
memo
.
name
}
className=
"w-auto max-w-full flex flex-row justify-start items-center text-sm leading-5 text-
gray-600 dark:text-gray-400 dark:border-zinc-700 dark:bg-zinc-900
hover:underline"
className=
"w-auto max-w-full flex flex-row justify-start items-center text-sm leading-5 text-
muted-foreground
hover:underline"
to=
{
`/${memo.name}`
}
viewTransition
state=
{
{
from
:
parentPage
,
}
}
>
<
span
className=
"text-xs opacity-60 leading-4 border border-
zinc-200 font-mono px-1 rounded-full mr-1 dark:border-zinc-700
"
>
<
span
className=
"text-xs opacity-60 leading-4 border border-
border font-mono px-1 rounded-full mr-1
"
>
{
extractMemoIdFromName
(
memo
.
name
).
slice
(
0
,
6
)
}
</
span
>
<
span
className=
"truncate"
>
{
memo
.
snippet
}
</
span
>
...
...
web/src/components/MemoView.tsx
View file @
91be2f68
...
...
@@ -131,7 +131,7 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
)
:
(
<
div
className=
{
cn
(
"group relative flex flex-col justify-start items-start w-full px-4 py-3 mb-2 gap-2 bg-
white dark:bg-zinc-800 rounded-lg border border-white dark:border-zinc-800 hover:border-gray-200 dark:hover:border-zinc-700
"
,
"group relative flex flex-col justify-start items-start w-full px-4 py-3 mb-2 gap-2 bg-
card rounded-lg border border-card hover:border-border
"
,
className
,
)
}
>
...
...
@@ -144,14 +144,14 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
</
Link
>
<
div
className=
"w-full flex flex-col justify-center items-start"
>
<
Link
className=
"w-full block leading-tight hover:opacity-80 truncate text-
gray-600 dark:text-gray-400
"
className=
"w-full block leading-tight hover:opacity-80 truncate text-
muted-foreground
"
to=
{
`/u/${encodeURIComponent(creator.username)}`
}
viewTransition
>
{
creator
.
displayName
||
creator
.
username
}
</
Link
>
<
div
className=
"w-auto -mt-0.5 text-xs leading-tight text-
gray-400 dark:text-gray-500
select-none cursor-pointer"
className=
"w-auto -mt-0.5 text-xs leading-tight text-
muted-foreground
select-none cursor-pointer"
onClick=
{
handleGotoMemoDetailPage
}
>
{
displayTime
}
...
...
@@ -160,7 +160,7 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
</
div
>
)
:
(
<
div
className=
"w-full text-sm leading-tight text-
gray-400 dark:text-gray-500
select-none cursor-pointer"
className=
"w-full text-sm leading-tight text-
muted-foreground
select-none cursor-pointer"
onClick=
{
handleGotoMemoDetailPage
}
>
{
displayTime
}
...
...
@@ -193,8 +193,8 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
from
:
parentPage
,
}
}
>
<
MessageCircleMoreIcon
className=
"w-4 h-4 mx-auto text-
gray-500 dark:text-gray-400
"
/>
{
commentAmount
>
0
&&
<
span
className=
"text-xs text-
gray-500 dark:text-gray-400
"
>
{
commentAmount
}
</
span
>
}
<
MessageCircleMoreIcon
className=
"w-4 h-4 mx-auto text-
muted-foreground
"
/>
{
commentAmount
>
0
&&
<
span
className=
"text-xs text-
muted-foreground
"
>
{
commentAmount
}
</
span
>
}
</
Link
>
)
}
{
props
.
showPinned
&&
memo
.
pinned
&&
(
...
...
@@ -202,7 +202,7 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
<
Tooltip
>
<
TooltipTrigger
asChild
>
<
span
className=
"cursor-pointer"
>
<
BookmarkIcon
className=
"w-4 h-auto text-
amber-500
"
onClick=
{
onPinIconClick
}
/>
<
BookmarkIcon
className=
"w-4 h-auto text-
primary
"
onClick=
{
onPinIconClick
}
/>
</
span
>
</
TooltipTrigger
>
<
TooltipContent
>
...
...
@@ -213,7 +213,7 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
)
}
{
nsfw
&&
showNSFWContent
&&
(
<
span
className=
"cursor-pointer"
>
<
EyeOffIcon
className=
"w-4 h-auto text-
amber-500
"
onClick=
{
()
=>
setShowNSFWContent
(
false
)
}
/>
<
EyeOffIcon
className=
"w-4 h-auto text-
primary
"
onClick=
{
()
=>
setShowNSFWContent
(
false
)
}
/>
</
span
>
)
}
<
MemoActionMenu
className=
"-ml-1"
memo=
{
memo
}
readonly=
{
readonly
}
onEdit=
{
()
=>
setShowEditor
(
true
)
}
/>
...
...
@@ -244,7 +244,7 @@ const MemoView: React.FC<Props> = observer((props: Props) => {
<>
<
div
className=
"absolute inset-0 bg-transparent"
/>
<
button
className=
"absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 py-2 px-4 text-sm text-
gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-zinc-800
"
className=
"absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 py-2 px-4 text-sm text-
muted-foreground hover:text-foreground border border-border rounded-lg bg-card
"
onClick=
{
()
=>
setShowNSFWContent
(
true
)
}
>
{
t
(
"memo.click-to-show-nsfw-content"
)
}
...
...
web/src/components/MobileHeader.tsx
View file @
91be2f68
...
...
@@ -16,7 +16,7 @@ const MobileHeader = (props: Props) => {
return
(
<
div
className=
{
cn
(
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-
zinc-50 dark:bg-zinc-900
bg-opacity-80 backdrop-blur-lg flex md:hidden flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1"
,
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-
background
bg-opacity-80 backdrop-blur-lg flex md:hidden flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1"
,
offsetTop
>
0
&&
"shadow-md"
,
className
,
)
}
...
...
web/src/components/Navigation.tsx
View file @
91be2f68
...
...
@@ -78,9 +78,9 @@ const Navigation = observer((props: Props) => {
<
NavLink
className=
{
({
isActive
})
=>
cn
(
"px-2 py-2 rounded-2xl border flex flex-row items-center text-lg text-
gray-800 dark:text-gray-400 hover:bg-white hover:border-zinc-200 dark:hover:border-zinc-700 dark:hover:bg-zinc-800
"
,
"px-2 py-2 rounded-2xl border flex flex-row items-center text-lg text-
foreground hover:bg-secondary hover:border-border
"
,
collapsed
?
""
:
"w-full px-4"
,
isActive
?
"bg-
white drop-shadow-sm dark:bg-zinc-900 border-zinc-200 dark:border-zinc-700
"
:
"border-transparent"
,
isActive
?
"bg-
secondary drop-shadow-sm border-border
"
:
"border-transparent"
,
)
}
key=
{
navLink
.
id
}
...
...
web/src/components/NavigationDrawer.tsx
View file @
91be2f68
...
...
@@ -23,12 +23,12 @@ const NavigationDrawer = observer(() => {
<
SheetTrigger
asChild
>
<
Button
variant=
"ghost"
className=
"px-2"
>
<
UserAvatar
className=
"shrink-0 w-6 h-6 rounded-md"
avatarUrl=
{
avatarUrl
}
/>
<
span
className=
"font-bold text-lg leading-10 ml-2 text-ellipsis shrink-0 cursor-pointer overflow-hidden text-
gray-700 dark:text-gray-300
"
>
<
span
className=
"font-bold text-lg leading-10 ml-2 text-ellipsis shrink-0 cursor-pointer overflow-hidden text-
foreground
"
>
{
title
}
</
span
>
</
Button
>
</
SheetTrigger
>
<
SheetContent
side=
"left"
className=
"w-full sm:w-80 overflow-auto px-2 bg-
zinc-100 dark:bg-zinc-900
"
>
<
SheetContent
side=
"left"
className=
"w-full sm:w-80 overflow-auto px-2 bg-
secondary
"
>
<
Navigation
/>
</
SheetContent
>
</
Sheet
>
...
...
web/src/components/PagedMemoList/PagedMemoList.tsx
View file @
91be2f68
...
...
@@ -148,7 +148,7 @@ const PagedMemoList = observer((props: Props) => {
{
/* Loading indicator */
}
{
isRequesting
&&
(
<
div
className=
"w-full flex flex-row justify-center items-center my-4"
>
<
LoaderIcon
className=
"animate-spin text-
zinc-500
"
/>
<
LoaderIcon
className=
"animate-spin text-
muted-foreground
"
/>
</
div
>
)
}
...
...
@@ -158,7 +158,7 @@ const PagedMemoList = observer((props: Props) => {
{
!
nextPageToken
&&
sortedMemoList
.
length
===
0
?
(
<
div
className=
"w-full mt-12 mb-8 flex flex-col justify-center items-center italic"
>
<
Empty
/>
<
p
className=
"mt-2 text-
gray-600 dark:text-gray-400
"
>
{
t
(
"message.no-data"
)
}
</
p
>
<
p
className=
"mt-2 text-
muted-foreground
"
>
{
t
(
"message.no-data"
)
}
</
p
>
</
div
>
)
:
(
<
div
className=
"w-full opacity-70 flex flex-row justify-center items-center my-4"
>
...
...
web/src/components/PasswordSignInForm.tsx
View file @
91be2f68
...
...
@@ -61,9 +61,9 @@ const PasswordSignInForm = observer(() => {
<
form
className=
"w-full mt-2"
onSubmit=
{
handleFormSubmit
}
>
<
div
className=
"flex flex-col justify-start items-start w-full gap-4"
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
span
className=
"leading-8 text-
gray-600
"
>
{
t
(
"common.username"
)
}
</
span
>
<
span
className=
"leading-8 text-
muted-foreground
"
>
{
t
(
"common.username"
)
}
</
span
>
<
Input
className=
"w-full bg-
white dark:bg-black
h-10"
className=
"w-full bg-
background
h-10"
type=
"text"
readOnly=
{
actionBtnLoadingState
.
isLoading
}
placeholder=
{
t
(
"common.username"
)
}
...
...
@@ -76,9 +76,9 @@ const PasswordSignInForm = observer(() => {
/>
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
span
className=
"leading-8 text-
gray-600
"
>
{
t
(
"common.password"
)
}
</
span
>
<
span
className=
"leading-8 text-
muted-foreground
"
>
{
t
(
"common.password"
)
}
</
span
>
<
Input
className=
"w-full bg-
white dark:bg-black
h-10"
className=
"w-full bg-
background
h-10"
type=
"password"
readOnly=
{
actionBtnLoadingState
.
isLoading
}
placeholder=
{
t
(
"common.password"
)
}
...
...
web/src/components/ReactionSelector.tsx
View file @
91be2f68
...
...
@@ -59,11 +59,11 @@ const ReactionSelector = observer((props: Props) => {
<
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 cursor-pointer"
,
"h-7 w-7 flex justify-center items-center rounded-full border hover:opacity-70 cursor-pointer"
,
className
,
)
}
>
<
SmilePlusIcon
className=
"w-4 h-4 mx-auto text-
gray-500 dark:text-gray-400
"
/>
<
SmilePlusIcon
className=
"w-4 h-4 mx-auto text-
muted-foreground
"
/>
</
span
>
</
PopoverTrigger
>
<
PopoverContent
align=
"start"
sideOffset=
{
2
}
>
...
...
@@ -74,8 +74,8 @@ const ReactionSelector = observer((props: Props) => {
<
span
key=
{
reactionType
}
className=
{
cn
(
"inline-flex w-auto text-base cursor-pointer rounded px-1 text-
gray-500 dark:text-gray-400
hover:opacity-80"
,
hasReacted
(
reactionType
)
&&
"bg-
blue-100 dark:bg-zinc-80
0"
,
"inline-flex w-auto text-base cursor-pointer rounded px-1 text-
muted-foreground
hover:opacity-80"
,
hasReacted
(
reactionType
)
&&
"bg-
primary/1
0"
,
)
}
onClick=
{
()
=>
handleReactionClick
(
reactionType
)
}
>
...
...
web/src/components/ReactionView.tsx
View file @
91be2f68
...
...
@@ -70,10 +70,10 @@ const ReactionView = observer((props: Props) => {
<
TooltipTrigger
asChild
>
<
div
className=
{
cn
(
"h-7 border
border-zinc-200 px-2 py-0.5 rounded-full flex flex-row justify-center items-center gap-1 dark:border-zinc-700
"
,
"text-sm text-
gray-600 dark:text-gray-400
"
,
"h-7 border
px-2 py-0.5 rounded-full flex flex-row justify-center items-center gap-1
"
,
"text-sm text-
muted-foreground
"
,
currentUser
&&
!
readonly
&&
"cursor-pointer"
,
hasReaction
&&
"bg-
blue-100 border-blue-200 dark:bg-zinc-900
"
,
hasReaction
&&
"bg-
primary/10 border-primary
"
,
)
}
onClick=
{
handleReactionClick
}
>
...
...
web/src/components/RenameTagDialog.tsx
View file @
91be2f68
...
...
@@ -47,7 +47,7 @@ const RenameTagDialog: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
className=
"title-text"
>
{
t
(
"tag.rename-tag"
)
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
()
=>
destroy
()
}
>
...
...
web/src/components/RequiredBadge.tsx
View file @
91be2f68
...
...
@@ -5,7 +5,7 @@ interface Props {
const
RequiredBadge
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
className
}
=
props
;
return
<
span
className=
{
`mx-0.5 text-
red-500
font-bold ${className ?? ""}`
}
>
*
</
span
>;
return
<
span
className=
{
`mx-0.5 text-
destructive
font-bold ${className ?? ""}`
}
>
*
</
span
>;
};
export
default
RequiredBadge
;
web/src/components/SearchBar.tsx
View file @
91be2f68
...
...
@@ -33,17 +33,15 @@ const SearchBar = observer(() => {
return
(
<
div
className=
"relative w-full h-auto flex flex-row justify-start items-center"
>
<
SearchIcon
className=
"absolute left-2 w-4 h-auto opacity-40
dark:text-zinc-300
"
/>
<
SearchIcon
className=
"absolute left-2 w-4 h-auto opacity-40
text-muted-foreground
"
/>
<
input
className=
{
cn
(
"w-full text-gray-500 leading-6 dark:text-zinc-300 bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 text-sm rounded-xl p-1 pl-8 outline-0"
,
)
}
className=
{
cn
(
"w-full text-muted-foreground leading-6 bg-secondary border border-border text-sm rounded-xl p-1 pl-8 outline-0"
)
}
placeholder=
{
t
(
"memo.search-placeholder"
)
}
value=
{
queryText
}
onChange=
{
onTextChange
}
onKeyDown=
{
onKeyDown
}
/>
<
MemoDisplaySettingMenu
className=
"absolute right-2 top-2
dark:text-zinc-300
"
/>
<
MemoDisplaySettingMenu
className=
"absolute right-2 top-2
text-muted-foreground
"
/>
</
div
>
);
});
...
...
web/src/components/Settings/AccessTokenSection.tsx
View file @
91be2f68
...
...
@@ -54,11 +54,11 @@ const AccessTokenSection = () => {
<
div
className=
"w-full"
>
<
div
className=
"sm:flex sm:items-center sm:justify-between"
>
<
div
className=
"sm:flex-auto space-y-1"
>
<
p
className=
"flex flex-row justify-start items-center font-medium text-
gray-700 dark:text-gray-400
"
>
<
p
className=
"flex flex-row justify-start items-center font-medium text-
muted-foreground
"
>
{
t
(
"setting.access-token-section.title"
)
}
<
LearnMore
className=
"ml-2"
url=
"https://usememos.com/docs/security/access-tokens"
/>
</
p
>
<
p
className=
"text-sm text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.access-token-section.description"
)
}
</
p
>
<
p
className=
"text-sm text-
muted-foreground
"
>
{
t
(
"setting.access-token-section.description"
)
}
</
p
>
</
div
>
<
div
className=
"mt-4 sm:mt-0"
>
<
Button
...
...
@@ -73,20 +73,20 @@ const AccessTokenSection = () => {
</
div
>
<
div
className=
"w-full mt-2 flow-root"
>
<
div
className=
"overflow-x-auto"
>
<
div
className=
"inline-block min-w-full border border-
zinc-200 rounded-lg align-middle dark:border-zinc-600
"
>
<
table
className=
"min-w-full divide-y divide-
gray-300 dark:divide-zinc-600
"
>
<
div
className=
"inline-block min-w-full border border-
border rounded-lg align-middle
"
>
<
table
className=
"min-w-full divide-y divide-
border
"
>
<
thead
>
<
tr
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"setting.access-token-section.token"
)
}
</
th
>
<
th
scope=
"col"
className=
"py-2 pl-4 pr-3 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"py-2 pl-4 pr-3 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"common.description"
)
}
</
th
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"setting.access-token-section.create-dialog.created-at"
)
}
</
th
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"setting.access-token-section.create-dialog.expires-at"
)
}
</
th
>
<
th
scope=
"col"
className=
"relative py-3.5 pl-3 pr-4"
>
...
...
@@ -94,22 +94,22 @@ const AccessTokenSection = () => {
</
th
>
</
tr
>
</
thead
>
<
tbody
className=
"divide-y divide-
gray-200 dark:divide-zinc-700
"
>
<
tbody
className=
"divide-y divide-
border
"
>
{
userAccessTokens
.
map
((
userAccessToken
)
=>
(
<
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"
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
foreground
flex flex-row justify-start items-center gap-x-1"
>
<
span
className=
"font-mono"
>
{
getFormatedAccessToken
(
userAccessToken
.
accessToken
)
}
</
span
>
<
Button
variant=
"ghost"
onClick=
{
()
=>
copyAccessToken
(
userAccessToken
.
accessToken
)
}
>
<
ClipboardIcon
className=
"w-4 h-auto text-
gray-400
"
/>
<
ClipboardIcon
className=
"w-4 h-auto text-
muted-foreground
"
/>
</
Button
>
</
td
>
<
td
className=
"whitespace-nowrap py-2 pl-4 pr-3 text-sm text-
gray-900 dark:text-gray-400
"
>
<
td
className=
"whitespace-nowrap py-2 pl-4 pr-3 text-sm text-
foreground
"
>
{
userAccessToken
.
description
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
{
userAccessToken
.
issuedAt
?.
toLocaleString
()
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
{
userAccessToken
.
expiresAt
?.
toLocaleString
()
??
t
(
"setting.access-token-section.create-dialog.duration-never"
)
}
</
td
>
<
td
className=
"relative whitespace-nowrap py-2 pl-3 pr-4 text-right text-sm"
>
...
...
@@ -119,7 +119,7 @@ const AccessTokenSection = () => {
handleDeleteAccessToken
(
userAccessToken
);
}
}
>
<
TrashIcon
className=
"text-
red-600
w-4 h-auto"
/>
<
TrashIcon
className=
"text-
destructive
w-4 h-auto"
/>
</
Button
>
</
td
>
</
tr
>
...
...
web/src/components/Settings/MemberSection.tsx
View file @
91be2f68
...
...
@@ -145,8 +145,8 @@ const MemberSection = observer(() => {
return
(
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.member-section.create-a-member"
)
}
</
p
>
<
div
className=
"w-auto flex flex-col justify-start items-start gap-2 border border-
zinc-200 rounded-md py-2 px-3 dark:border-zinc-700
"
>
<
p
className=
"font-medium text-
muted-foreground
"
>
{
t
(
"setting.member-section.create-a-member"
)
}
</
p
>
<
div
className=
"w-auto flex flex-col justify-start items-start gap-2 border border-
border rounded-md py-2 px-3
"
>
<
div
className=
"flex flex-col justify-start items-start gap-1"
>
<
span
>
{
t
(
"common.username"
)
}
</
span
>
<
Input
...
...
@@ -192,10 +192,10 @@ const MemberSection = observer(() => {
<
div
className=
"title-text"
>
{
t
(
"setting.member-list"
)
}
</
div
>
</
div
>
<
div
className=
"w-full overflow-x-auto"
>
<
div
className=
"inline-block min-w-full align-middle border border-
zinc-200 rounded-lg dark:border-zinc-600
"
>
<
table
className=
"min-w-full divide-y divide-
gray-300 dark:divide-zinc-600
"
>
<
div
className=
"inline-block min-w-full align-middle border border-
border rounded-lg
"
>
<
table
className=
"min-w-full divide-y divide-
border
"
>
<
thead
>
<
tr
className=
"text-sm font-semibold text-left text-
gray-900 dark:text-gray-400
"
>
<
tr
className=
"text-sm font-semibold text-left text-
foreground
"
>
<
th
scope=
"col"
className=
"px-3 py-2"
>
{
t
(
"common.username"
)
}
</
th
>
...
...
@@ -211,23 +211,23 @@ const MemberSection = observer(() => {
<
th
scope=
"col"
className=
"relative py-2 pl-3 pr-4"
></
th
>
</
tr
>
</
thead
>
<
tbody
className=
"divide-y divide-
gray-200 dark:divide-zinc-600
"
>
<
tbody
className=
"divide-y divide-
border
"
>
{
sortedUsers
.
map
((
user
)
=>
(
<
tr
key=
{
user
.
name
}
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
{
user
.
username
}
<
span
className=
"ml-1 italic"
>
{
user
.
state
===
State
.
ARCHIVED
&&
"(Archived)"
}
</
span
>
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
{
stringifyUserRole
(
user
.
role
)
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
{
user
.
displayName
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
{
user
.
email
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
{
stringifyUserRole
(
user
.
role
)
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
{
user
.
displayName
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
{
user
.
email
}
</
td
>
<
td
className=
"relative whitespace-nowrap py-2 pl-3 pr-4 text-right text-sm font-medium flex justify-end"
>
{
currentUser
?.
name
===
user
.
name
?
(
<
span
>
{
t
(
"common.yourself"
)
}
</
span
>
)
:
(
<
Popover
>
<
PopoverTrigger
asChild
>
<
button
className=
"flex items-center justify-center p-1 hover:bg-
gray-100 dark:hover:bg-zinc-700
rounded"
>
<
button
className=
"flex items-center justify-center p-1 hover:bg-
muted
rounded"
>
<
MoreVerticalIcon
className=
"w-4 h-auto"
/>
</
button
>
</
PopoverTrigger
>
...
...
@@ -235,14 +235,14 @@ const MemberSection = observer(() => {
<
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 text-left
dark:text-zinc-300 hover:bg-gray-100 dark:hover:bg-zinc-700
outline-none rounded"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
{
t
(
"common.update"
)
}
</
button
>
{
user
.
state
===
State
.
NORMAL
?
(
<
button
onClick=
{
()
=>
handleArchiveUserClick
(
user
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
{
t
(
"setting.member-section.archive-member"
)
}
</
button
>
...
...
@@ -250,13 +250,13 @@ const MemberSection = observer(() => {
<>
<
button
onClick=
{
()
=>
handleRestoreUserClick
(
user
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
hover:bg-muted
outline-none rounded"
>
{
t
(
"common.restore"
)
}
</
button
>
<
button
onClick=
{
()
=>
handleDeleteUserClick
(
user
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
destructive hover:bg-muted
outline-none rounded"
>
{
t
(
"setting.member-section.delete-member"
)
}
</
button
>
...
...
web/src/components/Settings/MemoRelatedSettings.tsx
View file @
91be2f68
...
...
@@ -67,7 +67,7 @@ const MemoRelatedSettings = observer(() => {
return
(
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.memo-related-settings.title"
)
}
</
p
>
<
p
className=
"font-medium text-
muted-foreground
"
>
{
t
(
"setting.memo-related-settings.title"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
>
{
t
(
"setting.system-section.disable-public-memos"
)
}
</
span
>
<
Switch
...
...
@@ -127,7 +127,7 @@ const MemoRelatedSettings = observer(() => {
<
Badge
key=
{
reactionType
}
variant=
"outline"
className=
"h-8 flex items-center gap-1"
>
{
reactionType
}
<
X
className=
"w-3 h-3 cursor-pointer hover:text-
red-500
"
className=
"w-3 h-3 cursor-pointer hover:text-
destructive
"
onClick=
{
()
=>
updatePartialSetting
({
reactions
:
memoRelatedSetting
.
reactions
.
filter
((
r
)
=>
r
!==
reactionType
)
})
}
/>
</
Badge
>
...
...
@@ -141,7 +141,7 @@ const MemoRelatedSettings = observer(() => {
onChange=
{
(
event
)
=>
setEditingReaction
(
event
.
target
.
value
.
trim
())
}
/>
<
CheckIcon
className=
"w-5 h-5 text-
gray-500 dark:text-gray-400 cursor-pointer hover:text-teal-600
"
className=
"w-5 h-5 text-
muted-foreground cursor-pointer hover:text-primary
"
onClick=
{
()
=>
upsertReaction
()
}
/>
</
div
>
...
...
@@ -161,7 +161,7 @@ const MemoRelatedSettings = observer(() => {
<
Badge
key=
{
nsfwTag
}
variant=
"outline"
className=
"h-8 flex items-center gap-1"
>
{
nsfwTag
}
<
X
className=
"w-3 h-3 cursor-pointer hover:text-
red-500
"
className=
"w-3 h-3 cursor-pointer hover:text-
destructive
"
onClick=
{
()
=>
updatePartialSetting
({
nsfwTags
:
memoRelatedSetting
.
nsfwTags
.
filter
((
r
)
=>
r
!==
nsfwTag
)
})
}
/>
</
Badge
>
...
...
@@ -175,7 +175,7 @@ const MemoRelatedSettings = observer(() => {
onChange=
{
(
event
)
=>
setEditingNsfwTag
(
event
.
target
.
value
.
trim
())
}
/>
<
CheckIcon
className=
"w-5 h-5 text-
gray-500 dark:text-gray-400 cursor-pointer hover:text-teal-600
"
className=
"w-5 h-5 text-
muted-foreground cursor-pointer hover:text-primary
"
onClick=
{
()
=>
upsertNsfwTags
()
}
/>
</
div
>
...
...
web/src/components/Settings/MyAccountSection.tsx
View file @
91be2f68
...
...
@@ -15,13 +15,13 @@ const MyAccountSection = () => {
return
(
<
div
className=
"w-full gap-2 pt-2 pb-4"
>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.account-section.title"
)
}
</
p
>
<
p
className=
"font-medium text-
muted-foreground
"
>
{
t
(
"setting.account-section.title"
)
}
</
p
>
<
div
className=
"w-full mt-2 flex flex-row justify-start items-center"
>
<
UserAvatar
className=
"mr-2 shrink-0 w-10 h-10"
avatarUrl=
{
user
.
avatarUrl
}
/>
<
div
className=
"max-w-[calc(100%-3rem)] flex flex-col justify-center items-start"
>
<
p
className=
"w-full"
>
<
span
className=
"text-xl leading-tight font-medium"
>
{
user
.
displayName
}
</
span
>
<
span
className=
"ml-1 text-base leading-tight text-
gray-500 dark:text-gray-400
"
>
(
{
user
.
username
}
)
</
span
>
<
span
className=
"ml-1 text-base leading-tight text-
muted-foreground
"
>
(
{
user
.
username
}
)
</
span
>
</
p
>
<
p
className=
"w-4/5 leading-tight text-sm truncate"
>
{
user
.
description
}
</
p
>
</
div
>
...
...
@@ -40,7 +40,7 @@ const MyAccountSection = () => {
<
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"
className=
"w-full flex items-center gap-2 px-2 py-1 text-left text-sm hover:bg-
muted
rounded-md"
>
{
t
(
"setting.account-section.change-password"
)
}
</
button
>
...
...
web/src/components/Settings/PreferencesSection.tsx
View file @
91be2f68
...
...
@@ -29,7 +29,7 @@ const PreferencesSection = observer(() => {
return
(
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"common.basic"
)
}
</
p
>
<
p
className=
"font-medium text-
muted-foreground
"
>
{
t
(
"common.basic"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
>
{
t
(
"common.language"
)
}
</
span
>
...
...
@@ -41,7 +41,7 @@ const PreferencesSection = observer(() => {
<
AppearanceSelect
value=
{
setting
.
appearance
as
Appearance
}
onChange=
{
handleAppearanceSelectChange
}
/>
</
div
>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.preference"
)
}
</
p
>
<
p
className=
"font-medium text-
muted-foreground
"
>
{
t
(
"setting.preference"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"truncate"
>
{
t
(
"setting.preference-section.default-memo-visibility"
)
}
</
span
>
...
...
web/src/components/Settings/SSOSection.tsx
View file @
91be2f68
...
...
@@ -41,7 +41,7 @@ const SSOSection = () => {
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
div
className=
"w-full flex flex-row justify-between items-center gap-1"
>
<
div
className=
"flex flex-row items-center gap-1"
>
<
span
className=
"font-mono text-
gray-400
"
>
{
t
(
"setting.sso-section.sso-list"
)
}
</
span
>
<
span
className=
"font-mono text-
muted-foreground
"
>
{
t
(
"setting.sso-section.sso-list"
)
}
</
span
>
<
LearnMore
url=
"https://www.usememos.com/docs/advanced-settings/sso"
/>
</
div
>
<
Button
color=
"primary"
onClick=
{
()
=>
showCreateIdentityProviderDialog
(
undefined
,
fetchIdentityProviderList
)
}
>
...
...
@@ -52,7 +52,7 @@ const SSOSection = () => {
{
identityProviderList
.
map
((
identityProvider
)
=>
(
<
div
key=
{
identityProvider
.
name
}
className=
"py-2 w-full border-b last:border-b
dark:border-zinc-700
flex flex-row items-center justify-between"
className=
"py-2 w-full border-b last:border-b
border-border
flex flex-row items-center justify-between"
>
<
div
className=
"flex flex-row items-center"
>
<
p
className=
"ml-2"
>
...
...
@@ -63,7 +63,7 @@ const SSOSection = () => {
<
div
className=
"flex flex-row items-center"
>
<
Popover
>
<
PopoverTrigger
asChild
>
<
button
className=
"flex items-center justify-center p-1 hover:bg-
gray-100 dark:hover:bg-zinc-700
rounded"
>
<
button
className=
"flex items-center justify-center p-1 hover:bg-
secondary
rounded"
>
<
MoreVerticalIcon
className=
"w-4 h-auto"
/>
</
button
>
</
PopoverTrigger
>
...
...
@@ -71,13 +71,13 @@ const SSOSection = () => {
<
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-secondary
outline-none rounded"
>
{
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"
className=
"flex items-center gap-2 px-2 py-1 text-left text-
destructive hover:bg-secondary
outline-none rounded"
>
{
t
(
"common.delete"
)
}
</
button
>
...
...
@@ -88,7 +88,7 @@ const SSOSection = () => {
</
div
>
))
}
{
identityProviderList
.
length
===
0
&&
(
<
div
className=
"w-full mt-2 text-sm
dark:border-zinc-700
opacity-60 flex flex-row items-center justify-between"
>
<
div
className=
"w-full mt-2 text-sm
border-border
opacity-60 flex flex-row items-center justify-between"
>
<
p
className=
""
>
{
t
(
"setting.sso-section.no-sso-found"
)
}
</
p
>
</
div
>
)
}
...
...
@@ -97,11 +97,7 @@ const SSOSection = () => {
<
p
className=
"text-sm"
>
{
t
(
"common.learn-more"
)
}
:
</
p
>
<
ul
className=
"list-disc list-inside text-sm ml-4"
>
<
li
>
<
Link
className=
"text-sm text-blue-600 hover:underline"
to=
"https://www.usememos.com/docs/advanced-settings/sso"
target=
"_blank"
>
<
Link
className=
"text-sm text-primary hover:underline"
to=
"https://www.usememos.com/docs/advanced-settings/sso"
target=
"_blank"
>
{
t
(
"setting.sso-section.single-sign-on"
)
}
</
Link
>
</
li
>
...
...
web/src/components/Settings/SectionMenuItem.tsx
View file @
91be2f68
...
...
@@ -13,7 +13,7 @@ const SectionMenuItem: React.FC<SettingMenuItemProps> = ({ text, icon: IconCompo
<
div
onClick=
{
onClick
}
className=
{
`w-auto max-w-full px-3 leading-8 flex flex-row justify-start items-center cursor-pointer rounded-lg select-none hover:opacity-80 ${
isSelected ? "bg-
zinc-100 shadow dark:bg-zinc-900
" : ""
isSelected ? "bg-
secondary shadow
" : ""
}`
}
>
<
IconComponent
className=
"w-4 h-auto mr-2 opacity-80 shrink-0"
/>
...
...
web/src/components/Settings/StorageSection.tsx
View file @
91be2f68
...
...
@@ -134,7 +134,7 @@ const StorageSection = observer(() => {
return
(
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
div
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.storage-section.current-storage"
)
}
</
div
>
<
div
className=
"font-medium text-
muted-foreground
"
>
{
t
(
"setting.storage-section.current-storage"
)
}
</
div
>
<
RadioGroup
value=
{
workspaceStorageSetting
.
storageType
.
toString
()
}
onValueChange=
{
(
value
)
=>
{
...
...
@@ -157,7 +157,7 @@ const StorageSection = observer(() => {
</
RadioGroup
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
"flex flex-row items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
{
t
(
"setting.system-section.max-upload-size"
)
}
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
{
t
(
"setting.system-section.max-upload-size"
)
}
</
span
>
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
>
...
...
@@ -173,7 +173,7 @@ const StorageSection = observer(() => {
</
div
>
{
workspaceStorageSetting
.
storageType
!==
WorkspaceStorageSetting_StorageType
.
DATABASE
&&
(
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
{
t
(
"setting.storage-section.filepath-template"
)
}
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
{
t
(
"setting.storage-section.filepath-template"
)
}
</
span
>
<
Input
value=
{
workspaceStorageSetting
.
filepathTemplate
}
placeholder=
"assets/
{
timestamp
}
_
{
filename
}"
...
...
@@ -184,11 +184,11 @@ const StorageSection = observer(() => {
{
workspaceStorageSetting
.
storageType
===
WorkspaceStorageSetting_StorageType
.
S3
&&
(
<>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
Access key id
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
Access key id
</
span
>
<
Input
value=
{
workspaceStorageSetting
.
s3Config
?.
accessKeyId
}
placeholder=
""
onChange=
{
handleS3ConfigAccessKeyIdChanged
}
/>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
Access key secret
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
Access key secret
</
span
>
<
Input
value=
{
workspaceStorageSetting
.
s3Config
?.
accessKeySecret
}
placeholder=
""
...
...
@@ -196,19 +196,19 @@ const StorageSection = observer(() => {
/>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
Endpoint
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
Endpoint
</
span
>
<
Input
value=
{
workspaceStorageSetting
.
s3Config
?.
endpoint
}
placeholder=
""
onChange=
{
handleS3ConfigEndpointChanged
}
/>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
Region
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
Region
</
span
>
<
Input
value=
{
workspaceStorageSetting
.
s3Config
?.
region
}
placeholder=
""
onChange=
{
handleS3ConfigRegionChanged
}
/>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
Bucket
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
Bucket
</
span
>
<
Input
value=
{
workspaceStorageSetting
.
s3Config
?.
bucket
}
placeholder=
""
onChange=
{
handleS3ConfigBucketChanged
}
/>
</
div
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
className=
"text-
gray-700 dark:text-gray-500
mr-1"
>
Use Path Style
</
span
>
<
span
className=
"text-
muted-foreground
mr-1"
>
Use Path Style
</
span
>
<
Switch
checked=
{
workspaceStorageSetting
.
s3Config
?.
usePathStyle
}
onCheckedChange=
{
(
checked
)
=>
handleS3ConfigUsePathStyleChanged
({
target
:
{
checked
}
}
as
any
)
}
...
...
@@ -227,7 +227,7 @@ const StorageSection = observer(() => {
<
ul
className=
"text-sm list-disc ml-4 space-y-1"
>
<
li
>
<
Link
className=
"text-sm text-
blue-600
hover:underline"
className=
"text-sm text-
primary
hover:underline"
to=
"https://www.usememos.com/docs/advanced-settings/local-storage"
target=
"_blank"
>
...
...
@@ -236,7 +236,7 @@ const StorageSection = observer(() => {
</
li
>
<
li
>
<
Link
className=
"text-sm text-
blue-600
hover:underline"
className=
"text-sm text-
primary
hover:underline"
to=
"https://www.usememos.com/blog/choosing-a-storage-for-your-resource"
target=
"_blank"
>
...
...
web/src/components/Settings/UserSessionsSection.tsx
View file @
91be2f68
...
...
@@ -41,12 +41,12 @@ const UserSessionsSection = () => {
const
getDeviceIcon
=
(
deviceType
:
string
)
=>
{
switch
(
deviceType
?.
toLowerCase
())
{
case
"mobile"
:
return
<
SmartphoneIcon
className=
"w-4 h-4 text-
gray-500
"
/>;
return
<
SmartphoneIcon
className=
"w-4 h-4 text-
muted-foreground
"
/>;
case
"tablet"
:
return
<
TabletIcon
className=
"w-4 h-4 text-
gray-500
"
/>;
return
<
TabletIcon
className=
"w-4 h-4 text-
muted-foreground
"
/>;
case
"desktop"
:
default
:
return
<
MonitorIcon
className=
"w-4 h-4 text-
gray-500
"
/>;
return
<
MonitorIcon
className=
"w-4 h-4 text-
muted-foreground
"
/>;
}
};
...
...
@@ -72,23 +72,23 @@ const UserSessionsSection = () => {
<
div
className=
"w-full"
>
<
div
className=
"sm:flex sm:items-center sm:justify-between"
>
<
div
className=
"sm:flex-auto space-y-1"
>
<
p
className=
"flex flex-row justify-start items-center font-medium text-
gray-700 dark:text-gray-400
"
>
<
p
className=
"flex flex-row justify-start items-center font-medium text-
muted-foreground
"
>
{
t
(
"setting.user-sessions-section.title"
)
}
<
LearnMore
className=
"ml-2"
url=
"https://usememos.com/docs/security/sessions"
/>
</
p
>
<
p
className=
"text-sm text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.user-sessions-section.description"
)
}
</
p
>
<
p
className=
"text-sm text-
muted-foreground
"
>
{
t
(
"setting.user-sessions-section.description"
)
}
</
p
>
</
div
>
</
div
>
<
div
className=
"w-full mt-2 flow-root"
>
<
div
className=
"overflow-x-auto"
>
<
div
className=
"inline-block min-w-full border border-
zinc-200 rounded-lg align-middle dark:border-zinc-600
"
>
<
table
className=
"min-w-full divide-y divide-
gray-300 dark:divide-zinc-600
"
>
<
div
className=
"inline-block min-w-full border border-
border rounded-lg align-middle
"
>
<
table
className=
"min-w-full divide-y divide-
border
"
>
<
thead
>
<
tr
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"setting.user-sessions-section.device"
)
}
</
th
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"setting.user-sessions-section.last-active"
)
}
</
th
>
<
th
scope=
"col"
className=
"relative py-3.5 pl-3 pr-4"
>
...
...
@@ -96,27 +96,27 @@ const UserSessionsSection = () => {
</
th
>
</
tr
>
</
thead
>
<
tbody
className=
"divide-y divide-
gray-200 dark:divide-zinc-700
"
>
<
tbody
className=
"divide-y divide-
border
"
>
{
userSessions
.
map
((
userSession
)
=>
(
<
tr
key=
{
userSession
.
sessionId
}
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-900 dark:text-gray-400
"
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
foreground
"
>
<
div
className=
"flex items-center space-x-3"
>
{
getDeviceIcon
(
userSession
.
clientInfo
?.
deviceType
||
""
)
}
<
div
className=
"flex flex-col"
>
<
span
className=
"font-medium"
>
{
formatDeviceInfo
(
userSession
.
clientInfo
)
}
{
isCurrentSession
(
userSession
)
&&
(
<
span
className=
"ml-2 inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-
green-100 text-green-800 dark:bg-green-800 dark:text-green-100
"
>
<
span
className=
"ml-2 inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-
primary/20 text-primary
"
>
<
WifiIcon
className=
"w-3 h-3 mr-1"
/>
{
t
(
"setting.user-sessions-section.current"
)
}
</
span
>
)
}
</
span
>
<
span
className=
"text-xs text-
gray-500
font-mono"
>
{
getFormattedSessionId
(
userSession
.
sessionId
)
}
</
span
>
<
span
className=
"text-xs text-
muted-foreground
font-mono"
>
{
getFormattedSessionId
(
userSession
.
sessionId
)
}
</
span
>
</
div
>
</
div
>
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-500 dark:text-gray-400
"
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
muted-foreground
"
>
<
div
className=
"flex items-center space-x-1"
>
<
ClockIcon
className=
"w-4 h-4"
/>
<
span
>
{
userSession
.
lastAccessedTime
?.
toLocaleString
()
}
</
span
>
...
...
@@ -135,7 +135,7 @@ const UserSessionsSection = () => {
:
t
(
"setting.user-sessions-section.revoke-session"
)
}
>
<
TrashIcon
className=
{
`w-4 h-auto ${isCurrentSession(userSession) ? "text-
gray-400" : "text-red-600
"}`
}
/>
<
TrashIcon
className=
{
`w-4 h-auto ${isCurrentSession(userSession) ? "text-
muted-foreground" : "text-destructive
"}`
}
/>
</
Button
>
</
td
>
</
tr
>
...
...
@@ -143,7 +143,7 @@ const UserSessionsSection = () => {
</
tbody
>
</
table
>
{
userSessions
.
length
===
0
&&
(
<
div
className=
"text-center py-8 text-
gray-500 dark:text-gray-400
"
>
{
t
(
"setting.user-sessions-section.no-sessions"
)
}
</
div
>
<
div
className=
"text-center py-8 text-
muted-foreground
"
>
{
t
(
"setting.user-sessions-section.no-sessions"
)
}
</
div
>
)
}
</
div
>
</
div
>
...
...
web/src/components/Settings/WebhookSection.tsx
View file @
91be2f68
...
...
@@ -44,7 +44,7 @@ const WebhookSection = () => {
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
div
className=
"w-full flex justify-between items-center"
>
<
div
className=
"flex-auto space-y-1"
>
<
p
className=
"flex flex-row justify-start items-center font-medium text-
gray-700 dark:text-gray-400
"
>
<
p
className=
"flex flex-row justify-start items-center font-medium text-
muted-foreground
"
>
{
t
(
"setting.webhook-section.title"
)
}
</
p
>
</
div
>
...
...
@@ -61,14 +61,14 @@ const WebhookSection = () => {
</
div
>
<
div
className=
"w-full mt-2 flow-root"
>
<
div
className=
"overflow-x-auto"
>
<
div
className=
"inline-block min-w-full border border-
zinc-200 rounded-lg align-middle dark:border-zinc-600
"
>
<
table
className=
"min-w-full divide-y divide-
gray-300 dark:divide-zinc-600
"
>
<
div
className=
"inline-block min-w-full border border-
border rounded-lg align-middle
"
>
<
table
className=
"min-w-full divide-y divide-
border
"
>
<
thead
>
<
tr
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"common.name"
)
}
</
th
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
gray-900 dark:text-gray-400
"
>
<
th
scope=
"col"
className=
"px-3 py-2 text-left text-sm font-semibold text-
foreground
"
>
{
t
(
"setting.webhook-section.url"
)
}
</
th
>
<
th
scope=
"col"
className=
"relative px-3 py-2 pr-4"
>
...
...
@@ -76,11 +76,11 @@ const WebhookSection = () => {
</
th
>
</
tr
>
</
thead
>
<
tbody
className=
"divide-y divide-
gray-200 dark:divide-gray-500
"
>
<
tbody
className=
"divide-y divide-
border
"
>
{
webhooks
.
map
((
webhook
)
=>
(
<
tr
key=
{
webhook
.
name
}
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-900 dark:text-gray-400
"
>
{
webhook
.
displayName
}
</
td
>
<
td
className=
"max-w-[200px] px-3 py-2 text-sm text-
gray-900 dark:text-gray-400
truncate"
title=
{
webhook
.
url
}
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
foreground
"
>
{
webhook
.
displayName
}
</
td
>
<
td
className=
"max-w-[200px] px-3 py-2 text-sm text-
foreground
truncate"
title=
{
webhook
.
url
}
>
{
webhook
.
url
}
</
td
>
<
td
className=
"relative whitespace-nowrap px-3 py-2 text-right text-sm"
>
...
...
@@ -90,7 +90,7 @@ const WebhookSection = () => {
handleDeleteWebhook
(
webhook
);
}
}
>
<
TrashIcon
className=
"text-
red-600
w-4 h-auto"
/>
<
TrashIcon
className=
"text-
destructive
w-4 h-auto"
/>
</
Button
>
</
td
>
</
tr
>
...
...
@@ -98,7 +98,7 @@ const WebhookSection = () => {
{
webhooks
.
length
===
0
&&
(
<
tr
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
gray-900 dark:text-gray-400
"
colSpan=
{
3
}
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-
foreground
"
colSpan=
{
3
}
>
{
t
(
"setting.webhook-section.no-webhooks-found"
)
}
</
td
>
</
tr
>
...
...
@@ -110,7 +110,7 @@ const WebhookSection = () => {
</
div
>
<
div
className=
"w-full mt-2"
>
<
Link
className=
"text-
gray-500 text-sm inline-flex flex-row justify-start items-center hover:underline hover:text-blue-600
"
className=
"text-
muted-foreground text-sm inline-flex flex-row justify-start items-center hover:underline hover:text-primary
"
to=
"https://usememos.com/docs/advanced-settings/webhook"
target=
"_blank"
>
...
...
web/src/components/Settings/WorkspaceSection.tsx
View file @
91be2f68
...
...
@@ -68,7 +68,7 @@ const WorkspaceSection = observer(() => {
return
(
<
div
className=
"w-full flex flex-col gap-2 pt-2 pb-4"
>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"common.basic"
)
}
</
p
>
<
p
className=
"font-medium text-
foreground
"
>
{
t
(
"common.basic"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
>
{
t
(
"setting.system-section.server-name"
)
}
:
{
" "
}
...
...
@@ -79,7 +79,7 @@ const WorkspaceSection = observer(() => {
</
Button
>
</
div
>
<
Separator
/>
<
p
className=
"font-medium text-
gray-700 dark:text-gray-500
"
>
{
t
(
"setting.system-section.title"
)
}
</
p
>
<
p
className=
"font-medium text-
foreground
"
>
{
t
(
"setting.system-section.title"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
span
>
{
t
(
"setting.system-section.additional-style"
)
}
</
span
>
</
div
>
...
...
@@ -102,7 +102,7 @@ const WorkspaceSection = observer(() => {
/>
<
div
className=
"w-full"
>
<
Link
className=
"text-
gray-500 text-sm flex flex-row justify-start items-center hover:underline hover:text-blue-600
"
className=
"text-
muted-foreground text-sm flex flex-row justify-start items-center hover:underline hover:text-primary
"
to=
"https://usememos.com/docs/advanced-settings/custom-style-and-script"
target=
"_blank"
>
...
...
web/src/components/StatisticsView/MonthNavigator.tsx
View file @
91be2f68
...
...
@@ -16,7 +16,7 @@ export const MonthNavigator = ({ visibleMonth, onMonthChange }: MonthNavigatorPr
return
(
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center gap-1"
>
<
span
className=
"relative text-sm text-
gray-500 dark:text-gray-400
"
>
<
span
className=
"relative text-sm text-
muted-foreground
"
>
{
currentMonth
.
toLocaleString
(
i18n
.
language
,
{
year
:
"numeric"
,
month
:
"long"
})
}
</
span
>
<
div
className=
"flex justify-end items-center shrink-0 gap-1"
>
...
...
web/src/components/StatisticsView/StatCard.tsx
View file @
91be2f68
...
...
@@ -6,8 +6,8 @@ export const StatCard = ({ icon, label, count, onClick, tooltip, className }: St
const
content
=
(
<
div
className=
{
cn
(
"w-auto border
border-zinc-200 dark:border-zinc-800
pl-1.5 pr-2 py-0.5 rounded-md flex justify-between items-center"
,
"cursor-pointer hover:bg-
gray-50 dark:hover:bg-zinc-800/50
transition-colors"
,
"w-auto border pl-1.5 pr-2 py-0.5 rounded-md flex justify-between items-center"
,
"cursor-pointer hover:bg-
muted
transition-colors"
,
className
,
)
}
onClick=
{
onClick
}
...
...
web/src/components/StatisticsView/StatisticsView.tsx
View file @
91be2f68
...
...
@@ -34,7 +34,7 @@ const StatisticsView = observer(() => {
const
hasPinnedMemos
=
currentUser
&&
(
userStore
.
state
.
currentUserStats
?.
pinnedMemos
||
[]).
length
>
0
;
return
(
<
div
className=
"group w-full mt-2 space-y-1 text-
zinc-600 dark:text-gray-400
animate-fade-in"
>
<
div
className=
"group w-full mt-2 space-y-1 text-
muted-foreground
animate-fade-in"
>
<
MonthNavigator
visibleMonth=
{
visibleMonthString
}
onMonthChange=
{
setVisibleMonthString
}
/>
<
div
className=
"w-full animate-scale-in"
>
...
...
web/src/components/TagTree.tsx
View file @
91be2f68
...
...
@@ -111,12 +111,12 @@ const TagItemContainer = observer((props: TagItemContainerProps) => {
<>
<
div
className=
"relative flex flex-row justify-between items-center w-full leading-6 py-0 mt-px rounded-lg text-sm select-none shrink-0"
>
<
div
className=
{
`flex flex-row justify-start items-center truncate shrink leading-5 mr-1 text-
gray-600 dark:text-gray-400
${
isActive && "text-
blue-600
!"
className=
{
`flex flex-row justify-start items-center truncate shrink leading-5 mr-1 text-
muted-foreground
${
isActive && "text-
primary
!"
}`
}
>
<
div
className=
"shrink-0"
>
<
HashIcon
className=
"w-4 h-auto shrink-0 mr-1 text-
gray-400 dark:text-gray-500
"
/>
<
HashIcon
className=
"w-4 h-auto shrink-0 mr-1 text-
muted-foreground
"
/>
</
div
>
<
span
className=
"truncate cursor-pointer hover:opacity-80"
onClick=
{
handleTagClick
}
>
{
tag
.
key
}
{
tag
.
amount
>
1
&&
`(${tag.amount})`
}
...
...
@@ -128,14 +128,14 @@ const TagItemContainer = observer((props: TagItemContainerProps) => {
className=
{
`flex flex-row justify-center items-center w-6 h-6 shrink-0 transition-all rotate-0 ${showSubTags && "rotate-90"}`
}
onClick=
{
handleToggleBtnClick
}
>
<
ChevronRightIcon
className=
"w-5 h-5 cursor-pointer text-
gray-400 dark:text-gray-500
"
/>
<
ChevronRightIcon
className=
"w-5 h-5 cursor-pointer text-
muted-foreground
"
/>
</
span
>
)
:
null
}
</
div
>
</
div
>
{
hasSubTags
?
(
<
div
className=
{
`w-[calc(100%-0.5rem)] flex flex-col justify-start items-start h-auto ml-2 pl-2 border-l-2 border-l-
gray-200 dark:border-l-zinc-800
${
className=
{
`w-[calc(100%-0.5rem)] flex flex-col justify-start items-start h-auto ml-2 pl-2 border-l-2 border-l-
border
${
!showSubTags && "hidden!"
}`
}
>
...
...
web/src/components/UpdateAccountDialog.tsx
View file @
91be2f68
...
...
@@ -141,7 +141,7 @@ const UpdateAccountDialog = ({ destroy }: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
className=
"title-text"
>
{
t
(
"setting.account-section.update-information"
)
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
handleCloseBtnClick
}
>
...
...
@@ -168,7 +168,7 @@ const UpdateAccountDialog = ({ destroy }: Props) => {
</
div
>
<
p
className=
"text-sm"
>
{
t
(
"common.username"
)
}
<
span
className=
"text-sm text-
gray-400
ml-1"
>
(
{
t
(
"setting.account-section.username-note"
)
}
)
</
span
>
<
span
className=
"text-sm text-
muted-foreground
ml-1"
>
(
{
t
(
"setting.account-section.username-note"
)
}
)
</
span
>
</
p
>
<
Input
className=
"w-full"
...
...
@@ -178,7 +178,7 @@ const UpdateAccountDialog = ({ destroy }: Props) => {
/>
<
p
className=
"text-sm"
>
{
t
(
"common.nickname"
)
}
<
span
className=
"text-sm text-
gray-400
ml-1"
>
(
{
t
(
"setting.account-section.nickname-note"
)
}
)
</
span
>
<
span
className=
"text-sm text-
muted-foreground
ml-1"
>
(
{
t
(
"setting.account-section.nickname-note"
)
}
)
</
span
>
</
p
>
<
Input
className=
"w-full"
...
...
@@ -188,7 +188,7 @@ const UpdateAccountDialog = ({ destroy }: Props) => {
/>
<
p
className=
"text-sm"
>
{
t
(
"common.email"
)
}
<
span
className=
"text-sm text-
gray-400
ml-1"
>
(
{
t
(
"setting.account-section.email-note"
)
}
)
</
span
>
<
span
className=
"text-sm text-
muted-foreground
ml-1"
>
(
{
t
(
"setting.account-section.email-note"
)
}
)
</
span
>
</
p
>
<
Input
className=
"w-full"
type=
"email"
value=
{
state
.
email
}
onChange=
{
handleEmailChanged
}
/>
<
p
className=
"text-sm"
>
{
t
(
"common.description"
)
}
</
p
>
...
...
web/src/components/UpdateCustomizedProfileDialog.tsx
View file @
91be2f68
...
...
@@ -98,7 +98,7 @@ const UpdateCustomizedProfileDialog = ({ destroy }: Props) => {
};
return
(
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
white dark:bg-zinc-800 dark:text-gray-300
p-4 rounded-lg"
>
<
div
className=
"max-w-full shadow flex flex-col justify-start items-start bg-
card text-card-foreground
p-4 rounded-lg"
>
<
div
className=
"flex flex-row justify-between items-center mb-4 gap-2 w-full"
>
<
p
className=
"title-text"
>
{
t
(
"setting.system-section.customize-server.title"
)
}
</
p
>
<
Button
variant=
"ghost"
onClick=
{
handleCloseButtonClick
}
>
...
...
web/src/components/UserAvatar.tsx
View file @
91be2f68
...
...
@@ -10,7 +10,7 @@ const UserAvatar = (props: Props) => {
return
(
<
div
className=
{
cn
(
`w-8 h-8 overflow-clip rounded-xl`
,
className
)
}
>
<
img
className=
"w-full h-auto shadow min-w-full min-h-full object-cover
dark:
opacity-80"
className=
"w-full h-auto shadow min-w-full min-h-full object-cover opacity-80"
src=
{
avatarUrl
||
"/full-logo.webp"
}
decoding=
"async"
loading=
"lazy"
...
...
web/src/components/UserBanner.tsx
View file @
91be2f68
...
...
@@ -28,10 +28,7 @@ const UserBanner = (props: Props) => {
<
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"
,
collapsed
?
"px-1"
:
"px-3"
,
)
}
className=
{
cn
(
"w-auto flex flex-row justify-start items-center cursor-pointer text-foreground"
,
collapsed
?
"px-1"
:
"px-3"
)
}
>
{
currentUser
.
avatarUrl
?
(
<
UserAvatar
className=
"shrink-0"
avatarUrl=
{
currentUser
.
avatarUrl
}
/>
...
...
@@ -39,7 +36,7 @@ const UserBanner = (props: Props) => {
<
User2Icon
className=
"w-6 mx-auto h-auto opacity-60"
/>
)
}
{
!
collapsed
&&
(
<
span
className=
"ml-2 text-lg font-medium text-
slate-800 dark:text-gray-300
grow truncate"
>
<
span
className=
"ml-2 text-lg font-medium text-
foreground
grow truncate"
>
{
currentUser
.
displayName
||
currentUser
.
username
}
</
span
>
)
}
...
...
@@ -49,35 +46,35 @@ const UserBanner = (props: Props) => {
<
div
className=
"flex flex-col text-sm gap-0.5"
>
<
button
onClick=
{
()
=>
navigateTo
(
`/u/${encodeURIComponent(currentUser.username)}`
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-muted
outline-none rounded"
>
<
SquareUserIcon
className=
"w-4 h-auto opacity-60"
/>
<
span
className=
"truncate"
>
{
t
(
"common.profile"
)
}
</
span
>
</
button
>
<
button
onClick=
{
()
=>
navigateTo
(
Routes
.
ARCHIVED
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-muted
outline-none rounded"
>
<
ArchiveIcon
className=
"w-4 h-auto opacity-60"
/>
<
span
className=
"truncate"
>
{
t
(
"common.archived"
)
}
</
span
>
</
button
>
<
button
onClick=
{
()
=>
navigateTo
(
Routes
.
INBOX
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-muted
outline-none rounded"
>
<
BellIcon
className=
"w-4 h-auto opacity-60"
/>
<
span
className=
"truncate"
>
{
t
(
"common.inbox"
)
}
</
span
>
</
button
>
<
button
onClick=
{
()
=>
navigateTo
(
Routes
.
SETTING
)
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-muted
outline-none rounded"
>
<
SettingsIcon
className=
"w-4 h-auto opacity-60"
/>
<
span
className=
"truncate"
>
{
t
(
"common.settings"
)
}
</
span
>
</
button
>
<
button
onClick=
{
handleSignOut
}
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"
className=
"flex items-center gap-2 px-2 py-1 text-left
text-foreground hover:bg-muted
outline-none rounded"
>
<
LogOutIcon
className=
"w-4 h-auto opacity-60"
/>
<
span
className=
"truncate"
>
{
t
(
"common.sign-out"
)
}
</
span
>
...
...
web/src/components/VisibilityIcon.tsx
View file @
91be2f68
...
...
@@ -22,7 +22,7 @@ const VisibilityIcon = (props: Props) => {
return
null
;
}
return
<
VIcon
className=
{
cn
(
"w-4 h-auto text-
gray-500 dark:text-gray-400
"
,
className
)
}
/>;
return
<
VIcon
className=
{
cn
(
"w-4 h-auto text-
muted-foreground
"
,
className
)
}
/>;
};
export
default
VisibilityIcon
;
web/src/components/ui/badge.tsx
View file @
91be2f68
...
...
@@ -11,7 +11,7 @@ const badgeVariants = cva(
default
:
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90"
,
secondary
:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90"
,
destructive
:
"border-transparent bg-destructive text-
white
[a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60"
,
"border-transparent bg-destructive text-
destructive-foreground
[a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60"
,
outline
:
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
,
},
},
...
...
web/src/components/ui/button.tsx
View file @
91be2f68
...
...
@@ -10,7 +10,7 @@ const buttonVariants = cva(
variant
:
{
default
:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90"
,
destructive
:
"bg-destructive text-
white
shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60"
,
"bg-destructive text-
destructive-foreground
shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60"
,
outline
:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
,
secondary
:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80"
,
...
...
web/src/components/ui/dialog.tsx
View file @
91be2f68
...
...
@@ -24,7 +24,7 @@ function DialogOverlay({ className, ...props }: React.ComponentProps<typeof Dial
<
DialogPrimitive
.
Overlay
data
-
slot=
"dialog-overlay"
className=
{
cn
(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-
black
/50"
,
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-
foreground
/50"
,
className
,
)
}
{
...
props
}
...
...
web/src/components/ui/sheet.tsx
View file @
91be2f68
...
...
@@ -24,7 +24,7 @@ function SheetOverlay({ className, ...props }: React.ComponentProps<typeof Sheet
<
SheetPrimitive
.
Overlay
data
-
slot=
"sheet-overlay"
className=
{
cn
(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-
black
/50"
,
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-
foreground
/50"
,
className
,
)
}
{
...
props
}
...
...
web/src/layouts/HomeLayout.tsx
View file @
91be2f68
...
...
@@ -19,7 +19,7 @@ const HomeLayout = observer(() => {
<
div
className=
{
cn
(
"fixed top-0 left-16 shrink-0 h-svh transition-all"
,
"border-r border
-gray-200 dark:border-zinc-800
"
,
"border-r border"
,
lg
?
"w-72"
:
"w-56"
,
)
}
>
...
...
web/src/layouts/RootLayout.tsx
View file @
91be2f68
...
...
@@ -50,7 +50,7 @@ const RootLayout = observer(() => {
{
sm
&&
(
<
div
className=
{
cn
(
"group flex flex-col justify-start items-start fixed top-0 left-0 select-none border-r border
-zinc-200 dark:border-zinc-800 h-full bg-zinc-100 dark:bg-zinc-800 dark:bg-opacity-40
"
,
"group flex flex-col justify-start items-start fixed top-0 left-0 select-none border-r border
h-full bg-secondary
"
,
"w-16 px-2"
,
)
}
>
...
...
web/src/main.tsx
View file @
91be2f68
...
...
@@ -13,7 +13,7 @@ import "leaflet/dist/leaflet.css";
const
Main
=
observer
(()
=>
(
<>
<
RouterProvider
router=
{
router
}
/>
<
Toaster
position=
"top-right"
toastOptions=
{
{
className
:
"dark:bg-zinc-700 dark:text-gray-300"
}
}
/>
<
Toaster
position=
"top-right"
/>
</>
));
...
...
web/src/pages/AdminSignIn.tsx
View file @
91be2f68
...
...
@@ -11,11 +11,11 @@ const AdminSignIn = observer(() => {
<
div
className=
"w-full py-4 grow flex flex-col justify-center items-center"
>
<
div
className=
"w-full flex flex-row justify-center items-center mb-6"
>
<
img
className=
"h-14 w-auto rounded-full shadow"
src=
{
workspaceGeneralSetting
.
customProfile
?.
logoUrl
||
"/logo.webp"
}
alt=
""
/>
<
p
className=
"ml-2 text-5xl text-
black opacity-80 dark:text-gray-20
0"
>
<
p
className=
"ml-2 text-5xl text-
foreground opacity-8
0"
>
{
workspaceGeneralSetting
.
customProfile
?.
title
||
"Memos"
}
</
p
>
</
div
>
<
p
className=
"w-full text-xl font-medium
dark:text-gray-500
"
>
Sign in with admin accounts
</
p
>
<
p
className=
"w-full text-xl font-medium
text-muted-foreground
"
>
Sign in with admin accounts
</
p
>
<
PasswordSignInForm
/>
</
div
>
<
AuthFooter
/>
...
...
web/src/pages/Attachments.tsx
View file @
91be2f68
...
...
@@ -70,7 +70,7 @@ const Attachments = observer(() => {
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8"
>
{
!
md
&&
<
MobileHeader
/>
}
<
div
className=
"w-full px-4 sm:px-6"
>
<
div
className=
"w-full shadow flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-
white dark:bg-zinc-800 text-black dark:text-gray-300
"
>
<
div
className=
"w-full shadow flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-
background text-foreground
"
>
<
div
className=
"relative w-full flex flex-row justify-between items-center"
>
<
p
className=
"py-1 flex flex-row justify-start items-center select-none opacity-80"
>
<
PaperclipIcon
className=
"w-6 h-auto mr-1 opacity-80"
/>
...
...
@@ -78,7 +78,7 @@ const Attachments = observer(() => {
</
p
>
<
div
>
<
div
className=
"relative max-w-32"
>
<
SearchIcon
className=
"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-
gray-500
"
/>
<
SearchIcon
className=
"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-
muted-foreground
"
/>
<
Input
className=
"pl-9"
placeholder=
{
t
(
"common.search"
)
}
...
...
@@ -98,7 +98,7 @@ const Attachments = observer(() => {
{
filteredAttachments
.
length
===
0
?
(
<
div
className=
"w-full mt-8 mb-8 flex flex-col justify-center items-center italic"
>
<
Empty
/>
<
p
className=
"mt-4 text-
gray-600 dark:text-gray-400
"
>
{
t
(
"message.no-data"
)
}
</
p
>
<
p
className=
"mt-4 text-
muted-foreground
"
>
{
t
(
"message.no-data"
)
}
</
p
>
</
div
>
)
:
(
<
div
className=
{
"w-full h-auto px-2 flex flex-col justify-start items-start gap-y-8"
}
>
...
...
@@ -115,11 +115,11 @@ const Attachments = observer(() => {
{
attachments
.
map
((
attachment
)
=>
{
return
(
<
div
key=
{
attachment
.
name
}
className=
"w-24 sm:w-32 h-auto flex flex-col justify-start items-start"
>
<
div
className=
"w-24 h-24 flex justify-center items-center sm:w-32 sm:h-32 border border-
zinc-200 dark:border-zinc-900
overflow-clip rounded-xl cursor-pointer hover:shadow hover:opacity-80"
>
<
div
className=
"w-24 h-24 flex justify-center items-center sm:w-32 sm:h-32 border border-
border
overflow-clip rounded-xl cursor-pointer hover:shadow hover:opacity-80"
>
<
AttachmentIcon
attachment=
{
attachment
}
strokeWidth=
{
0.5
}
/>
</
div
>
<
div
className=
"w-full max-w-full flex flex-row justify-between items-center mt-1 px-1"
>
<
p
className=
"text-xs shrink text-
gray-400
truncate"
>
{
attachment
.
filename
}
</
p
>
<
p
className=
"text-xs shrink text-
muted-foreground
truncate"
>
{
attachment
.
filename
}
</
p
>
</
div
>
</
div
>
);
...
...
@@ -136,8 +136,8 @@ const Attachments = observer(() => {
<
div
className=
"w-16 sm:w-24 sm:pl-4 flex flex-col justify-start items-start"
></
div
>
<
div
className=
"w-full max-w-[calc(100%-4rem)] sm:max-w-[calc(100%-6rem)] flex flex-row justify-start items-start gap-4 flex-wrap"
>
<
div
className=
"w-full flex flex-row justify-start items-center gap-2"
>
<
span
className=
"text-
gray-600 dark:text-gray-400
"
>
{
t
(
"resource.unused-resources"
)
}
</
span
>
<
span
className=
"text-
gray-500 dark:text-gray-500
opacity-80"
>
(
{
unusedAttachments
.
length
}
)
</
span
>
<
span
className=
"text-
muted-foreground
"
>
{
t
(
"resource.unused-resources"
)
}
</
span
>
<
span
className=
"text-
muted-foreground
opacity-80"
>
(
{
unusedAttachments
.
length
}
)
</
span
>
<
TooltipProvider
>
<
Tooltip
>
<
TooltipTrigger
asChild
>
...
...
@@ -154,11 +154,11 @@ const Attachments = observer(() => {
{
unusedAttachments
.
map
((
attachment
)
=>
{
return
(
<
div
key=
{
attachment
.
name
}
className=
"w-24 sm:w-32 h-auto flex flex-col justify-start items-start"
>
<
div
className=
"w-24 h-24 flex justify-center items-center sm:w-32 sm:h-32 border border-
zinc-200 dark:border-zinc-900
overflow-clip rounded-xl cursor-pointer hover:shadow hover:opacity-80"
>
<
div
className=
"w-24 h-24 flex justify-center items-center sm:w-32 sm:h-32 border border-
border
overflow-clip rounded-xl cursor-pointer hover:shadow hover:opacity-80"
>
<
AttachmentIcon
attachment=
{
attachment
}
strokeWidth=
{
0.5
}
/>
</
div
>
<
div
className=
"w-full max-w-full flex flex-row justify-between items-center mt-1 px-1"
>
<
p
className=
"text-xs shrink text-
gray-400
truncate"
>
{
attachment
.
filename
}
</
p
>
<
p
className=
"text-xs shrink text-
muted-foreground
truncate"
>
{
attachment
.
filename
}
</
p
>
</
div
>
</
div
>
);
...
...
web/src/pages/AuthCallback.tsx
View file @
91be2f68
...
...
@@ -72,7 +72,7 @@ const AuthCallback = observer(() => {
return
(
<
div
className=
"p-4 py-24 w-full h-full flex justify-center items-center"
>
{
state
.
loading
?
(
<
LoaderIcon
className=
"animate-spin
dark:text-gray-200
"
/>
<
LoaderIcon
className=
"animate-spin
text-foreground
"
/>
)
:
(
<
div
className=
"max-w-lg font-mono whitespace-pre-wrap opacity-80"
>
{
state
.
errorMessage
}
</
div
>
)
}
...
...
web/src/pages/Inboxes.tsx
View file @
91be2f68
...
...
@@ -7,14 +7,14 @@ import MemoCommentMessage from "@/components/Inbox/MemoCommentMessage";
import
MobileHeader
from
"@/components/MobileHeader"
;
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
{
userStore
}
from
"@/store/v2"
;
import
{
Inbox_Status
,
Inbox_Type
}
from
"@/types/proto/api/v1/inbox_service"
;
import
{
Inbox
,
Inbox
_Status
,
Inbox_Type
}
from
"@/types/proto/api/v1/inbox_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
const
Inboxes
=
observer
(()
=>
{
const
t
=
useTranslate
();
const
{
md
}
=
useResponsiveWidth
();
const
inboxes
=
sortBy
(
userStore
.
state
.
inboxes
,
(
inbox
)
=>
{
const
inboxes
=
sortBy
(
userStore
.
state
.
inboxes
,
(
inbox
:
Inbox
)
=>
{
if
(
inbox
.
status
===
Inbox_Status
.
UNREAD
)
return
0
;
if
(
inbox
.
status
===
Inbox_Status
.
ARCHIVED
)
return
1
;
return
2
;
...
...
@@ -36,7 +36,7 @@ const Inboxes = observer(() => {
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8"
>
{
!
md
&&
<
MobileHeader
/>
}
<
div
className=
"w-full px-4 sm:px-6"
>
<
div
className=
"w-full shadow flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-
white dark:bg-zinc-800 text-black dark:text-gray-300
"
>
<
div
className=
"w-full shadow flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-
background text-foreground
"
>
<
div
className=
"relative w-full flex flex-row justify-between items-center"
>
<
p
className=
"py-1 flex flex-row justify-start items-center select-none opacity-80"
>
<
BellIcon
className=
"w-6 h-auto mr-1 opacity-80"
/>
...
...
@@ -47,11 +47,11 @@ const Inboxes = observer(() => {
{
inboxes
.
length
===
0
&&
(
<
div
className=
"w-full mt-4 mb-8 flex flex-col justify-center items-center italic"
>
<
Empty
/>
<
p
className=
"mt-4 text-
gray-600 dark:text-gray-400
"
>
{
t
(
"message.no-data"
)
}
</
p
>
<
p
className=
"mt-4 text-
muted-foreground
"
>
{
t
(
"message.no-data"
)
}
</
p
>
</
div
>
)
}
<
div
className=
"flex flex-col justify-start items-start w-full mt-4 gap-4"
>
{
inboxes
.
map
((
inbox
)
=>
{
{
inboxes
.
map
((
inbox
:
Inbox
)
=>
{
if
(
inbox
.
type
===
Inbox_Type
.
MEMO_COMMENT
)
{
return
<
MemoCommentMessage
key=
{
`${inbox.name}-${inbox.status}`
}
inbox=
{
inbox
}
/>;
}
...
...
web/src/pages/Loading.tsx
View file @
91be2f68
...
...
@@ -4,7 +4,7 @@ function Loading() {
return
(
<
div
className=
"fixed w-full h-full flex flex-row justify-center items-center"
>
<
div
className=
"w-80 max-w-full h-full py-4 flex flex-col justify-center items-center"
>
<
LoaderIcon
className=
"animate-spin
dark:text-gray-200
"
/>
<
LoaderIcon
className=
"animate-spin
text-foreground
"
/>
</
div
>
</
div
>
);
...
...
web/src/pages/MemoDetail.tsx
View file @
91be2f68
...
...
@@ -93,7 +93,7 @@ const MemoDetail = observer(() => {
{
parentMemo
&&
(
<
div
className=
"w-auto inline-block mb-2"
>
<
Link
className=
"px-3 py-1 border border-
zinc-200 rounded-lg max-w-xs w-auto text-sm flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-400 dark:border-gray-500
hover:shadow hover:opacity-80"
className=
"px-3 py-1 border border-
border rounded-lg max-w-xs w-auto text-sm flex flex-row justify-start items-center flex-nowrap text-muted-foreground
hover:shadow hover:opacity-80"
to=
{
`/${parentMemo.name}`
}
state=
{
locationState
}
viewTransition
...
...
@@ -123,8 +123,8 @@ const MemoDetail = observer(() => {
showCreateCommentButton
&&
(
<
div
className=
"w-full flex flex-row justify-center items-center py-6"
>
<
Button
variant=
"ghost"
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
"
/>
<
span
className=
"text-
muted-foreground
"
>
{
t
(
"memo.comment.write-a-comment"
)
}
</
span
>
<
MessageCircleIcon
className=
"ml-2 w-5 h-auto text-
muted-foreground
"
/>
</
Button
>
</
div
>
)
...
...
@@ -132,12 +132,12 @@ const MemoDetail = observer(() => {
<>
<
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
>
<
MessageCircleIcon
className=
"w-5 h-auto text-
muted-foreground
mr-1"
/>
<
span
className=
"text-
muted-foreground
text-sm"
>
{
t
(
"memo.comment.self"
)
}
</
span
>
<
span
className=
"text-
muted-foreground
text-sm ml-1"
>
(
{
comments
.
length
}
)
</
span
>
</
div
>
{
showCreateCommentButton
&&
(
<
Button
variant=
"ghost"
className=
"text-
gray-500
"
onClick=
{
handleShowCommentEditor
}
>
<
Button
variant=
"ghost"
className=
"text-
muted-foreground
"
onClick=
{
handleShowCommentEditor
}
>
{
t
(
"memo.comment.write-a-comment"
)
}
</
Button
>
)
}
...
...
web/src/pages/NotFound.tsx
View file @
91be2f68
...
...
@@ -6,7 +6,7 @@ const NotFound = () => {
<
MobileHeader
/>
<
div
className=
"w-full px-4 grow flex flex-col justify-center items-center sm:px-6"
>
<
p
className=
"font-medium"
>
{
"The page you are looking for can't be found."
}
</
p
>
<
p
className=
"mt-4 text-[8rem] font-mono
dark:text-gray-300
"
>
404
</
p
>
<
p
className=
"mt-4 text-[8rem] font-mono
text-foreground
"
>
404
</
p
>
</
div
>
</
section
>
);
...
...
web/src/pages/PermissionDenied.tsx
View file @
91be2f68
...
...
@@ -6,7 +6,7 @@ const PermissionDenied = () => {
<
MobileHeader
/>
<
div
className=
"w-full px-4 grow flex flex-col justify-center items-center sm:px-6"
>
<
p
className=
"font-medium"
>
Permission denied
</
p
>
<
p
className=
"mt-4 text-[8rem] font-mono
dark:text-gray-300
"
>
403
</
p
>
<
p
className=
"mt-4 text-[8rem] font-mono
text-foreground
"
>
403
</
p
>
</
div
>
</
section
>
);
...
...
web/src/pages/Setting.tsx
View file @
91be2f68
...
...
@@ -87,9 +87,9 @@ const Setting = observer(() => {
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-start sm:pt-3 md:pt-6 pb-8"
>
{
!
md
&&
<
MobileHeader
/>
}
<
div
className=
"w-full px-4 sm:px-6"
>
<
div
className=
"w-full shadow flex flex-row justify-start items-start px-4 py-3 rounded-xl bg-
white dark:bg-zinc-800 text-gray-600 dark:text-gray-400
"
>
<
div
className=
"w-full shadow flex flex-row justify-start items-start px-4 py-3 rounded-xl bg-
background text-muted-foreground
"
>
<
div
className=
"hidden sm:flex flex-col justify-start items-start w-40 h-auto shrink-0 py-2"
>
<
span
className=
"text-sm mt-0.5 pl-3 font-mono select-none text-
gray-400 dark:text-gray-500
"
>
{
t
(
"common.basic"
)
}
</
span
>
<
span
className=
"text-sm mt-0.5 pl-3 font-mono select-none text-
muted-foreground
"
>
{
t
(
"common.basic"
)
}
</
span
>
<
div
className=
"w-full flex flex-col justify-start items-start mt-1"
>
{
BASIC_SECTIONS
.
map
((
item
)
=>
(
<
SectionMenuItem
...
...
@@ -103,7 +103,7 @@ const Setting = observer(() => {
</
div
>
{
isHost
?
(
<>
<
span
className=
"text-sm mt-4 pl-3 font-mono select-none text-
gray-400 dark:text-gray-500
"
>
{
t
(
"common.admin"
)
}
</
span
>
<
span
className=
"text-sm mt-4 pl-3 font-mono select-none text-
muted-foreground
"
>
{
t
(
"common.admin"
)
}
</
span
>
<
div
className=
"w-full flex flex-col justify-start items-start mt-1"
>
{
ADMIN_SECTIONS
.
map
((
item
)
=>
(
<
SectionMenuItem
...
...
web/src/pages/SignIn.tsx
View file @
91be2f68
...
...
@@ -60,19 +60,19 @@ const SignIn = observer(() => {
<
div
className=
"w-full py-4 grow flex flex-col justify-center items-center"
>
<
div
className=
"w-full flex flex-row justify-center items-center mb-6"
>
<
img
className=
"h-14 w-auto rounded-full shadow"
src=
{
workspaceGeneralSetting
.
customProfile
?.
logoUrl
||
"/logo.webp"
}
alt=
""
/>
<
p
className=
"ml-2 text-5xl text-
black opacity-80 dark:text-gray-20
0"
>
<
p
className=
"ml-2 text-5xl text-
foreground opacity-8
0"
>
{
workspaceGeneralSetting
.
customProfile
?.
title
||
"Memos"
}
</
p
>
</
div
>
{
!
workspaceGeneralSetting
.
disallowPasswordAuth
?
(
<
PasswordSignInForm
/>
)
:
(
identityProviderList
.
length
==
0
&&
<
p
className=
"w-full text-2xl mt-2
dark:text-gray-500
"
>
Password auth is not allowed.
</
p
>
identityProviderList
.
length
==
0
&&
<
p
className=
"w-full text-2xl mt-2
text-muted-foreground
"
>
Password auth is not allowed.
</
p
>
)
}
{
!
workspaceGeneralSetting
.
disallowUserRegistration
&&
!
workspaceGeneralSetting
.
disallowPasswordAuth
&&
(
<
p
className=
"w-full mt-4 text-sm"
>
<
span
className=
"
dark:text-gray-500
"
>
{
t
(
"auth.sign-up-tip"
)
}
</
span
>
<
Link
to=
"/auth/signup"
className=
"cursor-pointer ml-2 text-
blue-600
hover:underline"
viewTransition
>
<
span
className=
"
text-muted-foreground
"
>
{
t
(
"auth.sign-up-tip"
)
}
</
span
>
<
Link
to=
"/auth/signup"
className=
"cursor-pointer ml-2 text-
primary
hover:underline"
viewTransition
>
{
t
(
"common.sign-up"
)
}
</
Link
>
</
p
>
...
...
@@ -90,7 +90,7 @@ const SignIn = observer(() => {
<
div
className=
"w-full flex flex-col space-y-2"
>
{
identityProviderList
.
map
((
identityProvider
)
=>
(
<
Button
className=
"bg-
white dark:bg-black
w-full"
className=
"bg-
background
w-full"
key=
{
identityProvider
.
name
}
variant=
"outline"
onClick=
{
()
=>
handleSignInWithIdentityProvider
(
identityProvider
)
}
...
...
web/src/pages/SignUp.tsx
View file @
91be2f68
...
...
@@ -72,19 +72,19 @@ const SignUp = observer(() => {
<
div
className=
"w-full py-4 grow flex flex-col justify-center items-center"
>
<
div
className=
"w-full flex flex-row justify-center items-center mb-6"
>
<
img
className=
"h-14 w-auto rounded-full shadow"
src=
{
workspaceGeneralSetting
.
customProfile
?.
logoUrl
||
"/logo.webp"
}
alt=
""
/>
<
p
className=
"ml-2 text-5xl text-
black opacity-80 dark:text-gray-20
0"
>
<
p
className=
"ml-2 text-5xl text-
foreground opacity-8
0"
>
{
workspaceGeneralSetting
.
customProfile
?.
title
||
"Memos"
}
</
p
>
</
div
>
{
!
workspaceGeneralSetting
.
disallowUserRegistration
?
(
<>
<
p
className=
"w-full text-2xl mt-2
dark:text-gray-500
"
>
{
t
(
"auth.create-your-account"
)
}
</
p
>
<
p
className=
"w-full text-2xl mt-2
text-muted-foreground
"
>
{
t
(
"auth.create-your-account"
)
}
</
p
>
<
form
className=
"w-full mt-2"
onSubmit=
{
handleFormSubmit
}
>
<
div
className=
"flex flex-col justify-start items-start w-full gap-4"
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
span
className=
"leading-8 text-
gray-600
"
>
{
t
(
"common.username"
)
}
</
span
>
<
span
className=
"leading-8 text-
muted-foreground
"
>
{
t
(
"common.username"
)
}
</
span
>
<
Input
className=
"w-full bg-
white dark:bg-black
h-10"
className=
"w-full bg-
background
h-10"
type=
"text"
readOnly=
{
actionBtnLoadingState
.
isLoading
}
placeholder=
{
t
(
"common.username"
)
}
...
...
@@ -97,9 +97,9 @@ const SignUp = observer(() => {
/>
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
span
className=
"leading-8 text-
gray-600
"
>
{
t
(
"common.password"
)
}
</
span
>
<
span
className=
"leading-8 text-
muted-foreground
"
>
{
t
(
"common.password"
)
}
</
span
>
<
Input
className=
"w-full bg-
white dark:bg-black
h-10"
className=
"w-full bg-
background
h-10"
type=
"password"
readOnly=
{
actionBtnLoadingState
.
isLoading
}
placeholder=
{
t
(
"common.password"
)
}
...
...
@@ -121,14 +121,14 @@ const SignUp = observer(() => {
</
form
>
</>
)
:
(
<
p
className=
"w-full text-2xl mt-2
dark:text-gray-500
"
>
Sign up is not allowed.
</
p
>
<
p
className=
"w-full text-2xl mt-2
text-muted-foreground
"
>
Sign up is not allowed.
</
p
>
)
}
{
!
workspaceStore
.
state
.
profile
.
owner
?
(
<
p
className=
"w-full mt-4 text-sm font-medium
dark:text-gray-500
"
>
{
t
(
"auth.host-tip"
)
}
</
p
>
<
p
className=
"w-full mt-4 text-sm font-medium
text-muted-foreground
"
>
{
t
(
"auth.host-tip"
)
}
</
p
>
)
:
(
<
p
className=
"w-full mt-4 text-sm"
>
<
span
className=
"
dark:text-gray-500
"
>
{
t
(
"auth.sign-in-tip"
)
}
</
span
>
<
Link
to=
"/auth"
className=
"cursor-pointer ml-2 text-
blue-600
hover:underline"
viewTransition
>
<
span
className=
"
text-muted-foreground
"
>
{
t
(
"auth.sign-in-tip"
)
}
</
span
>
<
Link
to=
"/auth"
className=
"cursor-pointer ml-2 text-
primary
hover:underline"
viewTransition
>
{
t
(
"common.sign-in"
)
}
</
Link
>
</
p
>
...
...
web/src/pages/UserProfile.tsx
View file @
91be2f68
...
...
@@ -89,10 +89,10 @@ const UserProfile = observer(() => {
<
div
className=
"w-full flex flex-col justify-start items-start pt-4 pb-8 px-3"
>
<
UserAvatar
className=
"w-16! h-16! drop-shadow rounded-3xl"
avatarUrl=
{
user
?.
avatarUrl
}
/>
<
div
className=
"mt-2 w-auto max-w-[calc(100%-6rem)] flex flex-col justify-center items-start"
>
<
p
className=
"w-full text-3xl text-
black leading-tight font-medium opacity-80 dark:text-gray-20
0 truncate"
>
<
p
className=
"w-full text-3xl text-
foreground leading-tight font-medium opacity-8
0 truncate"
>
{
user
.
displayName
||
user
.
username
}
</
p
>
<
p
className=
"w-full text-
gray-500 leading-snug dark:text-gray-400
whitespace-pre-wrap truncate line-clamp-6"
>
<
p
className=
"w-full text-
muted-foreground leading-snug
whitespace-pre-wrap truncate line-clamp-6"
>
{
user
.
description
}
</
p
>
</
div
>
...
...
web/src/style.css
View file @
91be2f68
...
...
@@ -29,6 +29,7 @@
--color-accent
:
var
(
--accent
);
--color-accent-foreground
:
var
(
--accent-foreground
);
--color-destructive
:
var
(
--destructive
);
--color-destructive-foreground
:
var
(
--destructive-foreground
);
--color-border
:
var
(
--border
);
--color-input
:
var
(
--input
);
--color-ring
:
var
(
--ring
);
...
...
@@ -48,72 +49,74 @@
}
:root
{
--radius
:
0.625rem
;
--background
:
oklch
(
1
0
0
);
--foreground
:
oklch
(
0.141
0.005
285.823
);
--card
:
oklch
(
1
0
0
);
--card-foreground
:
oklch
(
0.141
0.005
285.823
);
--popover
:
oklch
(
1
0
0
);
--popover-foreground
:
oklch
(
0.141
0.005
285.823
);
--primary
:
oklch
(
0.21
0.006
285.885
);
--primary-foreground
:
oklch
(
0.985
0
0
);
--secondary
:
oklch
(
0.967
0.001
286.375
);
--secondary-foreground
:
oklch
(
0.21
0.006
285.885
);
--muted
:
oklch
(
0.967
0.001
286.375
);
--muted-foreground
:
oklch
(
0.552
0.016
285.938
);
--accent
:
oklch
(
0.967
0.001
286.375
);
--accent-foreground
:
oklch
(
0.21
0.006
285.885
);
--destructive
:
oklch
(
0.577
0.245
27.325
);
--border
:
oklch
(
0.92
0.004
286.32
);
--input
:
oklch
(
0.92
0.004
286.32
);
--ring
:
oklch
(
0.705
0.015
286.067
);
--chart-1
:
oklch
(
0.646
0.222
41.116
);
--chart-2
:
oklch
(
0.6
0.118
184.704
);
--chart-3
:
oklch
(
0.398
0.07
227.392
);
--chart-4
:
oklch
(
0.828
0.189
84.429
);
--chart-5
:
oklch
(
0.769
0.188
70.08
);
--sidebar
:
oklch
(
0.985
0
0
);
--sidebar-foreground
:
oklch
(
0.141
0.005
285.823
);
--sidebar-primary
:
oklch
(
0.21
0.006
285.885
);
--sidebar-primary-foreground
:
oklch
(
0.985
0
0
);
--sidebar-accent
:
oklch
(
0.967
0.001
286.375
);
--sidebar-accent-foreground
:
oklch
(
0.21
0.006
285.885
);
--sidebar-border
:
oklch
(
0.92
0.004
286.32
);
--sidebar-ring
:
oklch
(
0.705
0.015
286.067
);
--radius
:
0.5rem
;
--background
:
oklch
(
0.9818
0.0054
95.0986
);
--foreground
:
oklch
(
0.3438
0.0269
95.7226
);
--card
:
oklch
(
0.9818
0.0054
95.0986
);
--card-foreground
:
oklch
(
0.1908
0.0020
106.5859
);
--popover
:
oklch
(
1.0000
0
0
);
--popover-foreground
:
oklch
(
0.2671
0.0196
98.9390
);
--primary
:
oklch
(
0.6171
0.1375
39.0427
);
--primary-foreground
:
oklch
(
1.0000
0
0
);
--secondary
:
oklch
(
0.9245
0.0138
92.9892
);
--secondary-foreground
:
oklch
(
0.4334
0.0177
98.6048
);
--muted
:
oklch
(
0.9341
0.0153
90.2390
);
--muted-foreground
:
oklch
(
0.6059
0.0075
97.4233
);
--accent
:
oklch
(
0.9245
0.0138
92.9892
);
--accent-foreground
:
oklch
(
0.2671
0.0196
98.9390
);
--destructive
:
oklch
(
0.1908
0.0020
106.5859
);
--destructive-foreground
:
oklch
(
1.0000
0
0
);
--border
:
oklch
(
0.8847
0.0069
97.3627
);
--input
:
oklch
(
0.7621
0.0156
98.3528
);
--ring
:
oklch
(
0.5937
0.1673
253.0630
);
--chart-1
:
oklch
(
0.5583
0.1276
42.9956
);
--chart-2
:
oklch
(
0.6898
0.1581
290.4107
);
--chart-3
:
oklch
(
0.8816
0.0276
93.1280
);
--chart-4
:
oklch
(
0.8822
0.0403
298.1792
);
--chart-5
:
oklch
(
0.5608
0.1348
42.0584
);
--sidebar
:
oklch
(
0.9663
0.0080
98.8792
);
--sidebar-foreground
:
oklch
(
0.3590
0.0051
106.6524
);
--sidebar-primary
:
oklch
(
0.6171
0.1375
39.0427
);
--sidebar-primary-foreground
:
oklch
(
0.9881
0
0
);
--sidebar-accent
:
oklch
(
0.9245
0.0138
92.9892
);
--sidebar-accent-foreground
:
oklch
(
0.3250
0
0
);
--sidebar-border
:
oklch
(
0.9401
0
0
);
--sidebar-ring
:
oklch
(
0.7731
0
0
);
}
.dark
{
--background
:
oklch
(
0.141
0.005
285.823
);
--foreground
:
oklch
(
0.985
0
0
);
--card
:
oklch
(
0.21
0.006
285.885
);
--card-foreground
:
oklch
(
0.985
0
0
);
--popover
:
oklch
(
0.21
0.006
285.885
);
--popover-foreground
:
oklch
(
0.985
0
0
);
--primary
:
oklch
(
0.92
0.004
286.32
);
--primary-foreground
:
oklch
(
0.21
0.006
285.885
);
--secondary
:
oklch
(
0.274
0.006
286.033
);
--secondary-foreground
:
oklch
(
0.985
0
0
);
--muted
:
oklch
(
0.274
0.006
286.033
);
--muted-foreground
:
oklch
(
0.705
0.015
286.067
);
--accent
:
oklch
(
0.274
0.006
286.033
);
--accent-foreground
:
oklch
(
0.985
0
0
);
--destructive
:
oklch
(
0.704
0.191
22.216
);
--border
:
oklch
(
1
0
0
/
10%
);
--input
:
oklch
(
1
0
0
/
15%
);
--ring
:
oklch
(
0.552
0.016
285.938
);
--chart-1
:
oklch
(
0.488
0.243
264.376
);
--chart-2
:
oklch
(
0.696
0.17
162.48
);
--chart-3
:
oklch
(
0.769
0.188
70.08
);
--chart-4
:
oklch
(
0.627
0.265
303.9
);
--chart-5
:
oklch
(
0.645
0.246
16.439
);
--sidebar
:
oklch
(
0.21
0.006
285.885
);
--sidebar-foreground
:
oklch
(
0.985
0
0
);
--sidebar-primary
:
oklch
(
0.488
0.243
264.376
);
--sidebar-primary-foreground
:
oklch
(
0.985
0
0
);
--sidebar-accent
:
oklch
(
0.274
0.006
286.033
);
--sidebar-accent-foreground
:
oklch
(
0.985
0
0
);
--sidebar-border
:
oklch
(
1
0
0
/
10%
);
--sidebar-ring
:
oklch
(
0.552
0.016
285.938
);
--background
:
oklch
(
0.2679
0.0036
106.6427
);
--foreground
:
oklch
(
0.8074
0.0142
93.0137
);
--card
:
oklch
(
0.2679
0.0036
106.6427
);
--card-foreground
:
oklch
(
0.9818
0.0054
95.0986
);
--popover
:
oklch
(
0.3085
0.0035
106.6039
);
--popover-foreground
:
oklch
(
0.9211
0.0040
106.4781
);
--primary
:
oklch
(
0.6724
0.1308
38.7559
);
--primary-foreground
:
oklch
(
1.0000
0
0
);
--secondary
:
oklch
(
0.9818
0.0054
95.0986
);
--secondary-foreground
:
oklch
(
0.3085
0.0035
106.6039
);
--muted
:
oklch
(
0.2213
0.0038
106.7070
);
--muted-foreground
:
oklch
(
0.7713
0.0169
99.0657
);
--accent
:
oklch
(
0.2130
0.0078
95.4245
);
--accent-foreground
:
oklch
(
0.9663
0.0080
98.8792
);
--destructive
:
oklch
(
0.6368
0.2078
25.3313
);
--destructive-foreground
:
oklch
(
1.0000
0
0
);
--border
:
oklch
(
0.3618
0.0101
106.8928
);
--input
:
oklch
(
0.4336
0.0113
100.2195
);
--ring
:
oklch
(
0.5937
0.1673
253.0630
);
--chart-1
:
oklch
(
0.5583
0.1276
42.9956
);
--chart-2
:
oklch
(
0.6898
0.1581
290.4107
);
--chart-3
:
oklch
(
0.2130
0.0078
95.4245
);
--chart-4
:
oklch
(
0.3074
0.0516
289.3230
);
--chart-5
:
oklch
(
0.5608
0.1348
42.0584
);
--sidebar
:
oklch
(
0.2357
0.0024
67.7077
);
--sidebar-foreground
:
oklch
(
0.8074
0.0142
93.0137
);
--sidebar-primary
:
oklch
(
0.3250
0
0
);
--sidebar-primary-foreground
:
oklch
(
0.9881
0
0
);
--sidebar-accent
:
oklch
(
0.1680
0.0020
106.6177
);
--sidebar-accent-foreground
:
oklch
(
0.8074
0.0142
93.0137
);
--sidebar-border
:
oklch
(
0.9401
0
0
);
--sidebar-ring
:
oklch
(
0.7731
0
0
);
}
@layer
base
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment