import { useState, ReactNode } from 'react'; import { Text } from '@react-three/drei'; import * as THREE from 'three'; interface XR3DButtonProps { position?: [number, number, number]; size?: [number, number]; label: string; icon?: string; active?: boolean; disabled?: boolean; onClick?: () => void; color?: string; fontSize?: number; } /** Flat 3D button suitable for in-XR HUD. Reacts to controller raycast. */ export function XR3DButton({ position = [0, 0, 0], size = [0.08, 0.025], label, icon, active = false, disabled = false, onClick, color, fontSize = 0.008, }: XR3DButtonProps) { const [hovered, setHovered] = useState(false); const [w, h] = size; const bgColor = disabled ? '#222' : active ? (color ?? '#3b82f6') : hovered ? '#444' : '#1a1a1a'; const fgColor = disabled ? '#555' : active ? '#ffffff' : '#e5e7eb'; const borderColor = active ? (color ?? '#3b82f6') : hovered ? '#666' : '#333'; return ( { e.stopPropagation(); if (!disabled) setHovered(true); }} onPointerOut={(e) => { e.stopPropagation(); setHovered(false); }} onClick={(e) => { e.stopPropagation(); if (!disabled && onClick) onClick(); }} > {/* Border */} {/* Background */} {icon ? `${icon} ${label}` : label} ); } interface XR3DPanelProps { position?: [number, number, number]; size?: [number, number]; color?: string; opacity?: number; children?: ReactNode; } /** Background panel for grouping XR3DButtons. */ export function XR3DPanel({ position = [0, 0, 0], size = [0.4, 0.3], color = '#0a0a0a', opacity = 0.85, children, }: XR3DPanelProps) { const [w, h] = size; return ( {children} ); }