Skip to content

Commit 422ec9c

Browse files
authored
🤖 fix: improve review UI visual hierarchy and add action buttons (#1131)
## Summary - Fix section header styling in ReviewsBanner (remove font-medium/uppercase to reduce visual weight) - Add complete/detach/trash buttons to attached reviews in ChatInput - Trash button separated with margin as destructive action ## Changes 1. **ReviewsBanner**: Simplified Pending/Completed section headers from `text-[10px] font-medium tracking-wide uppercase` to just `text-[10px]` for proper visual hierarchy 2. **ReviewBlock**: Added `onComplete`, `onDetach`, `onDelete` props with proper button grouping (safe actions together, trash separated) 3. **ChatInput types**: Added `onCheckReview` and `onDeleteReview` callbacks 4. **AIView**: Wired up new callbacks to useReviews hook methods _Generated with `mux`_
1 parent 31a8455 commit 422ec9c

File tree

5 files changed

+67
-22
lines changed

5 files changed

+67
-22
lines changed

src/browser/components/AIView.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,9 @@ const AIViewInner: React.FC<AIViewProps> = ({
749749
attachedReviews={reviews.attachedReviews}
750750
onDetachReview={reviews.detachReview}
751751
onDetachAllReviews={reviews.detachAllAttached}
752+
onCheckReview={reviews.checkReview}
752753
onCheckReviews={handleCheckReviews}
754+
onDeleteReview={reviews.removeReview}
753755
onUpdateReviewNote={reviews.updateReviewNote}
754756
/>
755757
</div>

src/browser/components/ChatInput/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1420,9 +1420,15 @@ const ChatInputInner: React.FC<ChatInputProps> = (props) => {
14201420
<ReviewBlockFromData
14211421
key={review.id}
14221422
data={review.data}
1423-
onRemove={
1423+
onComplete={
1424+
props.onCheckReview ? () => props.onCheckReview!(review.id) : undefined
1425+
}
1426+
onDetach={
14241427
props.onDetachReview ? () => props.onDetachReview!(review.id) : undefined
14251428
}
1429+
onDelete={
1430+
props.onDeleteReview ? () => props.onDeleteReview!(review.id) : undefined
1431+
}
14261432
onEditComment={
14271433
props.onUpdateReviewNote
14281434
? (newNote) => props.onUpdateReviewNote!(review.id, newNote)

src/browser/components/ChatInput/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ export interface ChatInputWorkspaceVariant {
3636
onDetachReview?: (reviewId: string) => void;
3737
/** Detach all attached reviews from chat input */
3838
onDetachAllReviews?: () => void;
39-
/** Mark reviews as checked after sending */
39+
/** Mark a single review as checked (completed) */
40+
onCheckReview?: (reviewId: string) => void;
41+
/** Mark multiple reviews as checked after sending */
4042
onCheckReviews?: (reviewIds: string[]) => void;
43+
/** Permanently delete a review */
44+
onDeleteReview?: (reviewId: string) => void;
4145
/** Update a review's comment/note */
4246
onUpdateReviewNote?: (reviewId: string, newNote: string) => void;
4347
}

src/browser/components/ReviewsBanner.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,7 @@ const ReviewsBannerInner: React.FC<ReviewsBannerInnerProps> = ({ workspaceId })
407407
{pendingList.length > 0 && (
408408
<div className="space-y-1.5">
409409
<div className="flex items-center justify-between">
410-
<div className="text-muted text-[10px] font-medium tracking-wide uppercase">
411-
Pending ({pendingList.length})
412-
</div>
410+
<div className="text-muted text-[10px]">Pending ({pendingList.length})</div>
413411
{pendingList.length > 1 && (
414412
<button
415413
type="button"
@@ -439,9 +437,7 @@ const ReviewsBannerInner: React.FC<ReviewsBannerInnerProps> = ({ workspaceId })
439437
{completedList.length > 0 && (
440438
<div className="space-y-1.5">
441439
<div className="flex items-center justify-between">
442-
<div className="text-muted text-[10px] font-medium tracking-wide uppercase">
443-
Completed ({completedList.length})
444-
</div>
440+
<div className="text-muted text-[10px]">Completed ({completedList.length})</div>
445441
{completedList.length > 0 && (
446442
<button
447443
type="button"

src/browser/components/shared/ReviewBlock.tsx

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import React, { useState, useCallback, useRef, useMemo } from "react";
10-
import { MessageSquare, X, Pencil, Check } from "lucide-react";
10+
import { MessageSquare, X, Pencil, Check, Trash2 } from "lucide-react";
1111
import { DiffRenderer } from "./DiffRenderer";
1212
import { Button } from "../ui/button";
1313
import { matchesKeybind, formatKeybind, KEYBINDS } from "@/browser/utils/ui/keybinds";
@@ -22,7 +22,12 @@ interface ReviewBlockCoreProps {
2222
lineRange: string;
2323
code: string;
2424
comment: string;
25-
onRemove?: () => void;
25+
/** Detach from chat (sets status back to pending) */
26+
onDetach?: () => void;
27+
/** Mark as complete (checked) */
28+
onComplete?: () => void;
29+
/** Permanently delete the review */
30+
onDelete?: () => void;
2631
onEditComment?: (newComment: string) => void;
2732
}
2833

@@ -34,7 +39,9 @@ const ReviewBlockCore: React.FC<ReviewBlockCoreProps> = ({
3439
lineRange,
3540
code,
3641
comment,
37-
onRemove,
42+
onDetach,
43+
onComplete,
44+
onDelete,
3845
onEditComment,
3946
}) => {
4047
const [isEditing, setIsEditing] = useState(false);
@@ -83,20 +90,42 @@ const ReviewBlockCore: React.FC<ReviewBlockCoreProps> = ({
8390

8491
return (
8592
<div className="min-w-0 overflow-hidden rounded border border-[var(--color-review-accent)]/30 bg-[var(--color-review-accent)]/5">
86-
{/* Header */}
87-
<div className="flex items-center gap-1.5 border-b border-[var(--color-review-accent)]/20 bg-[var(--color-review-accent)]/10 px-2 py-1 text-xs">
93+
{/* Header - actions left of file path (consistent with ReviewsBanner), trash on right */}
94+
<div className="flex items-center gap-1 border-b border-[var(--color-review-accent)]/20 bg-[var(--color-review-accent)]/10 px-2 py-1 text-xs">
95+
{/* Safe actions on left: complete and detach */}
96+
{onComplete && (
97+
<button
98+
type="button"
99+
onClick={onComplete}
100+
className="text-muted hover:text-success flex shrink-0 items-center justify-center rounded p-0.5 transition-colors"
101+
title="Mark as done"
102+
>
103+
<Check className="size-3" />
104+
</button>
105+
)}
106+
{onDetach && (
107+
<button
108+
type="button"
109+
onClick={onDetach}
110+
className="text-muted hover:text-secondary flex shrink-0 items-center justify-center rounded p-0.5 transition-colors"
111+
title="Detach from message"
112+
>
113+
<X className="size-3" />
114+
</button>
115+
)}
88116
<MessageSquare className="size-3 shrink-0 text-[var(--color-review-accent)]" />
89117
<span className="text-primary min-w-0 flex-1 truncate font-mono">
90118
{filePath}:{lineRange}
91119
</span>
92-
{onRemove && (
120+
{/* Destructive action on right */}
121+
{onDelete && (
93122
<button
94123
type="button"
95-
onClick={onRemove}
96-
className="text-muted hover:text-error -mr-0.5 flex shrink-0 items-center justify-center rounded p-0.5 transition-colors"
97-
title="Remove from message"
124+
onClick={onDelete}
125+
className="text-muted hover:text-error flex shrink-0 items-center justify-center rounded p-0.5 transition-colors"
126+
title="Delete review"
98127
>
99-
<X className="size-3" />
128+
<Trash2 className="size-3" />
100129
</button>
101130
)}
102131
</div>
@@ -183,8 +212,12 @@ const ReviewBlockCore: React.FC<ReviewBlockCoreProps> = ({
183212
interface ReviewBlockFromDataProps {
184213
/** Structured review data (no parsing needed) */
185214
data: ReviewNoteDataForDisplay;
186-
/** Optional callback to remove the review */
187-
onRemove?: () => void;
215+
/** Detach from chat (sets status back to pending) */
216+
onDetach?: () => void;
217+
/** Mark as complete (checked) */
218+
onComplete?: () => void;
219+
/** Permanently delete the review */
220+
onDelete?: () => void;
188221
/** Optional callback to edit the comment */
189222
onEditComment?: (newComment: string) => void;
190223
}
@@ -195,7 +228,9 @@ interface ReviewBlockFromDataProps {
195228
*/
196229
export const ReviewBlockFromData: React.FC<ReviewBlockFromDataProps> = ({
197230
data,
198-
onRemove,
231+
onDetach,
232+
onComplete,
233+
onDelete,
199234
onEditComment,
200235
}) => {
201236
return (
@@ -204,7 +239,9 @@ export const ReviewBlockFromData: React.FC<ReviewBlockFromDataProps> = ({
204239
lineRange={data.lineRange}
205240
code={data.selectedCode}
206241
comment={data.userNote}
207-
onRemove={onRemove}
242+
onDetach={onDetach}
243+
onComplete={onComplete}
244+
onDelete={onDelete}
208245
onEditComment={onEditComment}
209246
/>
210247
);

0 commit comments

Comments
 (0)