Skip to content

Conversation

@chmurson
Copy link
Collaborator

@chmurson chmurson commented Oct 22, 2025

Screenshot 2025-10-22 at 22 43 53 Screenshot 2025-10-22 at 22 44 14

Summary by CodeRabbit

  • New Features

    • Notes now highlight as "active" based on your current selection location
    • Enhanced interactive note editing with expanded layout for selected notes
    • Added dark mode styling support for notes
  • Style

    • Refactored note and navigation link styling for improved consistency
    • Introduced CSS variables for better theme management
  • Tests

    • Improved snapshot tests with better timing and visual assertions

@netlify
Copy link

netlify bot commented Oct 22, 2025

Deploy Preview for graypaper-reader ready!

Name Link
🔨 Latest commit 9be8c3f
🔍 Latest deploy log https://app.netlify.com/projects/graypaper-reader/deploys/68f95688b5b6a2000865eaa0
😎 Deploy Preview https://deploy-preview-330--graypaper-reader.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2025

Caution

Review failed

The pull request is closed.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Activation note logic change” succinctly captures the primary change of updating how notes become active based on selection state, directly reflecting the main feature introduced in the diffs without extraneous details. It is concise, avoids generic terms or file references, and clearly signals to reviewers that the pull request focuses on modifying note activation logic.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a8d3689 and 9be8c3f.

📒 Files selected for processing (2)
  • src/components/LocationProvider/LocationProvider.tsx (1 hunks)
  • src/components/NoteManager/components/Note.tsx (3 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 22, 2025

Visual Regression Test Report ✅ Passed

Github run id: 18731281973

🔗 Artifacts: Download

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (7)
src/components/NoteManager/NoteManager.css (1)

1-9: Verify CSS variables are actually used in the component.

The CSS variables --inactive-note-bg and --active-note-bg are defined here but don't appear to be referenced anywhere in this CSS file. Confirm they're being consumed via inline styles or the component's JavaScript before merging.

Additionally, consider consolidating the dark mode approach: this file mixes CSS variables with .dark selector (lines 6–9) and light-dark() function elsewhere (lines 62, 66). For consistency, choose one strategy—either use light-dark() throughout or use the variable approach everywhere.

src/components/Outline/OutlineLink.tsx (1)

32-51: Reduce code duplication between firstLevel branches.

The two conditional branches differ only in border color classes. Consider consolidating this logic to improve maintainability.

Apply this diff to eliminate duplication:

-      {firstLevel && (
-        <>
-          {number != null && (
-            <>
-              <span>{number}</span>&nbsp;
-            </>
-          )}
-          <span className="border-b-1 dark:border-brand/50 border-brand-darkest/50">{title}</span>
-        </>
-      )}
-      {!firstLevel && (
-        <>
-          {number != null && (
-            <>
-              <span>{number}</span>&nbsp;
-            </>
-          )}
-          <span className="border-b-1 dark:border-brand-light/50 border-brand-dark/50">{title}</span>
-        </>
-      )}
+      {number != null && (
+        <>
+          <span>{number}</span>&nbsp;
+        </>
+      )}
+      <span
+        className={twMerge(
+          "border-b",
+          firstLevel && "dark:border-brand/50 border-brand-darkest/50",
+          !firstLevel && "dark:border-brand-light/50 border-brand-dark/50",
+        )}
+      >
+        {title}
+      </span>
src/components/NoteManager/components/NoteLink.tsx (2)

111-111: Avoid trailing space in title.

The title construction may produce a trailing space when subSection is an empty string (not just null). Consider trimming the result.

Apply this diff:

-        title={`${section} ${subSection ? `${subSection} ` : ""}`}
+        title={`${section}${subSection ? ` ${subSection}` : ""}`}

112-112: Clarify the semantic purpose of the separator.

The > symbol is appended to the number prop, but it's semantically a separator rather than part of the page number. Consider whether OutlineLink should handle separators internally, or document why this formatting choice was made here versus in Outline.tsx (Line 92) where the separator is handled differently.

src/components/NoteManager/components/NotesList.tsx (1)

25-25: Consider using key-based comparison for robustness.

Using includes() for object comparison relies on reference equality. While this currently works because activeNotes is filtered from the same filteredNotes array, it's fragile—if note objects are ever cloned or recreated, the comparison will fail.

Consider using a key-based lookup for more resilient comparison:

+  const activeNoteKeys = new Set(activeNotes.map(n => n.key));
+
   return (
     <>
       {notes.map((note) => (
         <Note
           key={note.key}
-          active={activeNotes.includes(note)}
+          active={activeNoteKeys.has(note.key)}
           note={note}
           onEditNote={onEditNote}
           onDeleteNote={onDeleteNote}
         />
       ))}
     </>
   );
src/components/NoteManager/components/Note.tsx (2)

156-156: Remove redundant condition check.

The condition !isEditing is redundant here since this code is already inside the active && !isEditing block (line 139).

Apply this diff:

             <NoteLayout.Text />
-            {!isEditing ? <NoteLabels note={note} /> : null}
+            <NoteLabels note={note} />
           </>

159-185: Remove unnecessary double fragment.

The editing branch has a double fragment (<><>) that can be simplified.

Apply this diff:

         {active && isEditing && (
-          <>
-            <>
-              <NoteLink note={note} onEditNote={onEditNote} />
+          <>
+            <NoteLink note={note} onEditNote={onEditNote} />
               <textarea
                 className={noteContentError ? "error" : ""}
                 onChange={handleNoteContentChange}
                 value={noteDirty.content}
                 autoFocus
               />
               {noteContentError ? <div className="validation-message">{noteContentError}</div> : null}
               <NoteLabelsEdit note={note} onNewLabels={handleEditLabels} />
               <div className="actions gap-2">
                 <Button variant="tertiary" intent="destructive" size="sm" onClick={handleDeleteClick}>
                   Delete
                 </Button>
                 <div className="fill" />
                 <Button data-testid={"save-button"} onClick={handleSaveClick} size="sm">
                   Save
                 </Button>
                 <Button variant="secondary" data-testid={"cancel-button"} onClick={handleCancelClick} size="sm">
                   Cancel
                 </Button>
               </div>
-            </>
           </>
         )}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc29529 and eb00133.

📒 Files selected for processing (10)
  • src/components/NoteManager/NoteManager.css (2 hunks)
  • src/components/NoteManager/NoteManager.tsx (3 hunks)
  • src/components/NoteManager/components/Note.tsx (3 hunks)
  • src/components/NoteManager/components/NoteLink.tsx (2 hunks)
  • src/components/NoteManager/components/NotesList.tsx (2 hunks)
  • src/components/NotesProvider/NotesProvider.tsx (3 hunks)
  • src/components/NotesProvider/utils/areSelectionsEqual.ts (1 hunks)
  • src/components/Outline/Outline.tsx (2 hunks)
  • src/components/Outline/OutlineLink.tsx (1 hunks)
  • src/components/Outline/index.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,jsx,ts,tsx}

