mitai-jinkendo/frontend/src/components/Toast.jsx
Lars 3541c416f9
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Build Test / pytest-backend (push) Successful in 8s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 16s
feat: Workflow Editor UX improvements - validation and notifications
**Problem 1: Validation footer covers mobile menu**
- Fixed bottom validation panel (z-index 1000) overlapped mobile nav
- Solution: Removed bottom panel, added inline validation in config panel header

**Problem 2: Alert dialogs for save success**
- alert() blocks UI and requires OK click for every save
- Solution: Toast notifications (auto-close after 3s, non-blocking)

**Problem 3: Validation shows only counts, not details**
- Footer showed "1 Error, 2 Warnings" without details
- Solution: Inline display shows all error/warning messages with click-to-navigate

**New Components:**
- Toast.jsx: Auto-closing notifications (success/error/warning/info)
- ConfirmDialog.jsx: Modal confirmation dialogs (for future save-on-close)

**Changes:**
- WorkflowEditorPage: Inline validation in config panel, toast state
- Removed fixed bottom .validation-panel (no mobile overlap)
- Toast for save success instead of alert()

**Still TODO (separate commit):**
- Save confirmation when closing/switching nodes with unsaved changes
- Dirty state tracking

Part 3: Inline Prompts - UX polish (validation + notifications)
2026-04-11 10:48:28 +02:00

96 lines
2.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect } from 'react'
/**
* Toast Notification Component
*
* Auto-closing notification that appears at the top of the screen
*
* Props:
* - message: string
* - type: 'success' | 'error' | 'warning' | 'info'
* - duration: number (ms, default 3000)
* - onClose: callback when toast closes
*/
export function Toast({ message, type = 'info', duration = 3000, onClose }) {
useEffect(() => {
const timer = setTimeout(() => {
if (onClose) onClose()
}, duration)
return () => clearTimeout(timer)
}, [duration, onClose])
const styles = {
success: {
background: '#4CAF50',
color: 'white',
icon: '✅'
},
error: {
background: 'var(--danger)',
color: 'white',
icon: '❌'
},
warning: {
background: '#FFC107',
color: '#856404',
icon: '⚠️'
},
info: {
background: 'var(--accent)',
color: 'white',
icon: ''
}
}
const style = styles[type] || styles.info
return (
<div
style={{
position: 'fixed',
top: '80px',
left: '50%',
transform: 'translateX(-50%)',
background: style.background,
color: style.color,
padding: '12px 24px',
borderRadius: '8px',
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
zIndex: 10000,
display: 'flex',
alignItems: 'center',
gap: '8px',
fontSize: '14px',
fontWeight: 500,
minWidth: '300px',
maxWidth: '600px',
animation: 'slideDown 0.3s ease-out'
}}
onClick={onClose}
>
<span style={{ fontSize: '18px' }}>{style.icon}</span>
<span>{message}</span>
</div>
)
}
// Add animation CSS if not already in global styles
const styleElement = document.createElement('style')
styleElement.textContent = `
@keyframes slideDown {
from {
opacity: 0;
transform: translateX(-50%) translateY(-20px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
`
if (!document.querySelector('style[data-toast-styles]')) {
styleElement.setAttribute('data-toast-styles', 'true')
document.head.appendChild(styleElement)
}