refactor: comprehensive navigation polish - prominence, contrast, cohesion
Major improvements across all navigation components for better visual hierarchy and user experience: **RoomInfo** - Redesigned with Radix tooltip for join code (hover to reveal) - Much better contrast: purple pill with bright text (rgba(196, 181, 253, 1)) - Click-to-copy in elegant tooltip with visual feedback - Auto-closes after successful copy with "Share this code with friends!" message **Player Avatars (ActivePlayersList & NetworkPlayerIndicator)** - Increased size from 20px to 56px - now span both rows for prominence - Enhanced drop shadows (0 6px 12px) for depth - Larger, more polished action buttons (configure/remove): - 24-26px buttons with 3px borders and gradient backgrounds - Better hover effects with color glows - Network players: larger frame borders, badges, and pulse indicators **AddPlayerButton** - Increased from 48px to 56px to match player avatars - Enhanced with gradient backgrounds and stronger shadows - Better hover states with 1.08 scale and green glow **GameContextNav Layout** - Added minHeight: 64px to row 2 for avatar accommodation - Network players now in distinct purple-gradient container - Your players container gets enhanced polish even when not emphasized - Improved spacing and gaps throughout (12px between player groups) Result: Navigation now has clear visual hierarchy with player avatars as the dominant focal point, excellent contrast on all text, and cohesive translucent design language throughout. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -38,10 +38,10 @@ export function ActivePlayersList({
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
fontSize: shouldEmphasize ? '48px' : '20px',
|
||||
fontSize: shouldEmphasize ? '56px' : '56px',
|
||||
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',
|
||||
filter: 'drop-shadow(0 6px 12px rgba(0,0,0,0.3))',
|
||||
cursor: shouldEmphasize ? 'pointer' : 'default',
|
||||
}}
|
||||
onClick={() => shouldEmphasize && onConfigurePlayer(player.id)}
|
||||
@@ -53,37 +53,40 @@ export function ActivePlayersList({
|
||||
<>
|
||||
{/* Configure button - bottom left */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onConfigurePlayer(player.id)
|
||||
}}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '-4px',
|
||||
left: '-4px',
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
bottom: '-6px',
|
||||
left: '-6px',
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '50%',
|
||||
border: '2px solid white',
|
||||
background: '#6b7280',
|
||||
border: '3px solid white',
|
||||
background: 'linear-gradient(135deg, #6b7280, #4b5563)',
|
||||
color: 'white',
|
||||
fontSize: '10px',
|
||||
fontSize: '12px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.4)',
|
||||
transition: 'all 0.2s ease',
|
||||
padding: 0,
|
||||
lineHeight: 1,
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = '#3b82f6'
|
||||
e.currentTarget.style.transform = 'scale(1.15)'
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, #3b82f6, #2563eb)'
|
||||
e.currentTarget.style.transform = 'scale(1.2)'
|
||||
e.currentTarget.style.boxShadow = '0 6px 16px rgba(59, 130, 246, 0.5)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = '#6b7280'
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, #6b7280, #4b5563)'
|
||||
e.currentTarget.style.transform = 'scale(1)'
|
||||
e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.4)'
|
||||
}}
|
||||
aria-label={`Configure ${player.name}`}
|
||||
>
|
||||
@@ -92,38 +95,41 @@ export function ActivePlayersList({
|
||||
|
||||
{/* Remove button - top right */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onRemovePlayer(player.id)
|
||||
}}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '-4px',
|
||||
right: '-4px',
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
top: '-6px',
|
||||
right: '-6px',
|
||||
width: '26px',
|
||||
height: '26px',
|
||||
borderRadius: '50%',
|
||||
border: '2px solid white',
|
||||
background: '#ef4444',
|
||||
border: '3px solid white',
|
||||
background: 'linear-gradient(135deg, #ef4444, #dc2626)',
|
||||
color: 'white',
|
||||
fontSize: '12px',
|
||||
fontSize: '14px',
|
||||
fontWeight: 'bold',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.3)',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.4)',
|
||||
transition: 'all 0.2s ease',
|
||||
padding: 0,
|
||||
lineHeight: 1,
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = '#dc2626'
|
||||
e.currentTarget.style.transform = 'scale(1.1)'
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, #dc2626, #b91c1c)'
|
||||
e.currentTarget.style.transform = 'scale(1.15)'
|
||||
e.currentTarget.style.boxShadow = '0 6px 16px rgba(239, 68, 68, 0.5)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = '#ef4444'
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, #ef4444, #dc2626)'
|
||||
e.currentTarget.style.transform = 'scale(1)'
|
||||
e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.4)'
|
||||
}}
|
||||
aria-label={`Remove ${player.name}`}
|
||||
>
|
||||
|
||||
@@ -46,14 +46,17 @@ export function AddPlayerButton({
|
||||
return (
|
||||
<div style={{ position: 'relative' }} ref={popoverRef}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPopover(!showPopover)}
|
||||
style={{
|
||||
fontSize: shouldEmphasize ? '32px' : '16px',
|
||||
width: shouldEmphasize ? '48px' : '24px',
|
||||
height: shouldEmphasize ? '48px' : '24px',
|
||||
fontSize: shouldEmphasize ? '36px' : '36px',
|
||||
width: shouldEmphasize ? '56px' : '56px',
|
||||
height: shouldEmphasize ? '56px' : '56px',
|
||||
borderRadius: '50%',
|
||||
border: '2px solid #10b981',
|
||||
background: showPopover ? '#10b981' : 'rgba(16, 185, 129, 0.1)',
|
||||
border: '3px solid #10b981',
|
||||
background: showPopover
|
||||
? 'linear-gradient(135deg, #10b981, #059669)'
|
||||
: 'linear-gradient(135deg, rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.1))',
|
||||
color: showPopover ? 'white' : '#10b981',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@@ -63,20 +66,24 @@ export function AddPlayerButton({
|
||||
padding: 0,
|
||||
lineHeight: 1,
|
||||
fontWeight: 'bold',
|
||||
boxShadow: showPopover ? '0 4px 12px rgba(16, 185, 129, 0.4)' : 'none',
|
||||
boxShadow: showPopover
|
||||
? '0 6px 16px rgba(16, 185, 129, 0.5)'
|
||||
: '0 6px 12px rgba(0,0,0,0.3)',
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
if (!showPopover) {
|
||||
e.currentTarget.style.background = '#10b981'
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, #10b981, #059669)'
|
||||
e.currentTarget.style.color = 'white'
|
||||
e.currentTarget.style.transform = 'scale(1.1)'
|
||||
e.currentTarget.style.transform = 'scale(1.08)'
|
||||
e.currentTarget.style.boxShadow = '0 6px 16px rgba(16, 185, 129, 0.5)'
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (!showPopover) {
|
||||
e.currentTarget.style.background = 'rgba(16, 185, 129, 0.1)'
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.1))'
|
||||
e.currentTarget.style.color = '#10b981'
|
||||
e.currentTarget.style.transform = 'scale(1)'
|
||||
e.currentTarget.style.boxShadow = '0 6px 12px rgba(0,0,0,0.3)'
|
||||
}
|
||||
}}
|
||||
title="Add player"
|
||||
|
||||
@@ -200,10 +200,11 @@ export function GameContextNav({
|
||||
alignItems: 'center',
|
||||
gap: '16px',
|
||||
justifyContent: 'space-between',
|
||||
minHeight: '64px', // Accommodate larger avatars
|
||||
}}
|
||||
>
|
||||
{/* Left: Control buttons */}
|
||||
<div>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
{!canModifyPlayers && (
|
||||
<GameControlButtons onSetup={onSetup} onNewGame={onNewGame} onQuit={onExitSession} />
|
||||
)}
|
||||
@@ -214,7 +215,7 @@ export function GameContextNav({
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: shouldEmphasize ? '12px' : '8px',
|
||||
gap: shouldEmphasize ? '16px' : '12px',
|
||||
}}
|
||||
>
|
||||
{/* Network Players */}
|
||||
@@ -223,7 +224,12 @@ export function GameContextNav({
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '6px',
|
||||
gap: '8px',
|
||||
padding: '6px 12px',
|
||||
background: 'linear-gradient(135deg, rgba(59, 130, 246, 0.12), rgba(147, 51, 234, 0.12))',
|
||||
borderRadius: '12px',
|
||||
border: '2px solid rgba(147, 51, 234, 0.25)',
|
||||
boxShadow: '0 4px 12px rgba(59, 130, 246, 0.15)',
|
||||
}}
|
||||
>
|
||||
{networkPlayers.map((player) => (
|
||||
@@ -238,16 +244,16 @@ export function GameContextNav({
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: shouldEmphasize ? '12px' : '2px',
|
||||
padding: shouldEmphasize ? '12px 20px' : '0',
|
||||
gap: shouldEmphasize ? '12px' : '8px',
|
||||
padding: shouldEmphasize ? '12px 20px' : '6px 12px',
|
||||
background: shouldEmphasize
|
||||
? 'linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.08))'
|
||||
: 'transparent',
|
||||
borderRadius: shouldEmphasize ? '16px' : '0',
|
||||
border: shouldEmphasize ? '3px solid rgba(255, 255, 255, 0.25)' : 'none',
|
||||
? 'linear-gradient(135deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.10))'
|
||||
: 'linear-gradient(135deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.05))',
|
||||
borderRadius: shouldEmphasize ? '16px' : '12px',
|
||||
border: shouldEmphasize ? '3px solid rgba(255, 255, 255, 0.3)' : '2px solid rgba(255, 255, 255, 0.15)',
|
||||
boxShadow: shouldEmphasize
|
||||
? '0 6px 20px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255,255,255,0.3)'
|
||||
: 'none',
|
||||
? '0 8px 24px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255,255,255,0.3)'
|
||||
: '0 4px 12px rgba(0, 0, 0, 0.1)',
|
||||
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
transform: shouldEmphasize ? 'scale(1.05)' : 'scale(1)',
|
||||
opacity: canModifyPlayers ? 1 : 0.6,
|
||||
|
||||
@@ -33,7 +33,7 @@ export function NetworkPlayerIndicator({ player, shouldEmphasize }: NetworkPlaye
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
fontSize: shouldEmphasize ? '48px' : '20px',
|
||||
fontSize: shouldEmphasize ? '56px' : '56px',
|
||||
lineHeight: 1,
|
||||
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
cursor: 'default',
|
||||
@@ -41,35 +41,37 @@ export function NetworkPlayerIndicator({ player, shouldEmphasize }: NetworkPlaye
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
>
|
||||
{/* Network frame border */}
|
||||
{/* Network frame border - larger and more prominent */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: '-6px',
|
||||
borderRadius: '8px',
|
||||
inset: '-8px',
|
||||
borderRadius: '12px',
|
||||
background: `
|
||||
linear-gradient(135deg,
|
||||
rgba(59, 130, 246, 0.4),
|
||||
rgba(147, 51, 234, 0.4),
|
||||
rgba(236, 72, 153, 0.4))
|
||||
rgba(59, 130, 246, 0.5),
|
||||
rgba(147, 51, 234, 0.5),
|
||||
rgba(236, 72, 153, 0.5))
|
||||
`,
|
||||
opacity: isHovered ? 1 : 0.7,
|
||||
opacity: isHovered ? 1 : 0.8,
|
||||
transition: 'opacity 0.2s ease',
|
||||
boxShadow: '0 6px 16px rgba(59, 130, 246, 0.3)',
|
||||
zIndex: -1,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Animated network signal indicator */}
|
||||
{/* Animated network signal indicator - larger */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '-8px',
|
||||
right: '-8px',
|
||||
width: '12px',
|
||||
height: '12px',
|
||||
top: '-10px',
|
||||
right: '-10px',
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
borderRadius: '50%',
|
||||
background: 'rgba(34, 197, 94, 0.9)',
|
||||
boxShadow: '0 0 8px rgba(34, 197, 94, 0.6)',
|
||||
background: 'rgba(34, 197, 94, 0.95)',
|
||||
border: '2px solid rgba(255, 255, 255, 0.8)',
|
||||
boxShadow: '0 0 12px rgba(34, 197, 94, 0.8)',
|
||||
animation: 'networkPulse 2s ease-in-out infinite',
|
||||
zIndex: 1,
|
||||
}}
|
||||
@@ -79,29 +81,29 @@ export function NetworkPlayerIndicator({ player, shouldEmphasize }: NetworkPlaye
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
filter: shouldEmphasize ? 'drop-shadow(0 4px 8px rgba(0,0,0,0.25))' : 'none',
|
||||
filter: 'drop-shadow(0 6px 12px rgba(0,0,0,0.3))',
|
||||
}}
|
||||
>
|
||||
{player.emoji || '🌐'}
|
||||
</div>
|
||||
|
||||
{/* Network icon badge */}
|
||||
{/* Network icon badge - larger */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '-4px',
|
||||
left: '-4px',
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
bottom: '-6px',
|
||||
left: '-6px',
|
||||
width: '22px',
|
||||
height: '22px',
|
||||
borderRadius: '50%',
|
||||
border: '2px solid white',
|
||||
border: '3px solid white',
|
||||
background: 'linear-gradient(135deg, #3b82f6, #8b5cf6)',
|
||||
color: 'white',
|
||||
fontSize: '8px',
|
||||
fontSize: '11px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 2px 6px rgba(0,0,0,0.3)',
|
||||
boxShadow: '0 4px 10px rgba(0,0,0,0.4)',
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as Tooltip from '@radix-ui/react-tooltip'
|
||||
import { useState } from 'react'
|
||||
|
||||
interface RoomInfoProps {
|
||||
@@ -9,7 +10,7 @@ interface RoomInfoProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays current arcade room/session information in a compact inline format
|
||||
* Displays current arcade room/session information with tooltip for join code
|
||||
*/
|
||||
export function RoomInfo({
|
||||
roomName,
|
||||
@@ -19,78 +20,176 @@ export function RoomInfo({
|
||||
shouldEmphasize,
|
||||
}: RoomInfoProps) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
const handleCodeClick = () => {
|
||||
if (!joinCode) return
|
||||
navigator.clipboard.writeText(joinCode)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
setTimeout(() => {
|
||||
setCopied(false)
|
||||
setIsOpen(false)
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
const displayName = roomName || gameName
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '6px',
|
||||
padding: '4px 10px',
|
||||
background: 'rgba(59, 130, 246, 0.15)',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid rgba(59, 130, 246, 0.3)',
|
||||
fontSize: '13px',
|
||||
fontWeight: '500',
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
transition: 'all 0.2s ease',
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
title="Active Arcade Room"
|
||||
>
|
||||
{/* Room icon and name */}
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<span style={{ fontSize: '14px' }}>🎮</span>
|
||||
<span style={{ fontWeight: '600' }}>{roomName || gameName}</span>
|
||||
</span>
|
||||
|
||||
{/* Join code with click-to-copy */}
|
||||
{joinCode && (
|
||||
<>
|
||||
<span style={{ opacity: 0.5 }}>•</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCodeClick}
|
||||
<Tooltip.Provider delayDuration={200}>
|
||||
<Tooltip.Root open={isOpen} onOpenChange={setIsOpen}>
|
||||
<Tooltip.Trigger asChild>
|
||||
<div
|
||||
style={{
|
||||
background: 'rgba(255, 255, 255, 0.15)',
|
||||
border: '1px solid rgba(255, 255, 255, 0.2)',
|
||||
borderRadius: '4px',
|
||||
padding: '2px 6px',
|
||||
fontFamily: 'monospace',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '6px',
|
||||
padding: '4px 10px',
|
||||
background: 'rgba(139, 92, 246, 0.2)',
|
||||
borderRadius: '6px',
|
||||
border: '2px solid rgba(139, 92, 246, 0.4)',
|
||||
fontSize: '12px',
|
||||
color: 'rgba(255, 255, 255, 0.95)',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold',
|
||||
color: 'rgba(196, 181, 253, 1)',
|
||||
transition: 'all 0.2s ease',
|
||||
fontWeight: '600',
|
||||
whiteSpace: 'nowrap',
|
||||
cursor: joinCode ? 'pointer' : 'default',
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.25)'
|
||||
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.4)'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.15)'
|
||||
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.2)'
|
||||
}}
|
||||
title={copied ? 'Copied!' : 'Click to copy join code'}
|
||||
onMouseEnter={() => joinCode && setIsOpen(true)}
|
||||
onMouseLeave={() => !copied && setIsOpen(false)}
|
||||
>
|
||||
{copied ? '✓ Copied' : joinCode}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{/* Room icon and name */}
|
||||
<span style={{ fontSize: '12px' }}>🎮</span>
|
||||
<span>{displayName}</span>
|
||||
|
||||
{/* Player count */}
|
||||
<span style={{ opacity: 0.5 }}>•</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '3px' }}>
|
||||
<span style={{ fontSize: '12px' }}>👥</span>
|
||||
<span>{playerCount}</span>
|
||||
</span>
|
||||
</div>
|
||||
{/* Player count */}
|
||||
<span style={{ opacity: 0.6 }}>•</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: '3px' }}>
|
||||
<span style={{ fontSize: '11px' }}>👥</span>
|
||||
<span>{playerCount}</span>
|
||||
</span>
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
|
||||
{joinCode && (
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content
|
||||
side="bottom"
|
||||
sideOffset={8}
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, rgba(17, 24, 39, 0.97), rgba(31, 41, 55, 0.97))',
|
||||
backdropFilter: 'blur(12px)',
|
||||
borderRadius: '12px',
|
||||
padding: '12px 16px',
|
||||
boxShadow: '0 8px 24px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(139, 92, 246, 0.3)',
|
||||
maxWidth: '280px',
|
||||
zIndex: 9999,
|
||||
animation: 'tooltipFadeIn 0.2s ease-out',
|
||||
}}
|
||||
>
|
||||
{/* Join code label */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
fontWeight: '600',
|
||||
color: 'rgba(196, 181, 253, 0.8)',
|
||||
marginBottom: '6px',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.5px',
|
||||
}}
|
||||
>
|
||||
Room Join Code
|
||||
</div>
|
||||
|
||||
{/* Click-to-copy button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCodeClick}
|
||||
style={{
|
||||
width: '100%',
|
||||
background: copied
|
||||
? 'linear-gradient(135deg, rgba(34, 197, 94, 0.2), rgba(34, 197, 94, 0.3))'
|
||||
: 'linear-gradient(135deg, rgba(139, 92, 246, 0.2), rgba(139, 92, 246, 0.3))',
|
||||
border: copied
|
||||
? '2px solid rgba(34, 197, 94, 0.5)'
|
||||
: '2px solid rgba(139, 92, 246, 0.4)',
|
||||
borderRadius: '8px',
|
||||
padding: '10px 16px',
|
||||
fontFamily: 'monospace',
|
||||
fontSize: '18px',
|
||||
fontWeight: 'bold',
|
||||
color: copied ? 'rgba(134, 239, 172, 1)' : 'rgba(196, 181, 253, 1)',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.2s ease',
|
||||
letterSpacing: '2px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: '8px',
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
if (!copied) {
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, rgba(139, 92, 246, 0.3), rgba(139, 92, 246, 0.4))'
|
||||
e.currentTarget.style.borderColor = 'rgba(139, 92, 246, 0.6)'
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (!copied) {
|
||||
e.currentTarget.style.background = 'linear-gradient(135deg, rgba(139, 92, 246, 0.2), rgba(139, 92, 246, 0.3))'
|
||||
e.currentTarget.style.borderColor = 'rgba(139, 92, 246, 0.4)'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{copied ? (
|
||||
<>
|
||||
<span style={{ fontSize: '16px' }}>✓</span>
|
||||
<span>Copied!</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span>{joinCode}</span>
|
||||
<span style={{ fontSize: '14px', opacity: 0.7 }}>📋</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{/* Helper text */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
color: 'rgba(156, 163, 175, 0.8)',
|
||||
marginTop: '8px',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
{copied ? 'Share this code with friends!' : 'Click to copy'}
|
||||
</div>
|
||||
|
||||
<Tooltip.Arrow
|
||||
style={{
|
||||
fill: 'rgba(17, 24, 39, 0.97)',
|
||||
}}
|
||||
/>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
)}
|
||||
</Tooltip.Root>
|
||||
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
@keyframes tooltipFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
</Tooltip.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user