fix: clipboard error handling, Escape key support, per-notification read state
This commit is contained in:
@@ -27,8 +27,12 @@ const quickStart: { step: number; text: string }[] = [
|
||||
const HelpPanel: React.FC<HelpPanelProps> = ({ open, onClose }) => {
|
||||
if (!open) return null;
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Escape') onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="modal-backdrop" onClick={onClose}>
|
||||
<div className="modal-backdrop" onClick={onClose} onKeyDown={handleKeyDown} tabIndex={-1}>
|
||||
<div className="modal-panel help-panel" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<h2>Hilfe</h2>
|
||||
|
||||
@@ -6,17 +6,17 @@ interface Notification {
|
||||
icon: string;
|
||||
title: string;
|
||||
timestamp: string;
|
||||
read: boolean;
|
||||
}
|
||||
|
||||
const initialNotifications: Notification[] = [
|
||||
{ id: 'n1', icon: '💾', title: 'Projekt automatisch gespeichert', timestamp: 'vor 2 Min.' },
|
||||
{ id: 'n2', icon: '🔄', title: 'Neue Version verfügbar', timestamp: 'vor 15 Min.' },
|
||||
{ id: 'n3', icon: '👤', title: 'Benutzer ist beigetreten', timestamp: 'vor 1 Std.' },
|
||||
{ id: 'n1', icon: '💾', title: 'Projekt automatisch gespeichert', timestamp: 'vor 2 Min.', read: false },
|
||||
{ id: 'n2', icon: '🔄', title: 'Neue Version verfügbar', timestamp: 'vor 15 Min.', read: false },
|
||||
{ id: 'n3', icon: '👤', title: 'Benutzer ist beigetreten', timestamp: 'vor 1 Std.', read: false },
|
||||
];
|
||||
|
||||
const NotificationPanel: React.FC<NotificationPanelProps> = ({ open, onClose }) => {
|
||||
const [notifications, setNotifications] = useState<Notification[]>(initialNotifications);
|
||||
const [allRead, setAllRead] = useState(false);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -26,8 +26,15 @@ const NotificationPanel: React.FC<NotificationPanelProps> = ({ open, onClose })
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') onClose();
|
||||
};
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [open, onClose]);
|
||||
|
||||
if (!open) return null;
|
||||
@@ -37,7 +44,7 @@ const NotificationPanel: React.FC<NotificationPanelProps> = ({ open, onClose })
|
||||
};
|
||||
|
||||
const handleMarkAllRead = () => {
|
||||
setAllRead(true);
|
||||
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -53,7 +60,7 @@ const NotificationPanel: React.FC<NotificationPanelProps> = ({ open, onClose })
|
||||
<p className="notif-empty">Keine Benachrichtigungen</p>
|
||||
) : (
|
||||
notifications.map((n) => (
|
||||
<div key={n.id} className={`notif-item ${allRead ? 'read' : ''}`}>
|
||||
<div key={n.id} className={`notif-item ${n.read ? 'read' : ''}`}>
|
||||
<span className="notif-icon">{n.icon}</span>
|
||||
<div className="notif-content">
|
||||
<span className="notif-title">{n.title}</span>
|
||||
|
||||
@@ -14,9 +14,15 @@ const ShareDialog: React.FC<ShareDialogProps> = ({ open, onClose, projectName })
|
||||
navigator.clipboard.writeText(shareLink).then(() => {
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
}).catch(() => {
|
||||
setCopied(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Escape') onClose();
|
||||
};
|
||||
|
||||
const handleInvite = () => {
|
||||
if (email.trim()) {
|
||||
setInvited(true);
|
||||
@@ -26,7 +32,7 @@ const ShareDialog: React.FC<ShareDialogProps> = ({ open, onClose, projectName })
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="modal-backdrop" onClick={onClose}>
|
||||
<div className="modal-backdrop" onClick={onClose} onKeyDown={handleKeyDown} tabIndex={-1}>
|
||||
<div className="modal-panel share-dialog" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<h2>Projekt teilen</h2>
|
||||
|
||||
Reference in New Issue
Block a user