From b9ea10c89dfaf285534abbbd00ef1133005c7cf8 Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:50:22 +0800 Subject: [PATCH] fix(comments): unify rendering with RichTextEditor, fix mention/link colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Comment display: replace with - Link color: primary → brand (blue) - Mention color: brand → primary + semibold - Add MentionHoverCard component with HoverCardTrigger render={} - Markdown.tsx: sync mention style to text-primary font-semibold Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/common/mention-hover-card.tsx | 70 +++++++++++++++++++ .../components/common/rich-text-editor.css | 6 +- apps/web/components/markdown/Markdown.tsx | 12 +++- .../issues/components/comment-card.tsx | 3 +- 4 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 apps/web/components/common/mention-hover-card.tsx diff --git a/apps/web/components/common/mention-hover-card.tsx b/apps/web/components/common/mention-hover-card.tsx new file mode 100644 index 00000000..f54d4ad2 --- /dev/null +++ b/apps/web/components/common/mention-hover-card.tsx @@ -0,0 +1,70 @@ +"use client"; + +import type { ReactNode } from "react"; +import { Bot } from "lucide-react"; +import { HoverCard, HoverCardTrigger, HoverCardContent } from "@/components/ui/hover-card"; +import { ActorAvatar } from "@/components/common/actor-avatar"; +import { useWorkspaceStore } from "@/features/workspace"; + +interface MentionHoverCardProps { + type: string; + id: string; + children: ReactNode; +} + +function MentionHoverCard({ type, id, children }: MentionHoverCardProps) { + const members = useWorkspaceStore((s) => s.members); + const agents = useWorkspaceStore((s) => s.agents); + + if (type === "member") { + const member = members.find((m) => m.user_id === id); + if (!member) return <>{children}; + + return ( + + } className="cursor-default"> + {children} + + +
+ +
+

{member.name}

+

{member.email}

+
+
+
+
+ ); + } + + if (type === "agent") { + const agent = agents.find((a) => a.id === id); + if (!agent) return <>{children}; + + return ( + + } className="cursor-default"> + {children} + + +
+
+ +
+
+

{agent.name}

+ {agent.description && ( +

{agent.description}

+ )} +
+
+
+
+ ); + } + + return <>{children}; +} + +export { MentionHoverCard }; diff --git a/apps/web/components/common/rich-text-editor.css b/apps/web/components/common/rich-text-editor.css index 4df15d5d..f387d05d 100644 --- a/apps/web/components/common/rich-text-editor.css +++ b/apps/web/components/common/rich-text-editor.css @@ -126,7 +126,7 @@ /* Links */ .rich-text-editor a { - color: var(--primary); + color: var(--brand); text-decoration: none; } @@ -137,8 +137,8 @@ /* Mentions */ .rich-text-editor .mention { - color: var(--brand); - font-weight: 500; + color: var(--primary); + font-weight: 600; text-decoration: none; margin: 0 0.125rem; } diff --git a/apps/web/components/markdown/Markdown.tsx b/apps/web/components/markdown/Markdown.tsx index a63c6213..00038dad 100644 --- a/apps/web/components/markdown/Markdown.tsx +++ b/apps/web/components/markdown/Markdown.tsx @@ -3,6 +3,7 @@ import ReactMarkdown, { type Components } from 'react-markdown' import rehypeRaw from 'rehype-raw' import remarkGfm from 'remark-gfm' import { cn } from '@/lib/utils' +import { MentionHoverCard } from '@/components/common/mention-hover-card' import { CodeBlock, InlineCode } from './CodeBlock' import { preprocessLinks } from './linkify' @@ -60,10 +61,15 @@ function createComponents( a: ({ href, children }) => { // Mention links: mention://member/id or mention://agent/id if (href?.startsWith('mention://')) { + const parts = href.replace('mention://', '').split('/') + const mentionType = parts[0] ?? 'member' + const mentionId = parts[1] ?? '' return ( - - {children} - + + + {children} + + ) } diff --git a/apps/web/features/issues/components/comment-card.tsx b/apps/web/features/issues/components/comment-card.tsx index 13aed067..2e2b7b51 100644 --- a/apps/web/features/issues/components/comment-card.tsx +++ b/apps/web/features/issues/components/comment-card.tsx @@ -15,7 +15,6 @@ import { import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip"; import { ActorAvatar } from "@/components/common/actor-avatar"; import { ReactionBar } from "@/components/common/reaction-bar"; -import { Markdown } from "@/components/markdown"; import { useActorName } from "@/features/workspace"; import { timeAgo } from "@/shared/utils"; import { RichTextEditor, type RichTextEditorRef } from "@/components/common/rich-text-editor"; @@ -162,7 +161,7 @@ function CommentRow({ ) : ( <>
- {entry.content ?? ""} +
{!isTemp && (