⚙️ CodeRabbit configuration file

When reviewing Tailwind CSS classes, ensure they follow Tailwind 4.x conventions and suggest modern 4.x alternatives for deprecated patterns.

Files:

  • src/components/Outline/index.ts
  • src/components/NoteManager/components/NoteLink.tsx
  • src/components/Outline/OutlineLink.tsx
  • src/components/NotesProvider/utils/areSelectionsEqual.ts
  • src/components/Outline/Outline.tsx
  • src/components/NotesProvider/NotesProvider.tsx
  • src/components/NoteManager/NoteManager.tsx
  • src/components/NoteManager/components/Note.tsx
  • src/components/NoteManager/components/NotesList.tsx
**/*.css

⚙️ CodeRabbit configuration file

Review CSS code with focus on Tailwind CSS 4.x best practices and conventions. Ensure compatibility with Tailwind 4.x features and syntax.

Files:

  • src/components/NoteManager/NoteManager.css
🧬 Code graph analysis (6)
src/components/NoteManager/components/NoteLink.tsx (2)
src/components/Outline/OutlineLink.tsx (1)
  • OutlineLink (4-54)
src/components/Outline/index.ts (1)
  • OutlineLink (2-2)
src/components/NotesProvider/utils/areSelectionsEqual.ts (1)
shared/links-metadata/src/types.ts (1)
  • ISynctexBlockId (1-4)
src/components/Outline/Outline.tsx (1)
src/components/Outline/OutlineLink.tsx (1)
  • OutlineLink (4-54)
src/components/NotesProvider/NotesProvider.tsx (2)
src/components/NotesProvider/types/DecoratedNote.ts (1)
  • IDecoratedNote (4-19)
src/components/NotesProvider/utils/areSelectionsEqual.ts (1)
  • areSelectionsEqual (8-13)
src/components/NoteManager/components/Note.tsx (7)
src/components/NotesProvider/NotesProvider.tsx (1)
  • INotesContext (20-40)
src/components/NotesProvider/types/DecoratedNote.ts (1)
  • IDecoratedNote (4-19)
src/components/NotesProvider/types/StorageNote.ts (1)
  • IStorageNote (5-5)
src/components/LocationProvider/LocationProvider.tsx (2)
  • LocationContext (29-29)
  • ILocationContext (6-10)
src/components/NoteManager/components/NoteLink.tsx (1)
  • NoteLink (16-131)
src/components/NoteManager/components/NoteLabels.tsx (2)
  • NoteLabels (9-17)
  • NoteLabelsEdit (26-49)
src/components/NoteContent/NoteContent.tsx (1)
  • NoteContent (10-19)
src/components/NoteManager/components/NotesList.tsx (2)
src/components/NotesProvider/types/DecoratedNote.ts (1)
  • IDecoratedNote (4-19)
src/components/NoteManager/components/Note.tsx (1)
  • Note (43-189)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: visual-tests
🔇 Additional comments (10)
src/components/NoteManager/NoteManager.css (1)

11-76: No changes required in existing rules.

The existing CSS appears well-formed and functional. No issues identified in this section.

src/components/NotesProvider/utils/areSelectionsEqual.ts (1)

1-17: LGTM!

The selection comparison logic is straightforward and correct. Both functions properly compare the required fields from ISynctexBlockId interface.

src/components/Outline/index.ts (1)

1-2: LGTM!

Clean module exports aligning with the public API.

src/components/NotesProvider/NotesProvider.tsx (1)

117-123: LGTM!

The activeNotes derivation logic is correct. The guard clause properly handles missing selection params, and the filtering uses the appropriate equality check via areSelectionsEqual.

src/components/NoteManager/NoteManager.tsx (1)

30-30: LGTM!

The integration of activeNotes from context and its propagation to MemoizedNotesList is implemented correctly.

Also applies to: 94-99

src/components/Outline/Outline.tsx (1)

87-93: LGTM!

The migration to OutlineLink is implemented correctly, consolidating the navigation rendering logic.

src/components/NoteManager/components/Note.tsx (4)

1-31: LGTM!

The imports and type definitions are clean and appropriate for the new activation logic.


33-41: LGTM!

The context pattern is well-implemented with appropriate error handling. This avoids prop drilling and keeps the component structure clean.


116-120: LGTM!

Good cleanup logic—resetting the editing state when the note becomes inactive prevents stale edit sessions.


191-205: LGTM!

The NoteText component and NoteLayout pattern are cleanly implemented. The context usage is appropriate and the semantic blockquote element is a good choice for note content.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/components/NoteManager/components/Note.tsx (1)

116-130: Keyboard handler activates on every key and blocks Tab/Arrows; restrict to Enter/Space.

Currently it prevents default for non-activation keys and still navigates. Handle only Enter/Space and prevent scroll only for Space.

-  const handleNoteEnter = (e: React.KeyboardEvent<HTMLDivElement>) => {
-    if (e.key !== "Enter" && e.key !== "Space") {
-      e.preventDefault();
-    }
-
-    if (active) {
-      return;
-    }
-
-    setLocationParams({
-      version: note.original.version,
-      selectionStart: note.original.selectionStart,
-      selectionEnd: note.original.selectionEnd,
-    });
-  };
+  const handleWholeNoteKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
+    // Only activate on Enter or Space; prevent page scroll for Space.
+    if (e.key !== "Enter" && e.key !== " " && e.key !== "Spacebar") {
+      return;
+    }
+    if (e.key === " " || e.key === "Spacebar") {
+      e.preventDefault();
+    }
+    if (active) return;
+    setLocationParams({
+      version: note.original.version,
+      selectionStart: note.original.selectionStart,
+      selectionEnd: note.original.selectionEnd,
+    });
+  };
@@
-        onKeyDown={handleNoteEnter}
+        onKeyDown={handleWholeNoteKeyDown}

Also applies to: 149-150

🧹 Nitpick comments (4)
src/components/NoteManager/NoteManager.css (1)

1-5: Good theming foundation; extend vars to cover link colors (avoid light-dark()).

Nice use of CSS vars for active/inactive note backgrounds. To keep theming consistent and avoid the less-supported light-dark() in link styles, introduce vars for update link colors and use them in the rules below.

Apply this diff to define the new vars:

 .note-manager{
   --inactive-note-bg: #ebebeb;
   --active-note-bg: #d8e8e7;
   --active-note-shadow-bg: #c8d9d8;
+  --note-update-fg: #444;
+  --note-update-disabled-fg: #ddd;
 }
 
 .dark .note-manager{
   --inactive-note-bg: #444;
   --active-note-bg: #3A4949;
   --active-note-shadow-bg: #4A6565;
+  --note-update-fg: #ddd;
+  --note-update-disabled-fg: #444;
 
 }

Then update the styles (outside this hunk) to use the vars and improve disabled behavior:

/* replace color: light-dark(...) */
.note-manager .update { color: var(--note-update-fg); }
.note-manager .update.disabled {
  color: var(--note-update-disabled-fg);
  pointer-events: none;
  cursor: not-allowed;
}

