SexyAnalysisReviewPill.tsx3.2 KBView on GitHub /**
* AnalysisReviewPill Component
*
* Pill-shaped sticky notification that appears at the bottom of the conversation canvas
* when there are completed analyses ready for review. Clicking opens the analysis review modal.
*/
import { motion, AnimatePresence } from 'motion/react';
import { ChevronRight, FileText, X } from 'lucide-react';
import { useState } from 'react';
export interface AnalysisReviewPillProps {
/** Number of completed analyses ready to review */
pendingCount: number;
/** Callback when the pill is clicked */
onOpenReview: () => void;
/** Callback to clear all analyses */
onClear: () => void;
}
export function AnalysisReviewPill({ pendingCount, onOpenReview, onClear }: AnalysisReviewPillProps) {
const [reviewHovered, setReviewHovered] = useState(false);
const [clearHovered, setClearHovered] = useState(false);
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">
{/* Clear pill */}
<button
onClick={onClear}
onMouseEnter={() => setClearHovered(true)}
onMouseLeave={() => setClearHovered(false)}
className="flex cursor-pointer items-center gap-2.5 overflow-hidden rounded-full bg-foreground px-4 py-2 shadow-md text-sm font-medium text-white transition-all duration-200 hover:bg-red-400"
>
<motion.div
animate={clearHovered ? { rotate: 90, scale: 1.2 } : { rotate: 0, scale: 1 }}
transition={{ duration: 0.2, ease: 'easeInOut' }}
>
<X className="h-4 w-4" />
</motion.div>
Clear
</button>
{/* Main pill (primary CTA) */}
<button
onClick={onOpenReview}
onMouseEnter={() => setReviewHovered(true)}
onMouseLeave={() => setReviewHovered(false)}
className="group flex cursor-pointer items-center gap-2.5 overflow-hidden rounded-full bg-foreground px-4 py-2 shadow-md transition-all duration-200 hover:bg-foreground/90"
>
<FileText className="h-4 w-4 text-white" />
<span className="rounded-full bg-white/20 px-1.5 py-0.5 text-xs font-medium text-white">
{pendingCount}
</span>
<span className="text-sm font-medium text-white">
Review {pendingCount !== 1 ? 'Analyses' : 'Analysis'}
</span>
<motion.div
animate={reviewHovered ? { x: 24, opacity: 0, scale: 1.4, color: '#ffffff' } : { x: 0, opacity: 1, scale: 1, color: 'rgba(255,255,255,0.7)' }}
transition={{ duration: 0.18, ease: 'easeIn' }}
>
<ChevronRight className="h-4 w-4" />
</motion.div>
</button>
</div>
</motion.div>
)}
</AnimatePresence>
);
}