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 {
|
interface FullscreenPlayerSelectionProps {
|
||||||
inactivePlayers: Player[]
|
inactivePlayers: Player[]
|
||||||
onSelectPlayer: (playerId: number) => void
|
onSelectPlayer: (playerId: number) => void
|
||||||
|
isVisible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FullscreenPlayerSelection({ inactivePlayers, onSelectPlayer }: FullscreenPlayerSelectionProps) {
|
export function FullscreenPlayerSelection({ inactivePlayers, onSelectPlayer, isVisible }: FullscreenPlayerSelectionProps) {
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: '32px',
|
gap: '32px',
|
||||||
width: '100%',
|
width: isVisible ? '100%' : '0',
|
||||||
padding: '40px 20px',
|
padding: isVisible ? '40px 20px' : '0',
|
||||||
animation: 'expandIn 0.4s ease'
|
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={{
|
<div style={{
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,35 @@ export function GameContextNav({
|
||||||
onAddPlayer,
|
onAddPlayer,
|
||||||
onRemovePlayer
|
onRemovePlayer
|
||||||
}: GameContextNavProps) {
|
}: 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 (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: showFullscreenSelection ? 'column' : 'row',
|
flexDirection: layoutMode,
|
||||||
alignItems: showFullscreenSelection ? 'stretch' : 'center',
|
alignItems: showFullscreenSelection ? 'stretch' : 'center',
|
||||||
gap: shouldEmphasize ? '16px' : '12px',
|
gap: shouldEmphasize ? '16px' : '12px',
|
||||||
width: showFullscreenSelection ? '100%' : 'auto',
|
width: containerWidth,
|
||||||
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)'
|
transition: 'gap 0.4s cubic-bezier(0.4, 0, 0.2, 1)'
|
||||||
}}>
|
}}>
|
||||||
{/* Header row */}
|
{/* Header row */}
|
||||||
<div style={{
|
<div style={{
|
||||||
|
|
@ -102,12 +123,11 @@ export function GameContextNav({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Fullscreen player selection grid */}
|
{/* Fullscreen player selection grid */}
|
||||||
{showFullscreenSelection && (
|
<FullscreenPlayerSelection
|
||||||
<FullscreenPlayerSelection
|
inactivePlayers={inactivePlayers}
|
||||||
inactivePlayers={inactivePlayers}
|
onSelectPlayer={onAddPlayer}
|
||||||
onSelectPlayer={onAddPlayer}
|
isVisible={showFullscreenSelection}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Add keyframes for animations */}
|
{/* Add keyframes for animations */}
|
||||||
<style dangerouslySetInnerHTML={{ __html: `
|
<style dangerouslySetInnerHTML={{ __html: `
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue