Skip to main content
Glama
Alert.tsx5 kB
/** * Professional Alert Component with variants and auto-dismiss functionality */ import React, { useState, useEffect } from 'react'; import { cn } from '../../utils/cn'; export interface AlertProps { variant?: 'info' | 'success' | 'warning' | 'error'; title?: string; children: React.ReactNode; dismissible?: boolean; autoDismiss?: boolean; autoDismissTime?: number; onDismiss?: () => void; className?: string; icon?: React.ReactNode; } const Alert: React.FC<AlertProps> = ({ variant = 'info', title, children, dismissible = false, autoDismiss = false, autoDismissTime = 5000, onDismiss, className, icon }) => { const [visible, setVisible] = useState(true); const [isExiting, setIsExiting] = useState(false); const defaultIcons = { info: ( <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" /> </svg> ), success: ( <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" /> </svg> ), warning: ( <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" /> </svg> ), error: ( <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" /> </svg> ) }; const variantClasses = { info: { container: 'bg-blue-50 border-blue-200 text-blue-800', icon: 'text-blue-600', title: 'text-blue-900', button: 'text-blue-600 hover:bg-blue-100' }, success: { container: 'bg-green-50 border-green-200 text-green-800', icon: 'text-green-600', title: 'text-green-900', button: 'text-green-600 hover:bg-green-100' }, warning: { container: 'bg-yellow-50 border-yellow-200 text-yellow-800', icon: 'text-yellow-600', title: 'text-yellow-900', button: 'text-yellow-600 hover:bg-yellow-100' }, error: { container: 'bg-red-50 border-red-200 text-red-800', icon: 'text-red-600', title: 'text-red-900', button: 'text-red-600 hover:bg-red-100' } }; useEffect(() => { if (autoDismiss) { const timer = setTimeout(() => { handleDismiss(); }, autoDismissTime); return () => clearTimeout(timer); } }, [autoDismiss, autoDismissTime]); const handleDismiss = () => { setIsExiting(true); setTimeout(() => { setVisible(false); onDismiss?.(); }, 200); }; if (!visible) return null; const classes = cn( 'p-4', 'rounded-lg', 'border', 'flex', 'items-start', 'space-x-3', 'transition-all', 'duration-200', 'ease-in-out', isExiting ? 'opacity-0 transform -translate-y-2' : 'opacity-100 transform translate-y-0', variantClasses[variant].container, className ); return ( <div className={classes} role="alert"> <div className={cn('flex-shrink-0', variantClasses[variant].icon)}> {icon || defaultIcons[variant]} </div> <div className="flex-1 min-w-0"> {title && ( <h3 className={cn('text-sm font-medium', variantClasses[variant].title)}> {title} </h3> )} <div className="text-sm"> {children} </div> </div> {dismissible && ( <button type="button" className={cn( 'inline-flex', 'flex-shrink-0', 'p-1.5', 'rounded-md', 'focus:outline-none', 'focus:ring-2', 'focus:ring-offset-2', variantClasses[variant].button )} onClick={handleDismiss} aria-label="Dismiss" > <span className="sr-only">Dismiss</span> <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"> <path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" /> </svg> </button> )} </div> ); }; export default Alert;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DeamonDev888/Browser-Manager-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server