feat: modal windows
This commit is contained in:
77
src/components/SubscriptionQrModal.tsx
Normal file
77
src/components/SubscriptionQrModal.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
interface SubscriptionQrModalProps {
|
||||
link: string | null;
|
||||
label?: string;
|
||||
imageAlt?: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function SubscriptionQrModal({
|
||||
link,
|
||||
label = 'Ссылка подписки',
|
||||
imageAlt = 'QR-код ссылки подписки',
|
||||
onClose,
|
||||
}: SubscriptionQrModalProps) {
|
||||
const [image, setImage] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!link) return;
|
||||
|
||||
let active = true;
|
||||
void QRCode.toDataURL(link, {
|
||||
errorCorrectionLevel: 'M',
|
||||
margin: 2,
|
||||
width: 280,
|
||||
color: { dark: '#1a1610', light: '#faf7f2' },
|
||||
})
|
||||
.then((dataUrl) => {
|
||||
if (active) setImage(dataUrl);
|
||||
})
|
||||
.catch(() => {
|
||||
if (active) setImage(null);
|
||||
});
|
||||
|
||||
const onKey = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') onClose();
|
||||
};
|
||||
document.addEventListener('keydown', onKey);
|
||||
document.body.style.overflow = 'hidden';
|
||||
return () => {
|
||||
active = false;
|
||||
document.removeEventListener('keydown', onKey);
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
}, [link, onClose]);
|
||||
|
||||
if (!link) return null;
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
className="modal-veil is-open"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="subscription-qr-title"
|
||||
onClick={(event) => {
|
||||
if (event.target === event.currentTarget) onClose();
|
||||
}}
|
||||
>
|
||||
<div className="modal subscription-qr-modal" role="document">
|
||||
<div className="modal-kicker">{label}</div>
|
||||
<h3 className="modal-title" id="subscription-qr-title">
|
||||
Откройте на устройстве
|
||||
</h3>
|
||||
<p className="modal-body">Отсканируйте код камерой или приложением Malenia.</p>
|
||||
<div className="subscription-qr-image">
|
||||
{image ? <img src={image} alt={imageAlt} /> : <span>Генерируем QR-код</span>}
|
||||
</div>
|
||||
<button type="button" className="btn" onClick={onClose} autoFocus>
|
||||
Закрыть
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user