From 33f407797213c56dd2f13e98228a5305efdf90fd Mon Sep 17 00:00:00 2001
From: xuatz <xzlow10@gmail.com>
Date: Mon, 3 Nov 2025 04:32:18 +0900
Subject: feat: display notes on bookmark card (#2083)

* feat: display notes on bookmark card

* apply styling

* include mobile impl

* apply pr comments

* add display options menu into PR

* put it under app setting

* cleanup

* address pr comments

* change the default for show notes to false

* make the in-card note font lighter

---------

Co-authored-by: Mohamed Bassem <me@mbassem.com>
---
 .../components/dashboard/bookmarks/NotePreview.tsx | 66 ++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 apps/web/components/dashboard/bookmarks/NotePreview.tsx

(limited to 'apps/web/components/dashboard/bookmarks/NotePreview.tsx')

diff --git a/apps/web/components/dashboard/bookmarks/NotePreview.tsx b/apps/web/components/dashboard/bookmarks/NotePreview.tsx
new file mode 100644
index 00000000..c32c85a3
--- /dev/null
+++ b/apps/web/components/dashboard/bookmarks/NotePreview.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import { useState } from "react";
+import Link from "next/link";
+import { Button } from "@/components/ui/button";
+import {
+  Popover,
+  PopoverContent,
+  PopoverTrigger,
+} from "@/components/ui/popover";
+import { useTranslation } from "@/lib/i18n/client";
+import { cn } from "@/lib/utils";
+import { ExternalLink, NotepadText } from "lucide-react";
+
+interface NotePreviewProps {
+  note: string;
+  bookmarkId: string;
+  className?: string;
+}
+
+export function NotePreview({ note, bookmarkId, className }: NotePreviewProps) {
+  const { t } = useTranslation();
+  const [isOpen, setIsOpen] = useState(false);
+
+  if (!note?.trim()) {
+    return null;
+  }
+
+  return (
+    <Popover open={isOpen} onOpenChange={setIsOpen}>
+      <PopoverTrigger asChild>
+        <div
+          className={cn(
+            "flex cursor-pointer items-center gap-1.5 text-sm font-light italic text-gray-500 dark:text-gray-400",
+            className,
+          )}
+        >
+          <NotepadText className="size-5 shrink-0" />
+          <div className="line-clamp-2 min-w-0 flex-1 overflow-hidden text-wrap break-words">
+            {note}
+          </div>
+        </div>
+      </PopoverTrigger>
+      <PopoverContent className="w-96 max-w-[calc(100vw-2rem)]" align="start">
+        <div className="space-y-3">
+          <div className="max-h-60 overflow-y-auto whitespace-pre-wrap break-words text-sm text-gray-700 dark:text-gray-300">
+            {note}
+          </div>
+          <div className="flex justify-end">
+            <Link href={`/dashboard/preview/${bookmarkId}`}>
+              <Button
+                variant="outline"
+                size="sm"
+                className="gap-2"
+                onClick={() => setIsOpen(false)}
+              >
+                {t("actions.edit_notes")}
+                <ExternalLink className="size-4" />
+              </Button>
+            </Link>
+          </div>
+        </div>
+      </PopoverContent>
+    </Popover>
+  );
+}
-- 
cgit v1.2.3-70-g09d2

