Skip to content

feat(web): auto-add bookmark to list on selection#2629

Merged
MohamedBassem merged 9 commits intokarakeep-app:mainfrom
xingzihai:feat/auto-add-to-list-clean
Apr 20, 2026
Merged

feat(web): auto-add bookmark to list on selection#2629
MohamedBassem merged 9 commits intokarakeep-app:mainfrom
xingzihai:feat/auto-add-to-list-clean

Conversation

@xingzihai
Copy link
Copy Markdown
Contributor

Fixes #2604

Summary

Automatically add bookmark to the selected list when user clicks on a list item in the ManageListsModal.

Changes

  • BookmarkListSelector now triggers addToList when a list is selected
  • Improved UX: users don't need to click "Add" button separately
  • Added loading state and prevented duplicate submission

Testing

  • Tested locally with list selection
  • Verified bookmark is added correctly

Remove the 'Add' button from Manage Lists modal. When a user selects
a list from the dropdown, the bookmark is now automatically added to
that list, simplifying the user experience.

Users can still remove a bookmark from a list by clicking the X button
next to the list name.

Fixes karakeep-app#2604
…sModal

- Added isPending state from useAddBookmarkToList hook
- Added duplicate submission prevention in onChange handler
- Added disabled prop to BookmarkListSelector component
- Fix incorrect indentation of onSuccess and onError callbacks
- Add trailing newline at end of file
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Removed the form/zod/react-hook-form submit flow from ManageListsModal; adding to a list now happens immediately via BookmarkListSelector.onChange. BookmarkListSelector gained a new disabled prop forwarded to its trigger button.

Changes

