feat: use CSS transitions for smooth fullscreen player selection collapse

Replace conditional rendering with always-mounted component that uses CSS transitions for height, width, and opacity. Prevents height from snapping when transitioning between fullscreen and prominent nav modes.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2025-09-29 16:57:36 -05:00
parent 98cfa5645b
commit 31898328a3
2 changed files with 38 additions and 13 deletions

View File

@ -9,18 +9,23 @@ interface Player {
interface FullscreenPlayerSelectionProps {
inactivePlayers: Player[]
onSelectPlayer: (playerId: number) => void
isVisible: boolean
}
export function FullscreenPlayerSelection({ inactivePlayers, onSelectPlayer }: FullscreenPlayerSelectionProps) {
export function FullscreenPlayerSelection({ inactivePlayers, onSelectPlayer, isVisible }: FullscreenPlayerSelectionProps) {
return (
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '32px',
width: '100%',
padding: '40px 20px',
animation: 'expandIn 0.4s ease'
width: isVisible ? '100%' : '0',
padding: isVisible ? '40px 20px' : '0',
maxHeight: isVisible ? '800px' : '0',
opacity: isVisible ? 1 : 0,
overflow: 'hidden',
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
pointerEvents: isVisible ? 'auto' : 'none'
}}>
<div style={{
textAlign: 'center',

View File

@ -35,14 +35,35 @@ export function GameContextNav({
onAddPlayer,
onRemovePlayer
}: GameContextNavProps) {
const [isTransitioning, setIsTransitioning] = React.useState(false)
const [layoutMode, setLayoutMode] = React.useState<'column' | 'row'>(showFullscreenSelection ? 'column' : 'row')
const [containerWidth, setContainerWidth] = React.useState<string>(showFullscreenSelection ? '100%' : 'auto')
React.useEffect(() => {
if (showFullscreenSelection) {
// Switching to fullscreen - change layout and width immediately
setLayoutMode('column')
setContainerWidth('100%')
} else {
// Switching away from fullscreen - delay layout change until transition completes
setIsTransitioning(true)
setContainerWidth('auto')
const timer = setTimeout(() => {
setLayoutMode('row')
setIsTransitioning(false)
}, 400) // Match transition duration
return () => clearTimeout(timer)
}
}, [showFullscreenSelection])
return (
<div style={{
display: 'flex',
flexDirection: showFullscreenSelection ? 'column' : 'row',
flexDirection: layoutMode,
alignItems: showFullscreenSelection ? 'stretch' : 'center',
gap: shouldEmphasize ? '16px' : '12px',
width: showFullscreenSelection ? '100%' : 'auto',
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)'
width: containerWidth,
transition: 'gap 0.4s cubic-bezier(0.4, 0, 0.2, 1)'
}}>
{/* Header row */}
<div style={{
@ -102,12 +123,11 @@ export function GameContextNav({
</div>
{/* Fullscreen player selection grid */}
{showFullscreenSelection && (
<FullscreenPlayerSelection
inactivePlayers={inactivePlayers}
onSelectPlayer={onAddPlayer}
/>
)}
<FullscreenPlayerSelection
inactivePlayers={inactivePlayers}
onSelectPlayer={onAddPlayer}
isVisible={showFullscreenSelection}
/>
{/* Add keyframes for animations */}
<style dangerouslySetInnerHTML={{ __html: `