From de5ebbc4422b458c685a653b8b8fbaac6e6af5f4 Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Sun, 23 Nov 2025 11:02:27 +0000
Subject: feat: Add notes feature to highlights (#2154)

* feat: Add note-taking functionality to highlights

This commit adds the ability to add and edit notes on highlights, allowing users to capture their thoughts alongside highlighted text.

Changes:
- Updated zUpdateHighlightSchema to include optional note field
- Modified Highlight.update() method to persist notes to database
- Added note button (MessageSquare icon) beside color picker in highlight menu
- Implemented note dialog with textarea for adding/editing notes
- Updated Highlight interface to include optional note field
- Modified ReaderView to pass notes through create and update operations
- Enhanced HighlightCard to display notes below highlighted text

The note button appears alongside the color picker for both new and existing highlights. Notes are displayed in a smaller, muted font below the highlighted text in the HighlightCard component.

* refactor: Convert highlight UI to inline form

Changed the highlight creation/editing interface from a modal dialog to an inline form for a more streamlined user experience.

Changes:
- Replaced ColorPickerMenu and Dialog with a unified HighlightForm component
- Form now displays color selector and note textarea together inline
- Added labels for "Color" and "Note" sections
- Textarea is now optional and inline (placeholder: "Add a note (optional)...")
- Consolidated Save and Cancel buttons in the form
- Delete button appears only for existing highlights
- Removed MessageSquare icon - notes are now always visible in the form
- Simplified state management by removing separate dialog state

The form appears in a popover when text is selected or an existing highlight is clicked, showing both color options and note input in a single 320px wide form.

* fixes

---------

Co-authored-by: Claude <noreply@anthropic.com>
---
 .../dashboard/highlights/HighlightCard.tsx          | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

(limited to 'apps/web/components/dashboard/highlights/HighlightCard.tsx')

diff --git a/apps/web/components/dashboard/highlights/HighlightCard.tsx b/apps/web/components/dashboard/highlights/HighlightCard.tsx
index 1bba0b47..51421e0f 100644
--- a/apps/web/components/dashboard/highlights/HighlightCard.tsx
+++ b/apps/web/components/dashboard/highlights/HighlightCard.tsx
@@ -44,16 +44,24 @@ export default function HighlightCard({
       });
   };
 
-  const Wrapper = ({ children }: { children: React.ReactNode }) =>
+  const Wrapper = ({
+    className,
+    children,
+  }: {
+    className?: string;
+    children: React.ReactNode;
+  }) =>
     clickable ? (
-      <button onClick={onBookmarkClick}>{children}</button>
+      <button className={className} onClick={onBookmarkClick}>
+        {children}
+      </button>
     ) : (
-      <div>{children}</div>
+      <div className={className}>{children}</div>
     );
 
   return (
     <div className={cn("flex items-center justify-between", className)}>
-      <Wrapper>
+      <Wrapper className="flex flex-col gap-2 text-left">
         <blockquote
           cite={highlight.bookmarkId}
           className={cn(
@@ -63,6 +71,11 @@ export default function HighlightCard({
         >
           <p>{highlight.text}</p>
         </blockquote>
+        {highlight.note && (
+          <span className="text-sm text-muted-foreground">
+            {highlight.note}
+          </span>
+        )}
       </Wrapper>
       {!readOnly && (
         <div className="flex gap-2">
-- 
cgit v1.2.3-70-g09d2

