- HelpTooltip-Komponente verwendet jetzt ℹ statt ?
- Help-Button im Header verwendet jetzt ℹ statt ❓
- Konsistenteres Design mit Informations-Icon
176 lines
7.5 KiB
TypeScript
176 lines
7.5 KiB
TypeScript
'use client';
|
||
|
||
import { useState, useRef, useEffect } from 'react';
|
||
import { useTranslations } from 'next-intl';
|
||
|
||
interface HelpTooltipProps {
|
||
shortText: string; // Text für Hover
|
||
longText: string; // Text für Click/Modal
|
||
position?: 'top' | 'bottom' | 'left' | 'right';
|
||
}
|
||
|
||
export default function HelpTooltip({ shortText, longText, position = 'top' }: HelpTooltipProps) {
|
||
const t = useTranslations('CuratorHelp');
|
||
const [showHover, setShowHover] = useState(false);
|
||
const [showModal, setShowModal] = useState(false);
|
||
const tooltipRef = useRef<HTMLDivElement>(null);
|
||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||
|
||
useEffect(() => {
|
||
function handleClickOutside(event: MouseEvent) {
|
||
if (
|
||
tooltipRef.current &&
|
||
!tooltipRef.current.contains(event.target as Node) &&
|
||
buttonRef.current &&
|
||
!buttonRef.current.contains(event.target as Node)
|
||
) {
|
||
setShowModal(false);
|
||
}
|
||
}
|
||
|
||
if (showModal) {
|
||
document.addEventListener('mousedown', handleClickOutside);
|
||
return () => {
|
||
document.removeEventListener('mousedown', handleClickOutside);
|
||
};
|
||
}
|
||
}, [showModal]);
|
||
|
||
const positionStyles = {
|
||
top: { bottom: '100%', left: '50%', transform: 'translateX(-50%)', marginBottom: '0.5rem' },
|
||
bottom: { top: '100%', left: '50%', transform: 'translateX(-50%)', marginTop: '0.5rem' },
|
||
left: { right: '100%', top: '50%', transform: 'translateY(-50%)', marginRight: '0.5rem' },
|
||
right: { left: '100%', top: '50%', transform: 'translateY(-50%)', marginLeft: '0.5rem' },
|
||
};
|
||
|
||
return (
|
||
<div style={{ position: 'relative', display: 'inline-block' }}>
|
||
<button
|
||
ref={buttonRef}
|
||
type="button"
|
||
onClick={() => setShowModal(!showModal)}
|
||
onMouseEnter={() => setShowHover(true)}
|
||
onMouseLeave={() => setShowHover(false)}
|
||
style={{
|
||
background: 'none',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
color: '#6b7280',
|
||
fontSize: '1rem',
|
||
padding: '0.25rem',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
borderRadius: '50%',
|
||
width: '1.5rem',
|
||
height: '1.5rem',
|
||
transition: 'background-color 0.2s',
|
||
}}
|
||
onMouseOver={(e) => {
|
||
e.currentTarget.style.backgroundColor = '#f3f4f6';
|
||
}}
|
||
onMouseOut={(e) => {
|
||
e.currentTarget.style.backgroundColor = 'transparent';
|
||
}}
|
||
aria-label="Help"
|
||
>
|
||
ℹ
|
||
</button>
|
||
|
||
{/* Hover Tooltip */}
|
||
{showHover && !showModal && (
|
||
<div
|
||
ref={tooltipRef}
|
||
style={{
|
||
position: 'absolute',
|
||
...positionStyles[position],
|
||
background: '#1f2937',
|
||
color: 'white',
|
||
padding: '0.5rem 0.75rem',
|
||
borderRadius: '0.375rem',
|
||
fontSize: '0.875rem',
|
||
whiteSpace: 'normal',
|
||
zIndex: 1000,
|
||
pointerEvents: 'none',
|
||
maxWidth: '250px',
|
||
}}
|
||
>
|
||
{shortText}
|
||
<div
|
||
style={{
|
||
position: 'absolute',
|
||
...(position === 'top' && { top: '100%', left: '50%', transform: 'translateX(-50%)', borderLeft: '6px solid transparent', borderRight: '6px solid transparent', borderTop: '6px solid #1f2937' }),
|
||
...(position === 'bottom' && { bottom: '100%', left: '50%', transform: 'translateX(-50%)', borderLeft: '6px solid transparent', borderRight: '6px solid transparent', borderBottom: '6px solid #1f2937' }),
|
||
...(position === 'left' && { left: '100%', top: '50%', transform: 'translateY(-50%)', borderTop: '6px solid transparent', borderBottom: '6px solid transparent', borderLeft: '6px solid #1f2937' }),
|
||
...(position === 'right' && { right: '100%', top: '50%', transform: 'translateY(-50%)', borderTop: '6px solid transparent', borderBottom: '6px solid transparent', borderRight: '6px solid #1f2937' }),
|
||
}}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Modal für detaillierte Informationen */}
|
||
{showModal && (
|
||
<>
|
||
{/* Overlay */}
|
||
<div
|
||
style={{
|
||
position: 'fixed',
|
||
top: 0,
|
||
left: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
background: 'rgba(0, 0, 0, 0.5)',
|
||
zIndex: 9998,
|
||
}}
|
||
onClick={() => setShowModal(false)}
|
||
/>
|
||
{/* Modal Content */}
|
||
<div
|
||
ref={tooltipRef}
|
||
style={{
|
||
position: 'fixed',
|
||
top: '50%',
|
||
left: '50%',
|
||
transform: 'translate(-50%, -50%)',
|
||
background: 'white',
|
||
padding: '1.5rem',
|
||
borderRadius: '0.5rem',
|
||
boxShadow: '0 10px 25px rgba(0, 0, 0, 0.2)',
|
||
maxWidth: '500px',
|
||
width: '90%',
|
||
maxHeight: '80vh',
|
||
overflowY: 'auto',
|
||
zIndex: 9999,
|
||
}}
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', marginBottom: '1rem' }}>
|
||
<h3 style={{ margin: 0, fontSize: '1.25rem', fontWeight: 'bold' }}>{t('modalTitle')}</h3>
|
||
<button
|
||
type="button"
|
||
onClick={() => setShowModal(false)}
|
||
style={{
|
||
background: 'none',
|
||
border: 'none',
|
||
fontSize: '1.5rem',
|
||
cursor: 'pointer',
|
||
color: '#6b7280',
|
||
padding: '0',
|
||
lineHeight: '1',
|
||
}}
|
||
aria-label="Close"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<div style={{ fontSize: '0.9rem', lineHeight: '1.6', whiteSpace: 'pre-wrap' }}>
|
||
{longText}
|
||
</div>
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|