'use client' import { useState, type ReactNode } from 'react' import { Button } from '../inputs/Button' export type ViewMode = 'split' | 'left' | 'right' export interface SplitViewProps { /** Left panel content */ leftPanel: ReactNode /** Right panel content */ rightPanel: ReactNode /** Height of the split view (CSS value) */ height?: string /** Initial view mode */ defaultMode?: ViewMode /** Left panel label for accessibility */ leftLabel?: string /** Right panel label for accessibility */ rightLabel?: string /** Left button label */ leftButtonLabel?: string /** Right button label */ rightButtonLabel?: string /** Split button label */ splitButtonLabel?: string /** Custom left icon */ leftIcon?: ReactNode /** Custom right icon */ rightIcon?: ReactNode /** Custom split icon */ splitIcon?: ReactNode /** Controlled mode value */ mode?: ViewMode /** Controlled mode change handler */ onModeChange?: (mode: ViewMode) => void /** Hide the mode selector buttons */ hideControls?: boolean /** Custom className for container */ className?: string /** Test ID for the component */ testId?: string } /** * Generic split view component for displaying two panels side by side, * with controls to switch between split, left-only, and right-only views. * * @example * ```tsx * } * rightPanel={} * leftLabel="Code Editor" * rightLabel="Preview" * height="500px" * /> * ``` */ export function SplitView({ leftPanel, rightPanel, height = '500px', defaultMode = 'split', leftLabel = 'Left panel', rightLabel = 'Right panel', leftButtonLabel = 'Left', rightButtonLabel = 'Right', splitButtonLabel = 'Split', leftIcon, rightIcon, splitIcon, mode: controlledMode, onModeChange, hideControls = false, className = '', testId, }: SplitViewProps) { const [internalMode, setInternalMode] = useState(defaultMode) const mode = controlledMode ?? internalMode const setMode = (newMode: ViewMode) => { if (onModeChange) { onModeChange(newMode) } else { setInternalMode(newMode) } } return ( {!hideControls && ( setMode('left')} className="flex items-center gap-2 h-8" data-testid="view-mode-left-btn" aria-label={`Show ${leftLabel} only`} aria-pressed={mode === 'left'} > {leftIcon} {leftButtonLabel} setMode('split')} className="flex items-center gap-2 h-8" data-testid="view-mode-split-btn" aria-label={`Show ${leftLabel} and ${rightLabel} side by side`} aria-pressed={mode === 'split'} > {splitIcon} {splitButtonLabel} setMode('right')} className="flex items-center gap-2 h-8" data-testid="view-mode-right-btn" aria-label={`Show ${rightLabel} only`} aria-pressed={mode === 'right'} > {rightIcon} {rightButtonLabel} )} {mode === 'left' && leftPanel} {mode === 'right' && rightPanel} {mode === 'split' && ( {leftPanel} {rightPanel} )} ) }