Also applies to: 7-12

src/components/NoteManager/components/Note.tsx (3)

97-104: Don’t cancel inner buttons/links from the container click handler.

Preventing default here can block expected behavior of nested anchors/buttons. Early return is enough.

-    if (target instanceof Element && (target.closest("button") || target.closest("a"))) {
-      e.preventDefault();
-      return;
-    }
+    if (target instanceof Element && (target.closest("button") || target.closest("a"))) {
+      return;
+    }

146-151: Fix ARIA labeling; announce “note”, not “label”, and avoid empty string props.

Use a clearer label and omit the prop when inactive. Optionally expose current state.

-        role={!active ? "button" : undefined}
-        tabIndex={!active ? 0 : undefined}
-        aria-label={!active ? "Activate label" : ""}
+        role={!active ? "button" : undefined}
+        tabIndex={!active ? 0 : undefined}
+        aria-label={!active ? "Activate note" : undefined}
+        aria-current={active ? "true" : undefined}

33-41: Naming nit: prefer NoteContext for consistency.

Align context name casing with React conventions.

-const noteContext = createContext<IDecoratedNote | null>(null);
+const NoteContext = createContext<IDecoratedNote | null>(null);
@@
-  const context = useContext(noteContext);
+  const context = useContext(NoteContext);
@@
-export function Note({ note, active = false, onEditNote, onDeleteNote }: NoteProps) {
+export function Note({ note, active = false, onEditNote, onDeleteNote }: NoteProps) {
@@
-    <NoteLayout.Root value={note}>
+    <NoteLayout.Root value={note}>
@@
-  Root: noteContext.Provider,
+  Root: NoteContext.Provider,
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 307acaa and 1ba513c.

📒 Files selected for processing (2)
  • src/components/NoteManager/NoteManager.css (2 hunks)
  • src/components/NoteManager/components/Note.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.css

⚙️ CodeRabbit configuration file

Review CSS code with focus on Tailwind CSS 4.x best practices and conventions. Ensure compatibility with Tailwind 4.x features and syntax.

Files:

  • src/components/NoteManager/NoteManager.css
**/*.{js,jsx,ts,tsx}

⚙️ CodeRabbit configuration file

When reviewing Tailwind CSS classes, ensure they follow Tailwind 4.x conventions and suggest modern 4.x alternatives for deprecated patterns.

Files:

  • src/components/NoteManager/components/Note.tsx
🧬 Code graph analysis (1)
src/components/NoteManager/components/Note.tsx (6)
src/components/NotesProvider/NotesProvider.tsx (1)
  • INotesContext (20-40)
src/components/NotesProvider/types/DecoratedNote.ts (1)
  • IDecoratedNote (4-19)
src/components/LocationProvider/LocationProvider.tsx (2)
  • LocationContext (29-29)
  • ILocationContext (6-10)
src/components/NoteManager/components/NoteLink.tsx (1)
  • NoteLink (16-131)
src/components/NoteManager/components/NoteLabels.tsx (2)
  • NoteLabels (9-17)
  • NoteLabelsEdit (26-49)
src/components/NoteContent/NoteContent.tsx (1)
  • NoteContent (10-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: visual-tests
🔇 Additional comments (1)
src/components/NoteManager/NoteManager.css (1)

53-53: No-op change.

Whitespace-only change; nothing to review.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/components/NoteManager/components/Note.tsx (2)

50-51: Remove unsafe context cast; add runtime guard.

Avoid casting a possibly null LocationContext. Fail fast with a clear error. (Previously flagged in this PR.)

-  const { setLocationParams } = useContext(LocationContext) as ILocationContext;
+  const locationCtx = useContext(LocationContext);
+  if (!locationCtx) {
+    throw new Error("Note must be rendered within a LocationProvider");
+  }
+  const { setLocationParams } = locationCtx;

116-130: Fix keyboard handler: only activate on Enter/Space; don’t hijack other keys; ignore bubbled events from children.

Current code prevents default for non-activation keys and still activates, breaking Tab/Arrow/Escape. Also "Space" key value is actually " " (or legacy "Spacebar"). (Previously flagged.)

-  const handleNoteEnter = (e: React.KeyboardEvent<HTMLDivElement>) => {
-    if (e.key !== "Enter" && e.key !== "Space") {
-      e.preventDefault();
-    }
-
-    if (active) {
-      return;
-    }
-
-    setLocationParams({
-      version: note.original.version,
-      selectionStart: note.original.selectionStart,
-      selectionEnd: note.original.selectionEnd,
-    });
-  };
+  const handleNoteKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
+    const isActivationKey = e.key === "Enter" || e.key === " " || e.key === "Spacebar";
+    if (!isActivationKey) return;
+    // Ignore key events originating from interactive descendants
+    if (e.currentTarget !== e.target) return;
+    // Prevent page scroll and duplicate native activation on Space/Enter
+    e.preventDefault();
+    if (active) return;
+    setLocationParams({
+      version: note.original.version,
+      selectionStart: note.original.selectionStart,
+      selectionEnd: note.original.selectionEnd,
+    });
+  };
@@
-        onKeyDown={handleNoteEnter}
+        onKeyDown={handleNoteKeyDown}

Also applies to: 151-151

🧹 Nitpick comments (8)
biome.jsonc (1)

4-10: Good addition; consider broader coverage for Playwright artifacts.

Ignoring tools/snapshot-tests/playwright-report/** via files.ignore is appropriate for generated output. Two optional tweaks:

  • If reports may appear in other packages or paths, prefer a globbed pattern: **/playwright-report/**.
  • Consider also ignoring other Playwright outputs to reduce noise: **/test-results/**, **/blob-report/**, and **/trace.* (or **/trace.zip), keeping them out of all Biome tooling. If you only want to skip formatting (but still allow linting), place these under formatter.ignore instead of files.ignore.

Would you like a quick script to scan the repo for Playwright artifact directories so we can add any missing ignores?

tools/snapshot-tests/tests/basic-snapshots.spec.ts (3)

35-47: Close the shared Page/Context created in beforeAll.

Add an afterAll to prevent resource leaks and cross-test flake when running many suites.

   test.beforeAll(async ({ browser }) => {
     const context = await browser.newContext(getCommonContext());

     page = await context.newPage();
     await page.goto(hostname, { waitUntil: "networkidle" });
     await page.evaluate(() => document.fonts.ready);
   });
+
+  test.afterAll(async () => {
+    if (!page) return;
+    const ctx = page.context();
+    await page.close();
+    await ctx.close();
+  });

51-56: Prefer locator screenshots over manual clip to reduce flakiness.

Let Playwright crop the element; removes boundingBox race and non-null assertion.

-        await expect(page).toHaveScreenshot("notes-tab-initial.png", {
-          // biome-ignore lint/style/noNonNullAssertion: boundingBox is expected to exist at this point
-          clip: (await page.locator('[data-testid="tab-content-notes"] .note-manager').boundingBox())!,
-          fullPage: false,
-          animations: "disabled",
-        });
+        await expect(
+          page.locator('[data-testid="tab-content-notes"] .note-manager')
+        ).toHaveScreenshot("notes-tab-initial.png", { animations: "disabled" });

Apply the same pattern to the two subsequent Notes Tab screenshots.


59-67: Decouple serial tests from prior state.

The second Notes Tab test assumes the tab remains open from the first test. Click/open the tab here as well to make it idempotent and resilient to future edits.

       test("notes tab - after note activation", async ({ browser }) => {
+        await page.click('[data-testid="tab-notes"]', { timeout });
         await page.click('[data-testid="notes-manager-card"]', { timeout });
         await expect(page).toHaveScreenshot("notes-tab-after-note-activation.png", {
-          // biome-ignore lint/style/noNonNullAssertion: boundingBox is guaranteed to exist at this point
-          clip: (await page.locator('[data-testid="tab-content-notes"] .note-manager').boundingBox())!,
-          fullPage: false,
-          animations: "disabled",
+          animations: "disabled",
         });
       });
src/components/NoteManager/components/Note.tsx (4)

147-151: Polish a11y attributes.

Use a clearer label and omit it when active to avoid empty attributes.

-        aria-label={!active ? "Activate label" : ""}
+        aria-label={!active ? "Activate note" : undefined}

55-60: Avoid mutating state when updating labels.

Create the new object from the previous state instead of mutating and re-spreading.

-    (labels: UnPrefixedLabel[]) => {
-      noteDirty.labels = [...new Set(labels)];
-      setNoteDirty({ ...noteDirty });
-    },
-    [noteDirty],
+    (labels: UnPrefixedLabel[]) => {
+      setNoteDirty((prev) => ({
+        ...prev,
+        labels: Array.from(new Set(labels)),
+      }));
+    },
+    [],

26-31: Make active optional to match the default parameter.

Type says active is required, but the component supplies a default. Align the prop type.

 type NoteProps = {
   note: IDecoratedNote;
-  active: boolean;
+  active?: boolean;
   onEditNote: INotesContext["handleUpdateNote"];
   onDeleteNote: INotesContext["handleDeleteNote"];
 };
@@
-export function Note({ note, active = false, onEditNote, onDeleteNote }: NoteProps) {
+export function Note({ note, active = false, onEditNote, onDeleteNote }: NoteProps) {

Also applies to: 43-43


168-170: Simplify: the Edit button’s test id and handler don’t need conditionals here.

This branch only renders when !isEditing, so the ternaries are dead code.

-                  data-testid={isEditing ? "save-button" : "edit-button"}
-                  onClick={isEditing ? handleSaveClick : handleEditClick}
+                  data-testid="edit-button"
+                  onClick={handleEditClick}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ba513c and a8d3689.

⛔ Files ignored due to path filters (14)
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-edit-click-dark-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-edit-click-light-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-activation-dark-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-activation-dark-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-activation-light-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-activation-light-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-edit-dark-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-edit-dark-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-edit-light-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-after-note-edit-light-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-initial-dark-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-initial-dark-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-initial-light-mode-darwin.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts-snapshots/notes-tab-initial-light-mode-linux.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • biome.jsonc (1 hunks)
  • src/components/NoteManager/components/Note.tsx (3 hunks)
  • tools/snapshot-tests/tests/basic-snapshots.spec.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

⚙️ CodeRabbit configuration file

When reviewing Tailwind CSS classes, ensure they follow Tailwind 4.x conventions and suggest modern 4.x alternatives for deprecated patterns.

Files:

  • tools/snapshot-tests/tests/basic-snapshots.spec.ts
  • src/components/NoteManager/components/Note.tsx
🧬 Code graph analysis (1)
src/components/NoteManager/components/Note.tsx (6)
src/components/NotesProvider/NotesProvider.tsx (1)
  • INotesContext (20-40)
src/components/NotesProvider/types/DecoratedNote.ts (1)
  • IDecoratedNote (4-19)
src/components/LocationProvider/LocationProvider.tsx (2)
  • LocationContext (29-29)
  • ILocationContext (6-10)
src/components/NoteManager/components/NoteLink.tsx (1)
  • NoteLink (16-131)
src/components/NoteManager/components/NoteLabels.tsx (2)
  • NoteLabels (9-17)
  • NoteLabelsEdit (26-49)
src/components/NoteContent/NoteContent.tsx (1)
  • NoteContent (10-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: visual-tests
🔇 Additional comments (1)
tools/snapshot-tests/tests/basic-snapshots.spec.ts (1)

1-1: Typed Playwright import looks good.

@chmurson chmurson merged commit a8d528d into main Oct 22, 2025
7 of 9 checks passed
@chmurson chmurson deleted the activation-note-logic-change branch October 22, 2025 22:11
This was referenced Nov 11, 2025
This was referenced Dec 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant