aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMaheshtheDev <[email protected]>2025-10-03 07:51:00 +0000
committerMaheshtheDev <[email protected]>2025-10-03 07:51:00 +0000
commit56590e93297a1e25304a7fd1b255d26386bb3b71 (patch)
tree38761295561f8887f166b2bd2f3ddd99014b8446 /apps
parentfeat(raycast-extension): initial version of supermemory extension for raycast... (diff)
downloadsupermemory-56590e93297a1e25304a7fd1b255d26386bb3b71.tar.xz
supermemory-56590e93297a1e25304a7fd1b255d26386bb3b71.zip
feat: delete memories and theme issues across the app (#449)10-02-fix_ui_theme_issues_across_the_app
# Add document deletion functionality and fix UI theme issues This PR adds the ability to delete documents and their associated memories across all content card types (Google Docs, Notes, Tweets, and Websites). Each card now includes: - A delete button that appears on hover - A confirmation dialog to prevent accidental deletions - Proper event handling to avoid triggering card clicks when using delete controls Additionally, this PR fixes various UI theme issues: - Updates button styling in the ActionButtons component - Improves theme consistency by replacing hardcoded colors with theme variables - Fixes text color issues in login page components - Ensures proper color contrast in various UI elements The masonry layout was also improved to properly re-render when documents are removed.
Diffstat (limited to 'apps')
-rw-r--r--apps/web/components/content-cards/google-docs.tsx88
-rw-r--r--apps/web/components/content-cards/note.tsx96
-rw-r--r--apps/web/components/content-cards/tweet.tsx66
-rw-r--r--apps/web/components/content-cards/website.tsx88
-rw-r--r--apps/web/components/masonry-memory-list.tsx8
-rw-r--r--apps/web/components/views/add-memory/action-buttons.tsx118
-rw-r--r--apps/web/components/views/add-memory/index.tsx7
7 files changed, 361 insertions, 110 deletions
diff --git a/apps/web/components/content-cards/google-docs.tsx b/apps/web/components/content-cards/google-docs.tsx
index 22f06f77..0306876d 100644
--- a/apps/web/components/content-cards/google-docs.tsx
+++ b/apps/web/components/content-cards/google-docs.tsx
@@ -2,8 +2,18 @@
import { Card, CardContent } from "@repo/ui/components/card"
import { Badge } from "@repo/ui/components/badge"
-import { ExternalLink, FileText, Brain } from "lucide-react"
-import { useState } from "react"
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@repo/ui/components/alert-dialog"
+import { ExternalLink, FileText, Brain, Trash2 } from "lucide-react"
import { cn } from "@lib/utils"
import { colors } from "@repo/ui/memory-graph/constants"
import { getPastelBackgroundColor } from "../memories-utils"
@@ -14,6 +24,7 @@ interface GoogleDocsCardProps {
description?: string | null
className?: string
onClick?: () => void
+ onDelete?: () => void
showExternalLink?: boolean
activeMemories?: Array<{ id: string; isForgotten?: boolean }>
lastModified?: string | Date
@@ -25,12 +36,11 @@ export const GoogleDocsCard = ({
description,
className,
onClick,
+ onDelete,
showExternalLink = true,
activeMemories,
lastModified,
}: GoogleDocsCardProps) => {
- const [imageError, setImageError] = useState(false)
-
const handleCardClick = () => {
if (onClick) {
onClick()
@@ -57,6 +67,54 @@ export const GoogleDocsCard = ({
backgroundColor: getPastelBackgroundColor(url || title || "googledocs"),
}}
>
+ {onDelete && (
+ <AlertDialog>
+ <AlertDialogTrigger asChild>
+ <button
+ className="absolute top-2 right-2 z-20 opacity-0 group-hover:opacity-100 transition-opacity p-1.5 rounded-md hover:bg-red-500/20"
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ style={{
+ color: colors.text.muted,
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
+ backdropFilter: "blur(4px)",
+ }}
+ type="button"
+ >
+ <Trash2 className="w-3.5 h-3.5" />
+ </button>
+ </AlertDialogTrigger>
+ <AlertDialogContent>
+ <AlertDialogHeader>
+ <AlertDialogTitle>Delete Document</AlertDialogTitle>
+ <AlertDialogDescription>
+ Are you sure you want to delete this document and all its
+ related memories? This action cannot be undone.
+ </AlertDialogDescription>
+ </AlertDialogHeader>
+ <AlertDialogFooter>
+ <AlertDialogCancel
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ >
+ Cancel
+ </AlertDialogCancel>
+ <AlertDialogAction
+ className="bg-red-600 hover:bg-red-700 text-white"
+ onClick={(e) => {
+ e.stopPropagation()
+ onDelete()
+ }}
+ >
+ Delete
+ </AlertDialogAction>
+ </AlertDialogFooter>
+ </AlertDialogContent>
+ </AlertDialog>
+ )}
+
<CardContent className="p-0">
<div className="px-4 border-b border-white/10">
<div className="flex items-center justify-between">
@@ -99,16 +157,18 @@ export const GoogleDocsCard = ({
</span>
</div>
</div>
- {showExternalLink && (
- <button
- onClick={handleExternalLinkClick}
- className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-white/10 flex-shrink-0"
- type="button"
- aria-label="Open in Google Docs"
- >
- <ExternalLink className="w-4 h-4" />
- </button>
- )}
+ <div className="flex items-center gap-1">
+ {showExternalLink && (
+ <button
+ onClick={handleExternalLinkClick}
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-white/10 flex-shrink-0"
+ type="button"
+ aria-label="Open in Google Docs"
+ >
+ <ExternalLink className="w-4 h-4" />
+ </button>
+ )}
+ </div>
</div>
</div>
diff --git a/apps/web/components/content-cards/note.tsx b/apps/web/components/content-cards/note.tsx
index e7703d9b..b0014bf6 100644
--- a/apps/web/components/content-cards/note.tsx
+++ b/apps/web/components/content-cards/note.tsx
@@ -1,8 +1,19 @@
import { Badge } from "@repo/ui/components/badge"
import { Card, CardContent, CardHeader } from "@repo/ui/components/card"
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@repo/ui/components/alert-dialog"
import { colors } from "@repo/ui/memory-graph/constants"
-import { Brain, ExternalLink } from "lucide-react"
+import { Brain, ExternalLink, Trash2 } from "lucide-react"
import { cn } from "@lib/utils"
import {
formatDate,
@@ -32,6 +43,7 @@ export const NoteCard = ({
activeMemories,
forgottenMemories,
onOpenDetails,
+ onDelete,
}: NoteCardProps) => {
return (
<Card
@@ -47,6 +59,52 @@ export const NoteCard = ({
width: width,
}}
>
+ <AlertDialog>
+ <AlertDialogTrigger asChild>
+ <button
+ className="absolute top-2 right-2 z-20 opacity-0 group-hover:opacity-100 group-hover:cursor-pointer transition-opacity p-1.5 rounded-md hover:bg-red-500/20"
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ style={{
+ color: colors.text.muted,
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
+ backdropFilter: "blur(4px)",
+ }}
+ type="button"
+ >
+ <Trash2 className="w-3.5 h-3.5" />
+ </button>
+ </AlertDialogTrigger>
+ <AlertDialogContent>
+ <AlertDialogHeader>
+ <AlertDialogTitle>Delete Document</AlertDialogTitle>
+ <AlertDialogDescription>
+ Are you sure you want to delete this document and all its related
+ memories? This action cannot be undone.
+ </AlertDialogDescription>
+ </AlertDialogHeader>
+ <AlertDialogFooter>
+ <AlertDialogCancel
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ >
+ Cancel
+ </AlertDialogCancel>
+ <AlertDialogAction
+ className="bg-red-600 hover:bg-red-700 text-white"
+ onClick={(e) => {
+ e.stopPropagation()
+ onDelete(document)
+ }}
+ >
+ Delete
+ </AlertDialogAction>
+ </AlertDialogFooter>
+ </AlertDialogContent>
+ </AlertDialog>
+
<CardHeader className="relative z-10 px-0 pb-0">
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-1">
@@ -59,23 +117,25 @@ export const NoteCard = ({
{document.title || "Untitled Document"}
</p>
</div>
- {document.url && (
- <button
- className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded"
- onClick={(e) => {
- e.stopPropagation()
- const sourceUrl = getSourceUrl(document)
- window.open(sourceUrl ?? undefined, "_blank")
- }}
- style={{
- backgroundColor: "rgba(255, 255, 255, 0.05)",
- color: colors.text.secondary,
- }}
- type="button"
- >
- <ExternalLink className="w-3 h-3" />
- </button>
- )}
+ <div className="flex items-center gap-1">
+ {document.url && (
+ <button
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded"
+ onClick={(e) => {
+ e.stopPropagation()
+ const sourceUrl = getSourceUrl(document)
+ window.open(sourceUrl ?? undefined, "_blank")
+ }}
+ style={{
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ color: colors.text.secondary,
+ }}
+ type="button"
+ >
+ <ExternalLink className="w-3 h-3" />
+ </button>
+ )}
+ </div>
<div className="flex items-center gap-2 text-[10px] text-muted-foreground">
<span>{formatDate(document.createdAt)}</span>
</div>
diff --git a/apps/web/components/content-cards/tweet.tsx b/apps/web/components/content-cards/tweet.tsx
index 3f46d6cc..34db9eb5 100644
--- a/apps/web/components/content-cards/tweet.tsx
+++ b/apps/web/components/content-cards/tweet.tsx
@@ -14,7 +14,18 @@ import {
enrichTweet,
} from "react-tweet"
import { Badge } from "@repo/ui/components/badge"
-import { Brain } from "lucide-react"
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@repo/ui/components/alert-dialog"
+import { Brain, Trash2 } from "lucide-react"
import { colors } from "@repo/ui/memory-graph/constants"
import { getPastelBackgroundColor } from "../memories-utils"
@@ -71,18 +82,69 @@ const CustomTweet = ({
export const TweetCard = ({
data,
activeMemories,
+ onDelete,
}: {
data: Tweet
activeMemories?: Array<{ id: string; isForgotten?: boolean }>
+ onDelete?: () => void
}) => {
return (
<div
- className="relative transition-all"
+ className="relative transition-all group"
style={{
backgroundColor: getPastelBackgroundColor(data.id_str || "tweet"),
}}
>
<CustomTweet components={{}} tweet={data} />
+
+ {onDelete && (
+ <AlertDialog>
+ <AlertDialogTrigger asChild>
+ <button
+ className="absolute top-2 right-2 z-20 opacity-0 group-hover:opacity-100 transition-opacity p-1.5 rounded-md hover:bg-red-500/20"
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ style={{
+ color: colors.text.muted,
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
+ backdropFilter: "blur(4px)",
+ }}
+ type="button"
+ >
+ <Trash2 className="w-3.5 h-3.5" />
+ </button>
+ </AlertDialogTrigger>
+ <AlertDialogContent>
+ <AlertDialogHeader>
+ <AlertDialogTitle>Delete Document</AlertDialogTitle>
+ <AlertDialogDescription>
+ Are you sure you want to delete this document and all its
+ related memories? This action cannot be undone.
+ </AlertDialogDescription>
+ </AlertDialogHeader>
+ <AlertDialogFooter>
+ <AlertDialogCancel
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ >
+ Cancel
+ </AlertDialogCancel>
+ <AlertDialogAction
+ className="bg-red-600 hover:bg-red-700 text-white"
+ onClick={(e) => {
+ e.stopPropagation()
+ onDelete()
+ }}
+ >
+ Delete
+ </AlertDialogAction>
+ </AlertDialogFooter>
+ </AlertDialogContent>
+ </AlertDialog>
+ )}
+
{activeMemories && activeMemories.length > 0 && (
<div className="absolute bottom-2 left-4 z-10">
<Badge
diff --git a/apps/web/components/content-cards/website.tsx b/apps/web/components/content-cards/website.tsx
index f36cd247..b3ee7df6 100644
--- a/apps/web/components/content-cards/website.tsx
+++ b/apps/web/components/content-cards/website.tsx
@@ -1,10 +1,22 @@
"use client"
import { Card, CardContent } from "@repo/ui/components/card"
-import { ExternalLink } from "lucide-react"
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@repo/ui/components/alert-dialog"
+import { ExternalLink, Trash2 } from "lucide-react"
import { useState } from "react"
import { cn } from "@lib/utils"
import { getPastelBackgroundColor } from "../memories-utils"
+import { colors } from "@repo/ui/memory-graph/constants"
interface WebsiteCardProps {
title: string
@@ -13,6 +25,7 @@ interface WebsiteCardProps {
description?: string
className?: string
onClick?: () => void
+ onDelete?: () => void
showExternalLink?: boolean
}
@@ -23,6 +36,7 @@ export const WebsiteCard = ({
description,
className,
onClick,
+ onDelete,
showExternalLink = true,
}: WebsiteCardProps) => {
const [imageError, setImageError] = useState(false)
@@ -51,7 +65,7 @@ export const WebsiteCard = ({
return (
<Card
className={cn(
- "cursor-pointer transition-all hover:shadow-md group overflow-hidden py-0",
+ "cursor-pointer transition-all hover:shadow-md group overflow-hidden py-0 relative",
className,
)}
onClick={handleCardClick}
@@ -59,6 +73,54 @@ export const WebsiteCard = ({
backgroundColor: getPastelBackgroundColor(url || title || "website"),
}}
>
+ {onDelete && (
+ <AlertDialog>
+ <AlertDialogTrigger asChild>
+ <button
+ className="absolute top-2 right-2 z-20 opacity-0 group-hover:opacity-100 transition-opacity p-1.5 rounded-md hover:bg-red-500/20"
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ style={{
+ color: colors.text.muted,
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
+ backdropFilter: "blur(4px)",
+ }}
+ type="button"
+ >
+ <Trash2 className="w-3.5 h-3.5" />
+ </button>
+ </AlertDialogTrigger>
+ <AlertDialogContent>
+ <AlertDialogHeader>
+ <AlertDialogTitle>Delete Document</AlertDialogTitle>
+ <AlertDialogDescription>
+ Are you sure you want to delete this document and all its
+ related memories? This action cannot be undone.
+ </AlertDialogDescription>
+ </AlertDialogHeader>
+ <AlertDialogFooter>
+ <AlertDialogCancel
+ onClick={(e) => {
+ e.stopPropagation()
+ }}
+ >
+ Cancel
+ </AlertDialogCancel>
+ <AlertDialogAction
+ className="bg-red-600 hover:bg-red-700 text-white"
+ onClick={(e) => {
+ e.stopPropagation()
+ onDelete()
+ }}
+ >
+ Delete
+ </AlertDialogAction>
+ </AlertDialogFooter>
+ </AlertDialogContent>
+ </AlertDialog>
+ )}
+
<CardContent className="p-0">
{image && !imageError && (
<div className="relative h-38 bg-gray-100 overflow-hidden">
@@ -75,16 +137,18 @@ export const WebsiteCard = ({
<div className="px-4 py-2 space-y-2">
<div className="font-semibold text-sm line-clamp-2 leading-tight flex items-center justify-between">
{title}
- {showExternalLink && (
- <button
- onClick={handleExternalLinkClick}
- className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-gray-100 flex-shrink-0"
- type="button"
- aria-label="Open in new tab"
- >
- <ExternalLink className="w-3 h-3" />
- </button>
- )}
+ <div className="flex items-center gap-1">
+ {showExternalLink && (
+ <button
+ onClick={handleExternalLinkClick}
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-gray-100 flex-shrink-0"
+ type="button"
+ aria-label="Open in new tab"
+ >
+ <ExternalLink className="w-3 h-3" />
+ </button>
+ )}
+ </div>
</div>
{description && (
diff --git a/apps/web/components/masonry-memory-list.tsx b/apps/web/components/masonry-memory-list.tsx
index 2f634f74..93326e49 100644
--- a/apps/web/components/masonry-memory-list.tsx
+++ b/apps/web/components/masonry-memory-list.tsx
@@ -63,6 +63,7 @@ const DocumentCard = memo(
description={document.content}
activeMemories={activeMemories}
lastModified={document.updatedAt || document.createdAt}
+ onDelete={() => onDelete(document)}
/>
)
}
@@ -77,6 +78,7 @@ const DocumentCard = memo(
document.metadata?.sm_internal_twitter_metadata as unknown as Tweet
}
activeMemories={activeMemories}
+ onDelete={() => onDelete(document)}
/>
)
}
@@ -87,6 +89,7 @@ const DocumentCard = memo(
url={document.url}
title={document.title || "Untitled Document"}
image={document.ogImage}
+ onDelete={() => onDelete(document)}
/>
)
}
@@ -212,9 +215,7 @@ export const MasonryMemoryList = ({
) : isLoading ? (
<div className="h-full flex items-center justify-center p-4">
<div className="rounded-xl overflow-hidden">
- <div
- className="relative z-10 px-6 py-4"
- >
+ <div className="relative z-10 px-6 py-4">
<div className="flex items-center gap-2">
<Sparkles className="w-4 h-4 animate-spin text-blue-400" />
<span>Loading memory list...</span>
@@ -232,6 +233,7 @@ export const MasonryMemoryList = ({
data-theme="light"
>
<Masonry
+ key={`masonry-${filteredDocuments.length}-${filteredDocuments.map((d) => d.id).join(",")}`}
items={filteredDocuments}
render={renderDocumentCard}
columnGutter={16}
diff --git a/apps/web/components/views/add-memory/action-buttons.tsx b/apps/web/components/views/add-memory/action-buttons.tsx
index fc901ba9..3f93fe17 100644
--- a/apps/web/components/views/add-memory/action-buttons.tsx
+++ b/apps/web/components/views/add-memory/action-buttons.tsx
@@ -1,67 +1,67 @@
-import { Button } from '@repo/ui/components/button';
-import { Loader2, type LucideIcon } from 'lucide-react';
-import { motion } from 'motion/react';
+import { Button } from "@repo/ui/components/button"
+import { Loader2, type LucideIcon } from "lucide-react"
+import { motion } from "motion/react"
interface ActionButtonsProps {
- onCancel: () => void;
- onSubmit?: () => void;
- submitText: string;
- submitIcon?: LucideIcon;
- isSubmitting?: boolean;
- isSubmitDisabled?: boolean;
- submitType?: 'button' | 'submit';
- className?: string;
+ onCancel: () => void
+ onSubmit?: () => void
+ submitText: string
+ submitIcon?: LucideIcon
+ isSubmitting?: boolean
+ isSubmitDisabled?: boolean
+ submitType?: "button" | "submit"
+ className?: string
}
export function ActionButtons({
- onCancel,
- onSubmit,
- submitText,
- submitIcon: SubmitIcon,
- isSubmitting = false,
- isSubmitDisabled = false,
- submitType = 'submit',
- className = '',
+ onCancel,
+ onSubmit,
+ submitText,
+ submitIcon: SubmitIcon,
+ isSubmitting = false,
+ isSubmitDisabled = false,
+ submitType = "submit",
+ className = "",
}: ActionButtonsProps) {
- return (
- <div className={`flex gap-3 order-1 sm:order-2 justify-end ${className}`}>
- <Button
- className="hover:bg-foreground/10 border-none flex-1 sm:flex-initial"
- onClick={onCancel}
- type="button"
- variant="ghost"
- >
- Cancel
- </Button>
+ return (
+ <div className={`flex gap-3 order-1 sm:order-2 justify-end ${className}`}>
+ <Button
+ className="hover:bg-foreground/10 border-none flex-1 sm:flex-initial"
+ onClick={onCancel}
+ type="button"
+ variant="ghost"
+ >
+ Cancel
+ </Button>
- <motion.div
- whileHover={{ scale: 1.05 }}
- whileTap={{ scale: 0.95 }}
- className="flex-1 sm:flex-initial"
- >
- <Button
- className="bg-foreground hover:bg-foreground/20 border-foreground/20 w-full"
- disabled={isSubmitting || isSubmitDisabled}
- onClick={submitType === 'button' ? onSubmit : undefined}
- type={submitType}
- >
- {isSubmitting ? (
- <>
- <Loader2 className="h-4 w-4 animate-spin mr-2" />
- {submitText.includes('Add')
- ? 'Adding...'
- : submitText.includes('Upload')
- ? 'Uploading...'
- : 'Processing...'}
- </>
- ) : (
- <>
- {SubmitIcon && <SubmitIcon className="h-4 w-4 mr-2" />}
- {submitText}
- </>
- )}
- </Button>
- </motion.div>
- </div>
- );
+ <motion.div
+ whileHover={{ scale: 1.05 }}
+ whileTap={{ scale: 0.95 }}
+ className="flex-1 sm:flex-initial"
+ >
+ <Button
+ className="w-full"
+ disabled={isSubmitting || isSubmitDisabled}
+ onClick={submitType === "button" ? onSubmit : undefined}
+ type={submitType}
+ >
+ {isSubmitting ? (
+ <>
+ <Loader2 className="h-4 w-4 animate-spin mr-2" />
+ {submitText.includes("Add")
+ ? "Adding..."
+ : submitText.includes("Upload")
+ ? "Uploading..."
+ : "Processing..."}
+ </>
+ ) : (
+ <>
+ {SubmitIcon && <SubmitIcon className="h-4 w-4 mr-2" />}
+ {submitText}
+ </>
+ )}
+ </Button>
+ </motion.div>
+ </div>
+ )
}
diff --git a/apps/web/components/views/add-memory/index.tsx b/apps/web/components/views/add-memory/index.tsx
index a78e7629..d9c6aef8 100644
--- a/apps/web/components/views/add-memory/index.tsx
+++ b/apps/web/components/views/add-memory/index.tsx
@@ -88,7 +88,10 @@ export function AddMemoryView({
const [newProjectName, setNewProjectName] = useState("")
// Check memory limits
- const { data: memoriesCheck } = fetchMemoriesFeature(autumn, !autumn.isLoading)
+ const { data: memoriesCheck } = fetchMemoriesFeature(
+ autumn,
+ !autumn.isLoading,
+ )
const memoriesUsed = memoriesCheck?.usage ?? 0
const memoriesLimit = memoriesCheck?.included_usage ?? 0
@@ -757,7 +760,7 @@ export function AddMemoryView({
{({ state, handleChange, handleBlur }) => (
<>
<Input
- className={`bg-black/5 border-black/10 text-black ${
+ className={`bg-black/5 border-black/10 ${
addContentMutation.isPending ? "opacity-50" : ""
}`}
disabled={addContentMutation.isPending}