reply UX: bigger chip, click-to-scroll with highlight
- Reply chip: larger with border-l-4, bg tint, proper padding
- Reply context in messages: click to smooth-scroll to quoted message
- Quoted message flashes primary/10 bg for 1.5s on scroll
- Each message gets id="msg-{id}" for scroll targeting
- Reply context text bumped to 11px
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -126,14 +126,17 @@ export function ComposeBox({
|
|||||||
)}>
|
)}>
|
||||||
{/* Reply chip */}
|
{/* Reply chip */}
|
||||||
{replyTo && (
|
{replyTo && (
|
||||||
<div className="flex items-center gap-1.5 mb-1.5 text-[10px] font-mono">
|
<div className="flex items-center gap-2 mb-3 px-3 py-2 border-l-4 border-primary bg-muted/30 text-xs font-mono">
|
||||||
<span className="text-primary">^</span>
|
<div className="flex-1 min-w-0">
|
||||||
<span className="text-foreground font-bold">{replyTo.username}</span>
|
<span className="text-primary font-bold">{replyTo.username}</span>
|
||||||
<span className="text-muted-foreground truncate max-w-48 md:max-w-96">{replyTo.content}</span>
|
<span className="text-muted-foreground ml-2 truncate inline-block max-w-48 md:max-w-96 align-bottom">
|
||||||
|
{replyTo.content}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onClearReply}
|
onClick={onClearReply}
|
||||||
className="text-muted-foreground hover:text-primary ml-auto flex-shrink-0"
|
className="text-muted-foreground hover:text-primary flex-shrink-0 text-sm font-bold min-w-[32px] min-h-[32px] flex items-center justify-center"
|
||||||
>
|
>
|
||||||
x
|
x
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -60,22 +60,36 @@ export function MessageItem({ message, replyTarget, onReply }: Props) {
|
|||||||
const cfg = TYPE_CONFIG[message.type] || TYPE_CONFIG.text;
|
const cfg = TYPE_CONFIG[message.type] || TYPE_CONFIG.text;
|
||||||
const meta = message.metadata as Record<string, string> | null;
|
const meta = message.metadata as Record<string, string> | null;
|
||||||
|
|
||||||
|
function scrollToMessage(id: string) {
|
||||||
|
const el = document.getElementById(`msg-${id}`);
|
||||||
|
if (el) {
|
||||||
|
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||||
|
el.classList.add("!bg-primary/10");
|
||||||
|
setTimeout(() => el.classList.remove("!bg-primary/10"), 1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
id={`msg-${message.id}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
"group border-b border-border/50 border-l-4 transition-colors",
|
"group border-b border-border/50 border-l-4 transition-all duration-300",
|
||||||
cfg.border,
|
cfg.border,
|
||||||
isAgent ? "bg-card" : "bg-background",
|
isAgent ? "bg-card" : "bg-background",
|
||||||
"hover:bg-muted/30",
|
"hover:bg-muted/30",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* Reply context */}
|
{/* Reply context — click to scroll to quoted message */}
|
||||||
{replyTarget && (
|
{replyTarget && (
|
||||||
<div className="px-4 pt-1.5 text-[10px] text-muted-foreground flex items-center gap-1">
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => scrollToMessage(replyTarget.id)}
|
||||||
|
className="w-full text-left px-4 pt-2 pb-0.5 text-[11px] text-muted-foreground flex items-center gap-1.5 hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
<span className="text-primary font-bold">^</span>
|
<span className="text-primary font-bold">^</span>
|
||||||
<span className="font-bold">{replyTarget.user.display_name}</span>
|
<span className="font-bold">{replyTarget.user.display_name}</span>
|
||||||
<span className="truncate max-w-40 md:max-w-80 opacity-60">{replyTarget.content}</span>
|
<span className="truncate max-w-48 md:max-w-96 opacity-60">{replyTarget.content}</span>
|
||||||
</div>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="px-4 py-3 md:px-5 md:py-4">
|
<div className="px-4 py-3 md:px-5 md:py-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user