import React, { useState, useEffect, useRef, useCallback } from 'react'; import { Settings, ShoppingBag, Volume2, Users, User, Home, Power } from 'lucide-react'; // Importing Home and Power icons // Main App component for the Aura X Game Console UI const App = () => { // State to manage the active menu item for navigation const [activeMenuItem, setActiveMenuItem] = useState('Home'); // Default to Home // State to manage the currently focused element for gamepad/keyboard navigation const [focusedElement, setFocusedElement] = useState({ type: 'menu', id: 'Home' }); // Default focus to Home // State to trigger icon animations on press const [animatingIconId, setAnimatingIconId] = useState(null); // Refs for menu items and game cards to allow programmatic focus const menuRefs = useRef({}); const gameRefs = useRef({}); const gameListContainerRef = useRef(null); // Ref for the scrollable game list container // Dummy data for menu items with icons and specific colors const menuItems = [ { id: 'Home', name: 'Home', icon: Home, defaultIconColor: 'text-gray-700' }, { id: 'Settings', name: 'Settings', icon: Settings, defaultIconColor: 'text-gray-700' }, { id: 'Store', name: 'Store', icon: ShoppingBag, defaultIconColor: 'text-gray-700' }, { id: 'Friends', name: 'Friends', icon: Users, defaultIconColor: 'text-[#FF0000]' }, // Red for Users { id: 'Profile', name: 'Profile', icon: User, defaultIconColor: 'text-[#00CC00]' }, // Green for User { id: 'Power', name: 'Power', icon: Power, defaultIconColor: 'text-blue-500' }, // Power at the bottom ]; // Dummy data for game titles to display, matching image proportions // Expanded to more than 9 to demonstrate scrolling const games = [ { id: 1, title: 'LEGO Star Wars', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=LEGO+SW', border: 'border-blue-400' }, // Example from image { id: 2, title: 'Fortnite', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Fortnite', border: 'border-blue-400' }, // Example from image { id: 3, title: 'Cyberpunk 2077', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Cyberpunk' }, { id: 4, title: 'The Witcher 3', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Witcher+3' }, { id: 5, title: 'Red Dead Redemption 2', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=RDR2' }, { id: 6, title: 'God of War', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=God+of+War' }, { id: 7, title: 'Spider-Man: Miles Morales', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Spider-Man' }, { id: 8, title: 'Horizon Zero Dawn', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Horizon' }, { id: 9, title: 'Elden Ring', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Elden+Ring' }, { id: 10, title: 'Doom Eternal', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Doom' }, { id: 11, title: 'Halo Infinite', icon: 'https://placehold.co/200x260/000000/FFFFFF?text=Halo' }, ]; // Function to get current time for the header const getCurrentTime = () => { const now = new Date(); return now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: true }); }; const [currentTime, setCurrentTime] = useState(getCurrentTime()); useEffect(() => { const timer = setInterval(() => { setCurrentTime(getCurrentTime()); }, 60000); // Update every minute return () => clearInterval(timer); }, []); // Effect to handle gamepad connection and disconnection useEffect(() => { const handleGamepadConnected = (e) => { console.log('Gamepad connected at index %d: %s. %d buttons, %d axes.', e.gamepad.index, e.gamepad.id, e.gamepad.buttons.length, e.gamepad.axes.length); setGamepad(e.gamepad); // Set initial focus to the Home menu item when gamepad connects setFocusedElement({ type: 'menu', id: 'Home' }); }; const handleGamepadDisconnected = (e) => { console.log('Gamepad disconnected from index %d: %s', e.gamepad.index, e.gamepad.id); setGamepad(null); setFocusedElement({ type: 'none', id: null }); // Clear focus }; window.addEventListener('gamepadconnected', handleGamepadConnected); window.addEventListener('gamepaddisconnected', handleGamepadDisconnected); // Check for already connected gamepads on mount const gamepads = navigator.getGamepads(); if (gamepads[0]) { setGamepad(gamepads[0]); setFocusedElement({ type: 'menu', id: 'Home' }); } return () => { window.removeEventListener('gamepadconnected', handleGamepadConnected); window.removeEventListener('gamepaddisconnected', handleGamepadDisconnected); }; }, []); // Debounce state for gamepad/keyboard buttons to prevent multiple triggers on a single press const [buttonStates, setButtonStates] = useState({}); // Unified navigation logic for both gamepad and keyboard const navigate = useCallback((direction) => { let handled = false; if (focusedElement.type === 'menu') { const currentIndex = menuItems.findIndex(item => item.id === focusedElement.id); let nextIndex; if (direction === 'up') { nextIndex = (currentIndex - 1 + menuItems.length) % menuItems.length; setFocusedElement({ type: 'menu', id: menuItems[nextIndex].id }); handled = true; } else if (direction === 'down') { nextIndex = (currentIndex + 1) % menuItems.length; setFocusedElement({ type: 'menu', id: menuItems[nextIndex].id }); handled = true; } else if (direction === 'right') { // Only move to games if 'Home' is the active menu (since Home now shows games) if (activeMenuItem === 'Home' && games.length > 0) { setFocusedElement({ type: 'game', id: games[0].id }); handled = true; } } } else if (focusedElement.type === 'game') { const allSlots = Array.from({ length: 9 }).map((_, i) => games[i] ? games[i].id : `empty-${i}`); const currentIndex = allSlots.findIndex(id => id === focusedElement.id); let nextIndex; if (direction === 'up') { nextIndex = (currentIndex - 1 + allSlots.length) % allSlots.length; setFocusedElement({ type: 'game', id: allSlots[nextIndex] }); handled = true; } else if (direction === 'down') { nextIndex = (currentIndex + 1) % allSlots.length; setFocusedElement({ type: 'game', id: allSlots[nextIndex] }); handled = true; } else if (direction === 'left') { // Move from games to menu, setting activeMenuItem to 'Home' (since Home shows games) setFocusedElement({ type: 'menu', id: 'Home' }); handled = true; } } return handled; // Return true if navigation was handled }, [focusedElement, activeMenuItem, games, menuItems]); // Function to handle gamepad input polling const handleGamepadInput = useCallback(() => { if (!gamepad) return; const currentGamepad = navigator.getGamepads()[gamepad.index]; if (!currentGamepad) { setGamepad(null); // Gamepad might have disconnected return; } const newButtonStates = {}; for (let i = 0; i < currentGamepad.buttons.length; i++) { const button = currentGamepad.buttons[i]; const isPressed = button.pressed; newButtonStates[i] = isPressed; if (isPressed && !buttonStates[i]) { // A button (Xbox layout) if (i === 0) { if (focusedElement.type === 'menu') { setAnimatingIconId(focusedElement.id); // Trigger animation setTimeout(() => { setActiveMenuItem(focusedElement.id); // Set active after animation starts setAnimatingIconId(null); // Clear animation state // If 'Home' is selected, and we're moving from menu to games, set focus to first game if (focusedElement.id === 'Home' && games.length > 0) { setFocusedElement({ type: 'game', id: games[0].id }); } }, 300); // Match animation duration } else if (focusedElement.type === 'game') { console.log(`Playing game: ${focusedElement.title}`); // Implement actual game launch logic here } } // D-pad or left stick for navigation else if (i === 12 || currentGamepad.axes[1] < -0.5) { // Up navigate('up'); } else if (i === 13 || currentGamepad.axes[1] > 0.5) { // Down navigate('down'); } else if (i === 14 || currentGamepad.axes[0] < -0.5) { // Left navigate('left'); } else if (i === 15 || currentGamepad.axes[0] > 0.5) { // Right navigate('right'); } } } setButtonStates(newButtonStates); }, [gamepad, focusedElement, navigate, games, buttonStates]); // Keyboard input handler const handleKeyDown = useCallback((event) => { let handled = false; switch (event.key) { case 'ArrowUp': handled = navigate('up'); break; case 'ArrowDown': handled = navigate('down'); break; case 'ArrowLeft': handled = navigate('left'); break; case 'ArrowRight': handled = navigate('right'); break; case 'Enter': // Confirmation key case 'z': // 'Z' key for confirmation case 'Z': // 'Z' key for confirmation (uppercase) if (focusedElement.type === 'menu') { setAnimatingIconId(focusedElement.id); // Trigger animation setTimeout(() => { setActiveMenuItem(focusedElement.id); // Set active after animation starts setAnimatingIconId(null); // Clear animation state // If 'Home' is selected, and we're moving from menu to games, set focus to first game if (focusedElement.id === 'Home' && games.length > 0) { setFocusedElement({ type: 'game', id: games[0].id }); } }, 300); // Match animation duration } else if (focusedElement.type === 'game') { console.log(`Playing game: ${focusedElement.title}`); } handled = true; break; default: break; } if (handled) { event.preventDefault(); // Prevent default browser scrolling/behavior } }, [focusedElement, navigate, games]); // Animation loop for gamepad polling useEffect(() => { let animationFrameId; const gameLoop = () => { handleGamepadInput(); animationFrameId = requestAnimationFrame(gameLoop); }; if (gamepad) { animationFrameId = requestAnimationFrame(gameLoop); } return () => { cancelAnimationFrame(animationFrameId); }; }, [gamepad, handleGamepadInput]); // Add keyboard event listener useEffect(() => { window.addEventListener('keydown', handleKeyDown); return () => { window.removeEventListener('keydown', handleKeyDown); }; }, [handleKeyDown]); // Effect to scroll focused game element into view useEffect(() => { if (focusedElement.type === 'menu' && menuRefs.current[focusedElement.id]) { menuRefs.current[focusedElement.id].scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } else if (focusedElement.type === 'game' && gameRefs.current[focusedElement.id]) { // Scroll the specific game card into view within its container gameRefs.current[focusedElement.id].scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, [focusedElement]); return ( // Main container for the app, full screen height and width, dark background matching image
{/* Console Header */}
{/* Avatar matching image style */}
Player Avatar
Hello, TheRedSlimeYT!
{currentTime}
{/* Main Content Area: Sidebar + Content */}
{/* Side Navigation Menu */} {/* Add keyframes for the gradient and icon animations */} {/* Content Display Area */}
{/* Removed justify-center items-center */} {/* Display games if Home is active, matching the image */} {activeMenuItem === 'Home' && (
{Array.from({ length: 9 }).map((_, index) => { const game = games[index]; const isFocused = focusedElement.type === 'game' && focusedElement.id === (game ? game.id : `empty-${index}`); const isPlaceholder = !game; return (
gameRefs.current[game ? game.id : `empty-${index}`] = el} className={` rounded-xl shadow-md flex-shrink-0 flex flex-col items-center relative ${isFocused ? 'border-2 border-blue-400 ring-2 ring-blue-400' : (isPlaceholder ? 'border-2 border-gray-700' : (game.border ? `border-2 ${game.border}` : 'border-2 border-transparent'))} `} style={{ width: '200px', height: '260px', backgroundColor: isPlaceholder ? '#2a2a2a' : '#3a3a3a' }} > {isPlaceholder ? (
Empty Slot
) : ( {game.title} { e.target.onerror = null; e.target.src = `https://placehold.co/200x260/555555/FFFFFF?text=${game.title.replace(/\s/g, '+')}`; }} /> )}
); })}
)} {activeMenuItem === 'Store' && (

Aura X Store

Discover new games and content!

New Release Game

Exciting adventure awaits!

DLC Pack

Expand your favorite game.

)} {activeMenuItem === 'Settings' && (

Settings

Adjust your console preferences here.

Audio Volume
Display Resolution
)} {/* Placeholder for Power content */} {activeMenuItem === 'Power' && (

Power Options

Shut down or restart your console.

)} {activeMenuItem === 'Friends' && (

Friends List

See who's online and invite them to play.

)} {activeMenuItem === 'Profile' && (

Player Profile

View and edit your profile information.

)} {/* Elliptical shadow on the right, as seen in the image */}
); }; export default App;