react-vite-themes
Version:
A test/experimental React theme system created for learning purposes. Features atomic design components, SCSS variables, and dark/light theme support. Not intended for production use.
73 lines (72 loc) • 3.28 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useEffect, useState, useCallback } from 'react';
import { cn } from '../../../utils';
import { Icon } from '../Icon';
// Helper function to get appropriate icon for variant
const getIconForVariant = (variant) => {
// Map gradient variants to appropriate icons
if (variant.startsWith('gradient-')) {
const gradientType = variant.replace('gradient-', '');
switch (gradientType) {
case 'primary':
case 'secondary':
return 'info';
case 'wizard':
return 'star';
case 'sunset':
case 'sunset-triple':
return 'star';
case 'ocean':
case 'ocean-deep':
return 'activity';
case 'forest':
case 'forest-rich':
return 'target';
case 'fire':
return 'zap';
case 'cosmic':
case 'cosmic-vibrant':
return 'star';
case 'aurora':
return 'star';
case 'rainbow':
case 'rainbow-burst':
return 'palette';
case 'custom-gradient':
return 'palette';
default:
return 'info';
}
}
// For non-gradient variants, use the variant name as icon
return variant;
};
export const Alert = ({ variant = 'info', size = 'md', title, children, className, isClosable = false, autoDismiss = false, dismissDelay = 5000, icon = 'info', onClose, onDismiss, ...props }) => {
const [isVisible, setIsVisible] = useState(true);
const [isDismissing, setIsDismissing] = useState(false);
const handleClose = () => {
setIsDismissing(true);
setTimeout(() => {
setIsVisible(false);
onClose?.();
}, 200); // Match transition duration
};
const handleDismiss = useCallback(() => {
setIsDismissing(true);
setTimeout(() => {
setIsVisible(false);
onDismiss?.();
}, 200);
}, [onDismiss]);
useEffect(() => {
if (autoDismiss && dismissDelay > 0) {
const timer = setTimeout(handleDismiss, dismissDelay);
return () => clearTimeout(timer);
}
}, [autoDismiss, dismissDelay, handleDismiss]);
if (!isVisible)
return null;
// Use provided icon or fall back to default icon logic
const iconName = icon || getIconForVariant(variant);
return (_jsxs("div", { className: cn('alert', `alert--${variant}`, `alert--${size}`, isDismissing && 'alert--dismissing', className), role: "alert", "aria-live": "polite", ...props, children: [_jsxs("div", { className: "alert__content", children: [_jsx("div", { className: "alert__icon", children: _jsx(Icon, { name: iconName, size: size }) }), _jsxs("div", { className: "alert__body", children: [title && _jsx("div", { className: "alert__title", children: title }), _jsx("div", { className: "alert__message", children: children })] })] }), isClosable && (_jsx("button", { className: "alert__close", onClick: handleClose, "aria-label": "Close alert", type: "button", children: _jsx(Icon, { name: "close", size: "sm" }) }))] }));
};