refactor: extract ActivePlayersList component from PageWithNav

Extract active player display with hover-triggered remove buttons into dedicated component. Handles emoji scaling and red × button on hover in emphasized mode.

🤖 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:51:33 -05:00
parent d67315f771
commit 28495767a9

View File

@@ -0,0 +1,80 @@
import React from 'react'
interface Player {
id: number
name: string
emoji: string
}
interface ActivePlayersListProps {
activePlayers: Player[]
shouldEmphasize: boolean
onRemovePlayer: (playerId: number) => void
}
export function ActivePlayersList({ activePlayers, shouldEmphasize, onRemovePlayer }: ActivePlayersListProps) {
const [hoveredPlayerId, setHoveredPlayerId] = React.useState<number | null>(null)
return (
<>
{activePlayers.map(player => (
<div
key={player.id}
style={{
position: 'relative',
fontSize: shouldEmphasize ? '48px' : '20px',
lineHeight: 1,
transition: 'font-size 0.4s cubic-bezier(0.4, 0, 0.2, 1), filter 0.4s ease',
filter: shouldEmphasize ? 'drop-shadow(0 4px 8px rgba(0,0,0,0.25))' : 'none',
cursor: shouldEmphasize ? 'pointer' : 'default'
}}
title={player.name}
onMouseEnter={() => shouldEmphasize && setHoveredPlayerId(player.id)}
onMouseLeave={() => shouldEmphasize && setHoveredPlayerId(null)}
>
{player.emoji}
{shouldEmphasize && hoveredPlayerId === player.id && (
<button
onClick={(e) => {
e.stopPropagation()
onRemovePlayer(player.id)
}}
style={{
position: 'absolute',
top: '-4px',
right: '-4px',
width: '20px',
height: '20px',
borderRadius: '50%',
border: '2px solid white',
background: '#ef4444',
color: 'white',
fontSize: '12px',
fontWeight: 'bold',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
transition: 'all 0.2s ease',
padding: 0,
lineHeight: 1
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = '#dc2626'
e.currentTarget.style.transform = 'scale(1.1)'
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = '#ef4444'
e.currentTarget.style.transform = 'scale(1)'
}}
aria-label={`Remove ${player.name}`}
>
×
</button>
)}
</div>
))}
</>
)
}