Download desktop/src/components/shared/Modal.tsx from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 2.13 kB
-
https://huggingface.co/chenbhao/codev/resolve/e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/components/shared/Modal.tsx
- Command line
-
hf download hf://chenbhao/codev@e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/components/shared/Modal.tsx
-
curl -L -o Modal.tsx https://huggingface.co/chenbhao/codev/resolve/e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/components/shared/Modal.tsx
2.13 kB
| import { useEffect, type ReactNode } from 'react' | |
| import { createPortal } from 'react-dom' | |
| type ModalProps = { | |
| open: boolean | |
| onClose: () => void | |
| title?: string | |
| children: ReactNode | |
| width?: number | |
| footer?: ReactNode | |
| } | |
| export function Modal({ open, onClose, title, children, width = 560, footer }: ModalProps) { | |
| useEffect(() => { | |
| if (!open) return | |
| const handleEsc = (e: KeyboardEvent) => { | |
| if (e.key === 'Escape') onClose() | |
| } | |
| document.addEventListener('keydown', handleEsc) | |
| return () => document.removeEventListener('keydown', handleEsc) | |
| }, [open, onClose]) | |
| if (!open) return null | |
| return createPortal( | |
| <div className="fixed inset-0 z-50 flex items-center justify-center"> | |
| {/* Backdrop */} | |
| <div | |
| className="absolute inset-0 bg-[var(--color-overlay-scrim)] transition-opacity duration-200" | |
| onClick={onClose} | |
| /> | |
| {/* Modal content */} | |
| <div | |
| className="glass-panel relative rounded-[var(--radius-xl)] max-h-[85vh] flex flex-col" | |
| style={{ width, maxWidth: 'calc(100vw - 48px)' }} | |
| role="dialog" | |
| aria-modal="true" | |
| aria-label={title} | |
| > | |
| {title && ( | |
| <div className="flex items-start justify-between gap-4 px-6 pt-6 pb-0"> | |
| <h2 className="text-xl font-bold text-[var(--color-text-primary)]">{title}</h2> | |
| <button | |
| type="button" | |
| onClick={onClose} | |
| aria-label="Close dialog" | |
| className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)]" | |
| > | |
| <span className="material-symbols-outlined text-[18px]">close</span> | |
| </button> | |
| </div> | |
| )} | |
| <div className="px-6 py-4 overflow-y-auto flex-1"> | |
| {children} | |
| </div> | |
| {footer && ( | |
| <div className="px-6 pb-6 pt-0 flex justify-end gap-2"> | |
| {footer} | |
| </div> | |
| )} | |
| </div> | |
| </div>, | |
| document.body, | |
| ) | |
| } | |