Repository navigation
feat: add mention in editor - #59
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
| Layer / File(s) | Summary |
|---|---|
Mention extension foundation package.json, components/editor/mentions.tsx, components/editor/extensions.ts, skills-lock.json |
Mention dependencies, the MentionUser shape, the configured TipTap mention extension, and skill metadata are added. |
Suggestion dropdown lifecycle components/editor/mentions.tsx, app/globals.css |
Mention suggestions render member rows with keyboard navigation, popup positioning, dismissal handling, cleanup, and themed mention styling. |
Dynamic editor integration components/editor/editor.tsx, components/editor/extensions.ts, app/(organization)/organizations/[organizationId]/_components/message-item.tsx |
Editor conditionally configures mention suggestions from mentionsQuery; editor sizing and rendered message layout classes are adjusted. |
Member lookup and composer wiring app/(organization)/organizations/[organizationId]/_components/edit-message-form.tsx, app/(organization)/organizations/[organizationId]/_components/messaeg-input.tsx, app/(organization)/organizations/[organizationId]/_components/message-omposer.tsx, components/thread-sidebar/threads-form.tsx |
Message forms query team members, normalize member records, filter up to eight name/email matches, and pass mention data into composers and editors. |
Estimated code review effort: 4 (Complex) | ~45 minutes
Sequence Diagram(s)
sequenceDiagram
participant MessageInput
participant TeamMembersQuery
participant Messagecomponser
participant Editor
participant MentionSuggestions
MessageInput->>TeamMembersQuery: fetch members for teamId
TeamMembersQuery-->>MessageInput: return member records
MessageInput->>Messagecomponser: pass members
Messagecomponser->>Editor: pass mentionsQuery
Editor->>MentionSuggestions: configure @ suggestions
MentionSuggestions->>Messagecomponser: request matching members
🚥 Pre-merge checks | ✅ 4 | ❌ 1
-
❌ Failed checks (1 warning)
Check name Status Explanation Resolution Docstring Coverage ⚠️ WarningDocstring coverage is 12.50% 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 Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled. Title check ✅ Passed The title clearly matches the main change: adding mention support to the editor. Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
-
✨ Finishing Touches
-
📝 Generate docstrings
-
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
-
- Create PR with unit tests
- Commit unit tests in branch
feat/mention
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (7)
app/(organization)/organizations/[organizationId]/_components/message-omposer.tsx (1)
6-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd explanatory comments to the new
mentionsQuerylogic.The new callback (filter/limit logic, empty-members guard) has no comments explaining the reasoning, e.g. why results are capped at 8.
As per coding guidelines,
**/*.{ts,tsx,js,jsx}: "Add comments to any new code you add, explaining the reason for the code or the non-obvious decision it implements."💬 Suggested comment
const mentionsQuery = useCallback( async (query: string) => { if (!members?.length) { return []; } const normalizedQuery = query.toLowerCase(); + // Cap suggestions to 8 rows to keep the dropdown compact and avoid + // rendering excessively long member lists. return members .filter( (member) => member.name.toLowerCase().includes(normalizedQuery) || (member.email?.toLowerCase().includes(normalizedQuery) ?? false) ) .slice(0, 8); }, [members] );Also applies to: 20-20, 31-54
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/`(organization)/organizations/[organizationId]/_components/message-omposer.tsx around lines 6 - 7, Add explanatory comments to the new mentionsQuery callback in the message composer, including the empty-members guard, filtering behavior, and the reason results are capped at 8; keep comments focused on the non-obvious decisions and use the MentionUser-related logic to locate the implementation.Source: Coding guidelines
app/(organization)/organizations/[organizationId]/_components/messaeg-input.tsx (1)
61-71: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate members-fetch logic across composer forms.
The suspense query + member-array mapping here is identical to the block added in
components/thread-sidebar/threads-form.tsx(lines 60-70). Consider extracting a shareduseTeamMembers(teamId)hook to avoid drift between the two copies as the member shape evolves.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/`(organization)/organizations/[organizationId]/_components/messaeg-input.tsx around lines 61 - 71, Extract the duplicated members query and mapping into a shared useTeamMembers(teamId) hook, then replace the inline logic in the message input component and components/thread-sidebar/threads-form.tsx with that hook. Preserve the existing returned member shape and suspense-query behavior.components/editor/mentions.tsx (3)
24-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFragile plugin lookup for
closeSuggestion.The heuristic finds "the" suggestion plugin by duck-typing its state shape (
active/decorationIdkeys). This works today because Mention is the only suggestion-based extension, but if a second suggestion extension (emoji, slash-commands, etc.) is added later,find()will grab whichever plugin appears first and may close/dismiss the wrong one.Consider configuring the Mention extension with an explicit
suggestion.pluginKeyand storing/exporting that key socloseSuggestioncan look it up directly instead of scanning by shape.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/editor/mentions.tsx` around lines 24 - 36, Replace the duck-typed plugin search in closeSuggestion with an explicit Mention suggestion plugin key. Configure the Mention extension’s suggestion option with a named pluginKey, export or otherwise share that key with closeSuggestion, and retrieve the plugin directly from view.state using the key before dispatching the exit metadata.
188-211: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winPopup position isn't updated on scroll/resize.
position()is only invoked fromonStartandonUpdate(i.e., when the query text changes). If the page or a scrollable ancestor scrolls while the dropdown is open, thefixed-positioned popup stays anchored to the last computedrectand visually drifts away from the caret until the next keystroke.Consider adding a
scroll/resizelistener (removed inonExit) that re-runsposition(props).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/editor/mentions.tsx` around lines 188 - 211, Add scroll and resize listeners when the mention popup opens, reusing the current SuggestionProps to call position(props) whenever the viewport or scrollable content changes; remove both listeners in onExit to prevent leaks, and ensure listener setup/cleanup is coordinated with the existing popup lifecycle and position function.
49-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTypo in comment.
"Refences" should be "References".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/editor/mentions.tsx` around lines 49 - 54, Correct the typo in the documentation comment above the mention editor extension: change “Refences and Thanks to” to “References and Thanks to”.app/(organization)/organizations/[organizationId]/_components/edit-message-form.tsx (1)
63-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing comment for the magic
8-result cap.The
.slice(0, 8)limit and the filter rules are new, non-obvious logic with no explanation of why 8 was chosen (e.g., UI/perf constraint for the dropdown).
As per coding guidelines, add a short comment for new code that isn't self-evident.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/`(organization)/organizations/[organizationId]/_components/edit-message-form.tsx around lines 63 - 86, The mentionsQuery result cap and matching logic lack context. Add a brief comment before the filtering or slicing in mentionsQuery explaining that results are limited to 8 to keep the mention dropdown concise and performant.Source: Coding guidelines
components/editor/editor.tsx (1)
31-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate
Mention.configure({HTMLAttributes:{class:"mention"}})between this file andextensions.ts.The same
HTMLAttributesconfig is repeated incomponents/editor/extensions.ts(Lines 57-61) and here. If the class name or attributes ever change, both call sites must be kept in sync manually.Consider extracting a small factory (e.g.,
createMentionExtension(suggestion?)) shared by both files.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/editor/editor.tsx` around lines 31 - 39, Remove the duplicated Mention configuration by introducing a shared factory such as createMentionExtension(suggestion?) in the editor extension utilities, centralizing the HTMLAttributes class setting and optional suggestion setup. Update both the editor extension construction and extensions.ts to use this factory while preserving their existing behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@app/`(organization)/organizations/[organizationId]/_components/edit-message-form.tsx:
- Around line 63-86: Extract the shared case-insensitive member filtering,
eight-result limit, and MentionUser mapping from mentionsQuery into a reusable
filterMembersForMentions helper with an optional limit defaulting to 8; update
this component’s mentionsQuery and the corresponding composer implementations,
including message-omposer.tsx, to call the helper.
In `@components/editor/editor.tsx`:
- Around line 26-40: Add a brief comment above the `baseExtensions.filter` and
configured `Mention` replacement in `editorExtensions`, explaining that the
default mention extension is removed and replaced with a suggestion-configured
instance when `mentionsQuery` is available.
In `@package.json`:
- Around line 43-52: Update the `@tiptap/extension-code-block-lowlight` dependency
to version ^3.27.3 in package.json, matching the other Tiptap packages and
avoiding peer dependency conflicts with `@tiptap/core` and `@tiptap/pm`.
---
Nitpick comments:
In
`@app/`(organization)/organizations/[organizationId]/_components/edit-message-form.tsx:
- Around line 63-86: The mentionsQuery result cap and matching logic lack
context. Add a brief comment before the filtering or slicing in mentionsQuery
explaining that results are limited to 8 to keep the mention dropdown concise
and performant.
In
`@app/`(organization)/organizations/[organizationId]/_components/messaeg-input.tsx:
- Around line 61-71: Extract the duplicated members query and mapping into a
shared useTeamMembers(teamId) hook, then replace the inline logic in the message
input component and components/thread-sidebar/threads-form.tsx with that hook.
Preserve the existing returned member shape and suspense-query behavior.
In
`@app/`(organization)/organizations/[organizationId]/_components/message-omposer.tsx:
- Around line 6-7: Add explanatory comments to the new mentionsQuery callback in
the message composer, including the empty-members guard, filtering behavior, and
the reason results are capped at 8; keep comments focused on the non-obvious
decisions and use the MentionUser-related logic to locate the implementation.
In `@components/editor/editor.tsx`:
- Around line 31-39: Remove the duplicated Mention configuration by introducing
a shared factory such as createMentionExtension(suggestion?) in the editor
extension utilities, centralizing the HTMLAttributes class setting and optional
suggestion setup. Update both the editor extension construction and
extensions.ts to use this factory while preserving their existing behavior.
In `@components/editor/mentions.tsx`:
- Around line 24-36: Replace the duck-typed plugin search in closeSuggestion
with an explicit Mention suggestion plugin key. Configure the Mention
extension’s suggestion option with a named pluginKey, export or otherwise share
that key with closeSuggestion, and retrieve the plugin directly from view.state
using the key before dispatching the exit metadata.
- Around line 188-211: Add scroll and resize listeners when the mention popup
opens, reusing the current SuggestionProps to call position(props) whenever the
viewport or scrollable content changes; remove both listeners in onExit to
prevent leaks, and ensure listener setup/cleanup is coordinated with the
existing popup lifecycle and position function.
- Around line 49-54: Correct the typo in the documentation comment above the
mention editor extension: change “Refences and Thanks to” to “References and
Thanks to”.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c84f2a00-c5d4-41f2-86aa-d5e7dc10aa09
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (11)
app/(organization)/organizations/[organizationId]/_components/edit-message-form.tsxapp/(organization)/organizations/[organizationId]/_components/messaeg-input.tsxapp/(organization)/organizations/[organizationId]/_components/message-item.tsxapp/(organization)/organizations/[organizationId]/_components/message-omposer.tsxapp/globals.csscomponents/editor/editor.tsxcomponents/editor/extensions.tscomponents/editor/mentions.tsxcomponents/thread-sidebar/threads-form.tsxpackage.jsonskills-lock.json
Resolve conflicts combining mention feature from feat/mention with main's updates: newer Tiptap (3.30.1), details extension, react-table, conversationKey, expandable content, and editor onSubmit/keyboard handling. Regenerate pnpm-lock.yaml from merged package.json.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Add Mention model to Prisma schema with relations on Message and User. Create lib/mentions.ts with analyzeContent() and server-side validMentionIds() that re-validates membership (team or org scope) and excludes the author. Update createMessage and updateMessage handlers to parse Tiptap content, validate mentions, and persist Mention rows in a single transaction. Output now includes computed mentionedUserIds. Add mentionedUserIds to messageListItemSchema and include it in the message:created realtime payload so PartyKit can notify mentioned users. Also wire up the user.mention RPC endpoint, useMentionUsers hook, and mention picker imports used by the editor.
Use Inngest to queue mention emails on message creation and edits, with recipient validation, retries, and HTML escaping. Add the Inngest API route and development tooling. closes #105
- Fix TS2353 in createMessage: narrow teamId from the discriminated union scope before passing to inngest.send - Add mentionedUserIds to RealtimeMessageSchema so the message:created payload carries server-validated mention IDs - Map mentionedUserIds from raw realtime payload into MessageListItemType in the conversation realtime provider
ali-raza-fa22
left a comment
There was a problem hiding this comment.
use shadcn command command component for mention.tsx
Summary by CodeRabbit
New Features
@mentionsuggestions to message editors and thread replies.Improvements