From e91651caaaeef22d9dc936db5af617b98b06d520 Mon Sep 17 00:00:00 2001 From: Nexus Dev Date: Wed, 1 Apr 2026 18:23:53 +0000 Subject: [PATCH] feat(22-03): add ChatStopButton and ChatMessageActions components - ChatStopButton: centered outline button with Square icon and 'Stop generating' label - ChatMessageActions: edit Pencil for user messages (absolute, group-hover) - ChatMessageActions: retry RefreshCw for assistant messages (right-aligned, group-hover) - Both action buttons return null when isStreaming is true - Proper aria-labels and tooltips on all interactive elements --- ui/src/components/ChatMessageActions.tsx | 58 ++++++++++++++++++++++++ ui/src/components/ChatStopButton.tsx | 23 ++++++++++ 2 files changed, 81 insertions(+) create mode 100644 ui/src/components/ChatMessageActions.tsx create mode 100644 ui/src/components/ChatStopButton.tsx diff --git a/ui/src/components/ChatMessageActions.tsx b/ui/src/components/ChatMessageActions.tsx new file mode 100644 index 00000000..92d59380 --- /dev/null +++ b/ui/src/components/ChatMessageActions.tsx @@ -0,0 +1,58 @@ +import { Pencil, RefreshCw } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; + +interface ChatMessageActionsProps { + role: "user" | "assistant" | "system"; + isStreaming?: boolean; + onEdit?: () => void; + onRetry?: () => void; +} + +export function ChatMessageActions({ role, isStreaming, onEdit, onRetry }: ChatMessageActionsProps) { + if (isStreaming) return null; + + if (role === "user" && onEdit) { + return ( +
+ + + + + Edit message + +
+ ); + } + + if (role === "assistant" && onRetry) { + return ( +
+ + + + + Retry response + +
+ ); + } + + return null; +} diff --git a/ui/src/components/ChatStopButton.tsx b/ui/src/components/ChatStopButton.tsx new file mode 100644 index 00000000..e2516347 --- /dev/null +++ b/ui/src/components/ChatStopButton.tsx @@ -0,0 +1,23 @@ +import { Square } from "lucide-react"; +import { Button } from "@/components/ui/button"; + +interface ChatStopButtonProps { + onStop: () => void; +} + +export function ChatStopButton({ onStop }: ChatStopButtonProps) { + return ( +
+ +
+ ); +}