DraftReviewPill.tsx3.1 KBView on GitHub /**
* DraftReviewPill Component
*
* Pill-shaped sticky notification that appears at the bottom of the conversation canvas
* when there are drafts ready for review. Clicking opens review mode.
*/
import { motion, AnimatePresence } from 'motion/react';
import { ChevronRight, Check, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
export interface DraftReviewPillProps {
/** Number of pending drafts */
pendingCount: number;
/** Callback when the pill is clicked */
onOpenReview: () => void;
/** Callback to accept all drafts */
onAcceptAll: () => void;
/** Callback to reject all drafts */
onRejectAll: () => void;
}
export function DraftReviewPill({
pendingCount,
onOpenReview,
onAcceptAll,
onRejectAll,
}: DraftReviewPillProps) {
return (
<AnimatePresence>
{pendingCount > 0 && (
<motion.div
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
transition={{ type: 'spring', damping: 25, stiffness: 300 }}
className="absolute bottom-4 left-1/2 z-10 -translate-x-1/2"
>
<div className="flex items-center gap-2 rounded-full border border-border bg-card px-2 py-2 shadow-md">
{/* Reject All button */}
<Button
variant="ghost"
size="sm"
onClick={(e) => {
e.stopPropagation();
onRejectAll();
}}
className="h-7 rounded-full cursor-pointer text-muted-foreground hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-950/50"
>
<X className="mr-1 h-3.5 w-3.5" />
Reject All
</Button>
{/* Main pill content (click to open review) - Primary action */}
<button
onClick={onOpenReview}
className="group flex cursor-pointer items-center gap-2.5 rounded-full bg-foreground px-3 py-1.5 transition-all duration-200 hover:bg-foreground/90"
>
<div className="flex items-center gap-2">
<div className="flex h-5 w-5 items-center justify-center rounded-full bg-background text-xs font-semibold text-foreground">
{pendingCount}
</div>
<span className="text-sm font-medium text-background">
Review Draft{pendingCount !== 1 ? 's' : ''}
</span>
</div>
<ChevronRight className="h-4 w-4 text-background/70 transition-colors group-hover:text-background" />
</button>
{/* Accept All button */}
<Button
variant="ghost"
size="sm"
onClick={(e) => {
e.stopPropagation();
onAcceptAll();
}}
className="h-7 rounded-full cursor-pointer hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-950/50"
>
<Check className="mr-1 h-3.5 w-3.5" />
Save All
</Button>
</div>
</motion.div>
)}
</AnimatePresence>
);
}