feat: add fullscreen toggle to Modal, enable in NodeEditorModal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useCallback, type ReactNode } from 'react'
|
||||
import { X } from 'lucide-react'
|
||||
import { useState, useEffect, useCallback, type ReactNode } from 'react'
|
||||
import { X, Maximize2, Minimize2 } from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface ModalProps {
|
||||
@@ -10,9 +10,28 @@ interface ModalProps {
|
||||
/** Optional footer content that stays fixed at bottom (doesn't scroll) */
|
||||
footer?: ReactNode
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl'
|
||||
/** If true, a fullscreen toggle button appears in the modal header */
|
||||
allowFullScreen?: boolean
|
||||
}
|
||||
|
||||
export function Modal({ isOpen, onClose, title, children, footer, size = 'md' }: ModalProps) {
|
||||
export function Modal({ isOpen, onClose, title, children, footer, size = 'md', allowFullScreen = false }: ModalProps) {
|
||||
const [isFullScreen, setIsFullScreen] = useState(() => {
|
||||
if (!allowFullScreen) return false
|
||||
try {
|
||||
return localStorage.getItem('rf-editor-fullscreen') === 'true'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
const toggleFullScreen = () => {
|
||||
const next = !isFullScreen
|
||||
setIsFullScreen(next)
|
||||
try {
|
||||
localStorage.setItem('rf-editor-fullscreen', String(next))
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// Close on Escape key
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
@@ -61,9 +80,13 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md' }:
|
||||
<div
|
||||
className={cn(
|
||||
'relative flex w-full flex-col border border-border bg-card shadow-lg',
|
||||
'max-h-[100vh] rounded-t-2xl sm:max-h-[85vh] sm:rounded-2xl',
|
||||
'animate-scale-in',
|
||||
sizeClasses[size]
|
||||
'animate-scale-in transition-all duration-200',
|
||||
isFullScreen
|
||||
? 'fixed inset-4 max-w-none w-auto h-auto rounded-2xl'
|
||||
: cn(
|
||||
'max-h-[100vh] rounded-t-2xl sm:max-h-[85vh] sm:rounded-2xl',
|
||||
sizeClasses[size]
|
||||
)
|
||||
)}
|
||||
>
|
||||
{/* Header - Fixed at top */}
|
||||
@@ -71,17 +94,32 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md' }:
|
||||
<h2 id="modal-title" className="text-lg font-semibold text-foreground">
|
||||
{title}
|
||||
</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
'rounded-md p-1.5 text-muted-foreground transition-colors sm:p-1',
|
||||
'hover:bg-accent hover:text-foreground',
|
||||
'focus:outline-none focus:ring-2 focus:ring-primary/20'
|
||||
<div className="flex items-center gap-1">
|
||||
{allowFullScreen && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleFullScreen}
|
||||
className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
title={isFullScreen ? 'Exit full screen' : 'Full screen'}
|
||||
>
|
||||
{isFullScreen
|
||||
? <Minimize2 className="h-4 w-4" />
|
||||
: <Maximize2 className="h-4 w-4" />
|
||||
}
|
||||
</button>
|
||||
)}
|
||||
aria-label="Close modal"
|
||||
>
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className={cn(
|
||||
'rounded-md p-1.5 text-muted-foreground transition-colors sm:p-1',
|
||||
'hover:bg-accent hover:text-foreground',
|
||||
'focus:outline-none focus:ring-2 focus:ring-primary/20'
|
||||
)}
|
||||
aria-label="Close modal"
|
||||
>
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Body - Scrollable */}
|
||||
|
||||
@@ -83,7 +83,7 @@ export function NodeEditorModal({ node, onClose, isNewNode = false }: NodeEditor
|
||||
)
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} onClose={onClose} title={getTitle()} size="lg" footer={footerContent}>
|
||||
<Modal isOpen={true} onClose={onClose} title={getTitle()} size="lg" footer={footerContent} allowFullScreen={true}>
|
||||
{/* Node ID display */}
|
||||
<div className="mb-4 text-xs text-muted-foreground">
|
||||
Node ID: <code className="rounded bg-accent px-1 py-0.5">{node.id}</code>
|
||||
|
||||
Reference in New Issue
Block a user