The Challenge
Today's challenge was to design a Flash Message component. Flash messages are brief notifications that appear temporarily to provide feedback to users about their actions or system status. They're crucial for maintaining a good user experience by keeping users informed about the results of their interactions.
My Approach
I decided to create a reusable Flash Message component using React and Tailwind CSS. The component needed to:
Support different message types (success, error, warning, info)
Auto-dismiss after a configurable duration
Allow manual dismissal
Be visually distinct based on the message type
Include appropriate icons for each type
Animate in and out smoothly
--
The implementation
First, let's create the Flash Message component using React, Tailwind CSS, and Lucide icons for a clean, modern look:
import React, { useEffect } from 'react';
import { X, CheckCircle, AlertCircle, AlertTriangle, Info } from 'lucide-react';
/**
* FlashMessage Component
* Displays a temporary notification message that automatically dismisses after a specified duration.
*
* @param {Object} props
* @param {string} props.message - The message to display in the flash notification
* @param {('info'|'success'|'error'|'warning')} [props.type='info'] - The type of message which determines its styling
* @param {number} [props.duration=5000] - Duration in milliseconds before the message auto-dismisses
* @param {Function} props.onDismiss - Callback function to execute when the message is dismissed
*/
const FlashMessage = ({
message,
type = 'info',
duration = 5000,
onDismiss
}) => {
// Set up auto-dismiss timer
useEffect(() => {
// Only set timer if duration is provided
if (duration !== null) {
const timer = setTimeout(() => {
onDismiss();
}, duration);
// Cleanup timer on component unmount or when duration/onDismiss changes
return () => clearTimeout(timer);
}
}, [duration, onDismiss]);
/**
* Returns the appropriate icon component based on message type
* @returns {React.ReactElement} Icon component
*/
const getIcon = () => {
switch (type) {
case 'success':
return <CheckCircle className="w-5 h-5" />;
case 'error':
return <AlertCircle className="w-5 h-5" />;
case 'warning':
return <AlertTriangle className="w-5 h-5" />;
default:
return <Info className="w-5 h-5" />;
}
};
/**
* Returns the appropriate Tailwind CSS classes based on message type
* @returns {string} Combined CSS classes
*/
const getStyles = () => {
// Base styles applied to all message types
const baseStyles = "fixed top-4 right-4 flex items-center gap-2 p-4 rounded-lg shadow-lg";
// Add type-specific styling
switch (type) {
case 'success':
return `${baseStyles} bg-green-100 text-green-800 border border-green-200`;
case 'error':
return `${baseStyles} bg-red-100 text-red-800 border border-red-200`;
case 'warning':
return `${baseStyles} bg-yellow-100 text-yellow-800 border border-yellow-200`;
default: // info
return `${baseStyles} bg-blue-100 text-blue-800 border border-blue-200`;
}
};
// Render the flash message with appropriate styling and icon
return (
<div className={getStyles()}>
{getIcon()}
<span className="text-sm font-medium">{message}</span>
{/* Dismiss button */}
<button
onClick={onDismiss}
className="ml-2 p-1 hover:bg-black/5 rounded-full transition-colors"
>
<X className="w-4 h-4" />
</button>
</div>
);
};
export default FlashMessage;
To demonstrate the Flash Message component in action, here's a simple demo page:
import React, { useState } from 'react';
import FlashMessage from './FlashMessage';
/**
* Demo Component
* Demonstrates the usage of the FlashMessage component with different message types.
* Includes buttons to trigger different types of flash messages.
*/
const Demo = () => {
// State to manage the currently displayed flash message
const [flash, setFlash] = useState(null);
/**
* Shows a flash message of the specified type
* @param {('success'|'error'|'warning'|'info')} type - The type of flash message to display
*/
const showFlash = (type) => {
setFlash({
type,
message: `This is a ${type} message!`,
});
};
return (
<div className="p-8">
{/* Container for flash message trigger buttons */}
<div className="space-x-4">
{/* Success message button */}
<button
onClick={() => showFlash('success')}
className="px-4 py-2 bg-green-500 text-white rounded-lg"
>
Show Success
</button>
{/* Error message button */}
<button
onClick={() => showFlash('error')}
className="px-4 py-2 bg-red-500 text-white rounded-lg"
>
Show Error
</button>
{/* Warning message button */}
<button
onClick={() => showFlash('warning')}
className="px-4 py-2 bg-yellow-500 text-white rounded-lg"
>
Show Warning
</button>
{/* Info message button */}
<button
onClick={() => showFlash('info')}
className="px-4 py-2 bg-blue-500 text-white rounded-lg"
>
Show Info
</button>
</div>
{/* Render FlashMessage component when flash state is set */}
{flash && (
<FlashMessage
type={flash.type}
message={flash.message}
onDismiss={() => setFlash(null)} // Reset flash state to remove message
/>
)}
</div>
);
};
export default Demo;
--
Key Features
Type-based Styling: Each message type has its own color scheme and icon for clear visual distinction
Auto-dismiss: Messages automatically disappear after 5 seconds (configurable)
Manual Dismiss: Users can click the X button to dismiss messages early
Responsive Design: Works well on all screen sizes
Accessibility: Uses semantic HTML and provides clear visual feedback
Smooth Animations: Transitions smoothly when appearing and disappearing
Next Steps
Add support for stacking multiple messages
Implement more sophisticated animationsAdd support for custom icons
Create a context-based system for showing messages from anywhere in the app
Add support for actions within the message (e.g., Undo button)
Conclusion
Flash Messages are crucial to modern web applications, providing immediate feedback to users about their actions. This implementation provides a solid foundation that can be easily extended and customized for different use cases.
--
This is Day 10 of the Daily UI Challenge, 10 percent of the challenge completed! Check back tomorrow for the next challenge!
Top comments (0)