<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
<div class="container">
<div class="header">
<h1>Ant Design Notifications</h1>
<p>Professional notification system with CSS animations</p>
</div>
<div class="section-title">
<ion-icon name="notifications-outline"></ion-icon>
Notification Types
</div>
<div class="controls">
<button class="btn btn-success" onclick="showNotification('success')">
<ion-icon name="checkmark-circle-outline"></ion-icon>
Success
</button>
<button class="btn btn-info" onclick="showNotification('info')">
<ion-icon name="information-circle-outline"></ion-icon>
Info
</button>
<button class="btn btn-warning" onclick="showNotification('warning')">
<ion-icon name="warning-outline"></ion-icon>
Warning
</button>
<button class="btn btn-error" onclick="showNotification('error')">
<ion-icon name="close-circle-outline"></ion-icon>
Error
</button>
</div>
<div class="section-title">
<ion-icon name="locate-outline"></ion-icon>
Notification Position
</div>
<div class="positions">
<button class="position-btn active" data-position="top-right" onclick="setPosition(this)">
Top Right
</button>
<button class="position-btn" data-position="top-center" onclick="setPosition(this)">
Top Center
</button>
<button class="position-btn" data-position="top-left" onclick="setPosition(this)">
Top Left
</button>
<button class="position-btn" data-position="bottom-right" onclick="setPosition(this)">
Bottom Right
</button>
<button class="position-btn" data-position="bottom-center" onclick="setPosition(this)">
Bottom Center
</button>
<button class="position-btn" data-position="bottom-left" onclick="setPosition(this)">
Bottom Left
</button>
</div>
<div class="demo-info">
<strong>💡 Features:</strong> Auto-dismiss after 5 seconds, progress bar, smooth animations, manual close, and multiple position options. Click any button above to see notifications in action!
</div>
</div>
<div id="notificationContainer" class="notification-container top-right"></div>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #003566 0%, #004d87 100%);
min-height: 100vh;
padding: 2rem;
display: flex;
align-items: center;
justify-content: center;
}
.container {
background: white;
padding: 3rem 2.5rem;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0, 53, 102, 0.3);
max-width: 800px;
width: 100%;
}
.header {
text-align: center;
margin-bottom: 3rem;
}
.header h1 {
color: #003566;
font-size: 2rem;
margin-bottom: 0.5rem;
}
.header p {
color: #6c757d;
font-size: 1rem;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.btn {
padding: 1rem 1.5rem;
border: none;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.btn ion-icon {
font-size: 1.25rem;
}
.btn-success {
background: #52c41a;
color: white;
}
.btn-info {
background: #003566;
color: white;
}
.btn-warning {
background: #faad14;
color: white;
}
.btn-error {
background: #ff4d4f;
color: white;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
}
.btn:active {
transform: translateY(0);
}
.positions {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin-bottom: 2rem;
}
.position-btn {
padding: 0.75rem;
background: #f5f5f5;
border: 2px solid #d9d9d9;
border-radius: 6px;
cursor: pointer;
font-size: 0.875rem;
font-weight: 500;
transition: all 0.3s ease;
color: #595959;
}
.position-btn.active {
background: #003566;
color: white;
border-color: #003566;
}
.position-btn:hover {
border-color: #003566;
}
.section-title {
font-size: 1.125rem;
color: #003566;
font-weight: 600;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
/* Notification Container */
.notification-container {
position: fixed;
z-index: 9999;
pointer-events: none;
}
.notification-container.top-right {
top: 24px;
right: 24px;
}
.notification-container.top-left {
top: 24px;
left: 24px;
}
.notification-container.bottom-right {
bottom: 24px;
right: 24px;
}
.notification-container.bottom-left {
bottom: 24px;
left: 24px;
}
.notification-container.top-center {
top: 24px;
left: 50%;
transform: translateX(-50%);
}
.notification-container.bottom-center {
bottom: 24px;
left: 50%;
transform: translateX(-50%);
}
/* Notification Card */
.notification {
background: white;
border-radius: 8px;
box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
padding: 16px 24px;
margin-bottom: 16px;
min-width: 384px;
max-width: 384px;
pointer-events: auto;
display: flex;
align-items: flex-start;
gap: 12px;
position: relative;
overflow: hidden;
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.notification.slide-out {
animation: slideOut 0.3s ease-out forwards;
}
@keyframes slideOut {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(100%);
}
}
.notification-icon {
font-size: 24px;
flex-shrink: 0;
margin-top: 2px;
}
.notification-icon.success {
color: #52c41a;
}
.notification-icon.info {
color: #003566;
}
.notification-icon.warning {
color: #faad14;
}
.notification-icon.error {
color: #ff4d4f;
}
.notification-content {
flex: 1;
}
.notification-title {
font-size: 16px;
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
margin-bottom: 4px;
line-height: 1.5;
}
.notification-description {
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
line-height: 1.5;
}
.notification-close {
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
cursor: pointer;
flex-shrink: 0;
transition: color 0.3s ease;
margin-top: 2px;
}
.notification-close:hover {
color: rgba(0, 0, 0, 0.85);
}
.notification-progress {
position: absolute;
bottom: 0;
left: 0;
height: 3px;
background: #003566;
animation: progress 4.5s linear;
}
@keyframes progress {
from {
width: 100%;
}
to {
width: 0%;
}
}
.notification.success .notification-progress {
background: #52c41a;
}
.notification.warning .notification-progress {
background: #faad14;
}
.notification.error .notification-progress {
background: #ff4d4f;
}
/* Responsive */
@media (max-width: 768px) {
.notification {
min-width: calc(100vw - 48px);
max-width: calc(100vw - 48px);
}
.controls {
grid-template-columns: 1fr;
}
.positions {
grid-template-columns: repeat(2, 1fr);
}
}
.demo-info {
background: #f0f5ff;
border: 1px solid #adc6ff;
border-radius: 8px;
padding: 1rem;
margin-top: 2rem;
font-size: 0.875rem;
color: #003566;
}
let currentPosition = 'top-right';
let notificationId = 0;
const notificationConfig = {
success: {
icon: 'checkmark-circle',
title: 'Success',
description: 'Your operation has been completed successfully!'
},
info: {
icon: 'information-circle',
title: 'Information',
description: 'This is an informational message for your attention.'
},
warning: {
icon: 'warning',
title: 'Warning',
description: 'Please be cautious! This action requires your attention.'
},
error: {
icon: 'close-circle',
title: 'Error',
description: 'Something went wrong. Please try again later.'
}
};
function setPosition(button) {
document.querySelectorAll('.position-btn').forEach(btn => {
btn.classList.remove('active');
});
button.classList.add('active');
currentPosition = button.dataset.position;
const container = document.getElementById('notificationContainer');
container.className = `notification-container ${currentPosition}`;
}
function showNotification(type) {
const config = notificationConfig[type];
const id = `notification-${notificationId++}`;
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.id = id;
notification.innerHTML = `
<div class="notification-icon ${type}">
<ion-icon name="${config.icon}"></ion-icon>
</div>
<div class="notification-content">
<div class="notification-title">${config.title}</div>
<div class="notification-description">${config.description}</div>
</div>
<div class="notification-close" onclick="closeNotification('${id}')">
<ion-icon name="close"></ion-icon>
</div>
<div class="notification-progress"></div>
`;
const container = document.getElementById('notificationContainer');
// Add to top or bottom based on position
if (currentPosition.includes('top')) {
container.appendChild(notification);
} else {
container.insertBefore(notification, container.firstChild);
}
// Auto dismiss after 5 seconds
setTimeout(() => {
closeNotification(id);
}, 5000);
}
function closeNotification(id) {
const notification = document.getElementById(id);
if (notification) {
notification.classList.add('slide-out');
setTimeout(() => {
notification.remove();
}, 300);
}
}
// Demo: Show a welcome notification
window.addEventListener('load', () => {
setTimeout(() => {
showNotification('info');
}, 500);
});
No comments yet. Be the first!