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:
parent
98cfa5645b
commit
31898328a3
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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: `
|
||||
|
|
|
|||
Loading…
Reference in New Issue