Cohort / File(s) Summary
Manage Lists Modal
apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
Removed react-hook-form/zod form wiring, Form/FormField scaffolding, submit handler and the type="submit" Add button. Selection now triggers addToList({ bookmarkId, listId }) directly from BookmarkListSelector.onChange; removed form.resetField("listId") calls. Dialog header title changed to t("actions.manage_lists"). List path lookup now uses allLists?.getPathById(list.id) with fallback to list.name. Footer actions reduced to Close and Archive; list item delete button includes aria-label={t("actions.remove_bookmark")}.
Bookmark List Selector
apps/web/components/dashboard/lists/BookmarkListSelector.tsx
Added disabled?: boolean prop (default false) and forwarded it to the selector trigger Button (disabled={disabled}) to control interactivity; selection/filtering and fetching logic unchanged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: implementing auto-add functionality when a bookmark is selected in a list, which aligns with the primary objective of the PR.
Description check ✅ Passed The description clearly explains the feature implementation, references the linked issue (#2604), and outlines the key changes and testing performed.
Linked Issues check ✅ Passed The PR successfully addresses issue #2604 by removing the explicit 'Add' button, implementing immediate bookmark addition on list selection, and maintaining the ability to remove lists afterward via delete controls.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked objective: removing form-based submission flow, enabling auto-add on selection, and improving accessibility with proper aria-labels. No extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 27, 2026

Greptile Summary

This PR simplifies the "Manage Lists" flow by removing the react-hook-form/zod wrapper and the explicit "Add" button — selecting a list from the dropdown now immediately triggers addToList. The BookmarkListSelector gains a disabled prop to block interaction during loading or an in-flight mutation. As a bonus, the old allLists.getPathById(list.id)! non-null assertion (which would throw if a list had no path) is replaced with optional chaining and a list.name fallback.

Confidence Score: 5/5

Safe to merge — no P0/P1 issues found; all remaining observations are P2 or lower.

The refactor is straightforward and correct. The disabled guard prevents double-submission, the null-assertion bug in the old code is fixed, and the selector correctly displays the placeholder after a selection (no controlled value is needed for the auto-add pattern). No data-loss or logic errors identified.

No files require special attention.

Important Files Changed

Filename Overview
apps/web/components/dashboard/bookmarks/ManageListsModal.tsx Removes the react-hook-form/zod form wrapper and "Add" button; now calls addToList directly from BookmarkListSelector's onChange, with disabled guard during loading/pending states. Also fixes a potential null-assertion crash by adding optional chaining and a list.name fallback.
apps/web/components/dashboard/lists/BookmarkListSelector.tsx Adds an optional disabled prop that is forwarded to the PopoverTrigger button; minimal and correct change.

Reviews (2): Last reviewed commit: "typecheck" | Re-trigger Greptile

Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx Outdated
Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
Copy link
Copy Markdown
Contributor

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/components/dashboard/bookmarks/ManageListsModal.tsx`:
- Around line 139-152: The selection can be triggered while membership data is
still loading; update the ManageListsModal usage of BookmarkListSelector so
interactions are disabled during loading and the onChange guard also checks
loading. Specifically, change the disabled prop to combine isAddingToListPending
|| isLoading, and update the onChange callback to return early unless both
!isAddingToListPending and !isLoading before calling addToList(bookmarkId,
listId); keep references to BookmarkListSelector, hideBookmarkIds
(alreadyInList?.lists.map), onChange, isAddingToListPending, isLoading,
addToList, and bookmarkId so the fix is easy to locate.
- Around line 117-120: The code assumes allLists.getPathById(list.id) always
returns an array and directly calls .map(...), which will crash if it returns
undefined/null; update the render in ManageListsModal to first store the result
of allLists.getPathById(list.id) (or call it into a local variable), guard it
with a null check (e.g., if path is falsy render a safe fallback like list.name
or an empty string), and only call path.map(...) and .join(" / ") when path is
an array—this prevents crashes for stale/missing paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4058e129-f284-4a71-92d8-5d7f26364ff8

📥 Commits

Reviewing files that changed from the base of the PR and between 53a4598 and 227cb54.

📒 Files selected for processing (2)
  • apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
  • apps/web/components/dashboard/lists/BookmarkListSelector.tsx

Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx Outdated
Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
- Add trailing newline at end of file
- Remove redundant in-flight guard check (disabled prop handles it)
- Add guard for getPathById to prevent crash on stale cache
- Disable interactions while list membership data is loading
Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/components/dashboard/bookmarks/ManageListsModal.tsx`:
- Around line 103-105: Replace the hardcoded modal title in
ManageListsModal.tsx: instead of <DialogTitle>Manage Lists</DialogTitle> call
the translation function used elsewhere (t) — e.g. <DialogTitle>{t("Manage
Lists")}</DialogTitle> (or use the existing i18n key you use for list headings,
like t("manageLists") if that key exists) so the DialogTitle uses localized
text; ensure t is in scope where DialogTitle is rendered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b4160672-40de-4c88-804f-cd972a8d9093

📥 Commits

Reviewing files that changed from the base of the PR and between 227cb54 and 4a07721.

📒 Files selected for processing (1)
  • apps/web/components/dashboard/bookmarks/ManageListsModal.tsx

Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
Copy link
Copy Markdown
Contributor

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/components/dashboard/bookmarks/ManageListsModal.tsx`:
- Around line 124-134: The ActionButton that renders the X icon is icon-only and
lacks an accessible name; add an aria-label (or equivalent sr-only text) to the
ActionButton in ManageListsModal so screen readers announce its purpose — e.g.,
set aria-label={`Remove bookmark from ${list.name}`} or a generic
aria-label="Remove bookmark" on the ActionButton that calls deleteFromList({
bookmarkId, listId: list.id }) to make the remove action accessible.
- Around line 109-121: The list rows are currently hidden because the whole UL
is gated on allLists; instead, render the rows unconditionally using
alreadyInList.lists and only use allLists when available to compute the display
path. Modify the render in ManageListsModal.tsx so that you iterate over
alreadyInList?.lists (or alreadyInList.lists) regardless of allLists, call
allLists?.getPathById(list.id) (optional chaining) to build the path if present,
and fall back to rendering list.name when getPathById returns undefined; keep
the existing remove control/handlers intact so they remain visible when the tree
query is empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b8b6565a-5b47-40ac-a8d2-0d1dca6a2e85

📥 Commits

Reviewing files that changed from the base of the PR and between 6d990af and 3e555c2.

📒 Files selected for processing (1)
  • apps/web/components/dashboard/bookmarks/ManageListsModal.tsx

Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx Outdated
Comment thread apps/web/components/dashboard/bookmarks/ManageListsModal.tsx
xingzihai and others added 3 commits March 29, 2026 20:41
- Add aria-label to remove button for accessibility (CodeRabbit comment 3006737430)
- Remove allLists gating to allow list.name fallback to render (CodeRabbit comment 3006737429)
- Use optional chaining for path lookup
@MohamedBassem
Copy link
Copy Markdown
Collaborator

@greptile review

@MohamedBassem MohamedBassem merged commit a8c5ac9 into karakeep-app:main Apr 20, 2026
7 checks passed
@MohamedBassem
Copy link
Copy Markdown
Collaborator

Thank you!

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.

Delete the 'Add' Button from Manage Lists

2 participants