perfViz/src/components/shared/Modal.tsx
Michael Mainguy 2e533925a2 Refactor tooltip system to use centralized enum-based definitions
- Create centralized tooltip definitions with TooltipType enum
- Add comprehensive tooltip content for 31 different field types
- Include Lighthouse relationships, calculations, and documentation links
- Implement click-to-open modal system with rich content display
- Refactor Tooltip component to use enum-based content lookup
- Update RequestsTable and RequestDebugger to use simplified enum syntax
- Add Modal component with keyboard shortcuts and backdrop dismiss
- Maintain type safety with proper TypeScript interfaces
- Clean up component props by centralizing all tooltip content

Benefits:
- Single source of truth for all tooltip definitions
- Improved maintainability and consistency
- Type-safe enum usage prevents errors
- Reduced code duplication across components
- Enhanced UX with detailed modal explanations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 12:04:09 -05:00

119 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect } from 'react'
interface ModalProps {
isOpen: boolean
onClose: () => void
title: string
children: React.ReactNode
}
export function Modal({ isOpen, onClose, title, children }: ModalProps) {
// Close modal on Escape key
useEffect(() => {
const handleEscape = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
onClose()
}
}
if (isOpen) {
document.addEventListener('keydown', handleEscape)
// Prevent body scrolling when modal is open
document.body.style.overflow = 'hidden'
}
return () => {
document.removeEventListener('keydown', handleEscape)
document.body.style.overflow = 'unset'
}
}, [isOpen, onClose])
if (!isOpen) return null
return (
<div
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 10000,
padding: '20px'
}}
onClick={onClose}
>
<div
style={{
backgroundColor: 'white',
borderRadius: '8px',
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.3)',
maxWidth: '600px',
maxHeight: '80vh',
width: '100%',
overflow: 'hidden',
display: 'flex',
flexDirection: 'column'
}}
onClick={(e) => e.stopPropagation()}
>
{/* Modal Header */}
<div
style={{
padding: '20px',
borderBottom: '1px solid #e9ecef',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#f8f9fa'
}}
>
<h2 style={{ margin: 0, color: '#495057', fontSize: '18px', fontWeight: 'bold' }}>
{title}
</h2>
<button
onClick={onClose}
style={{
background: 'none',
border: 'none',
fontSize: '24px',
cursor: 'pointer',
color: '#6c757d',
padding: '0',
width: '30px',
height: '30px',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'background-color 0.2s'
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = '#e9ecef'
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'transparent'
}}
>
×
</button>
</div>
{/* Modal Content */}
<div
style={{
padding: '20px',
overflow: 'auto',
flex: 1
}}
>
{children}
</div>
</div>
</div>
)
}