/ proof-of-concept / takes
Sign in
proof-of-concept / takes
takes / src / components / Modal.tsx
70 lines · 1.7 KBCodeBlameHistory
f3253d0Takes: record, organize, and edit explainer videosJeremy Magland 1import { useEffect, type ReactNode } from 'react';
5bb2925Crop the screen and camera of each take; default output to 720pJeremy Magland 3export function Modal({
4 title,
5 onClose,
6 children,
7 footer,
8 wide,
9 className,
10}: {
11 title: string;
12 onClose: () => void;
13 children: ReactNode;
14 footer?: ReactNode;
15 wide?: boolean;
16 className?: string;
17}) {
f3253d0Takes: record, organize, and edit explainer videosJeremy Magland 18 useEffect(() => {
19 const onKey = (e: KeyboardEvent) => {
20 if (e.key === 'Escape') onClose();
21 };
22 window.addEventListener('keydown', onKey);
23 return () => window.removeEventListener('keydown', onKey);
24 }, [onClose]);
25 return (
26 <div className="modal-backdrop" onMouseDown={(e) => e.target === e.currentTarget && onClose()}>
5bb2925Crop the screen and camera of each take; default output to 720pJeremy Magland 27 <div className={`modal${wide ? ' wide' : ''}${className ? ` ${className}` : ''}`} role="dialog" aria-modal="true" aria-label={title}>
f3253d0Takes: record, organize, and edit explainer videosJeremy Magland 28 <h2>{title}</h2>
29 <div className="modal-body">{children}</div>
30 {footer && <div className="modal-footer">{footer}</div>}
31 </div>
32 </div>
33 );
36export interface ConfirmRequest {
37 title: string;
38 message: ReactNode;
39 confirmLabel: string;
40 danger?: boolean;
41 onConfirm: () => void | Promise<void>;
44export function ConfirmDialog({ req, onClose }: { req: ConfirmRequest; onClose: () => void }) {
45 return (
46 <Modal
47 title={req.title}
48 onClose={onClose}
49 footer={
50 <>
51 <button className="btn" onClick={onClose}>
52 Cancel
53 </button>
54 <button
55 className={`btn ${req.danger ? 'danger' : 'primary'}`}
56 autoFocus
57 onClick={async () => {
58 onClose();
59 await req.onConfirm();
60 }}
61 >
62 {req.confirmLabel}
63 </button>
64 </>
65 }
66 >
67 <p>{req.message}</p>
68 </Modal>
69 );
↑↓ move↵openescclose