fix toggle button behavior, tweak joystick

This commit is contained in:
Brian Beck 2026-02-12 12:21:19 -08:00
parent d9293b1a0b
commit 2d3cfccf9b
23 changed files with 58 additions and 49 deletions

View file

@ -45,6 +45,7 @@ export function InspectorControls({
const [settingsOpen, setSettingsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const focusAreaRef = useRef<HTMLDivElement>(null);
// Focus the panel when it opens.
useEffect(() => {
@ -54,12 +55,8 @@ export function InspectorControls({
}, [settingsOpen]);
const handleDropdownBlur = (e: React.FocusEvent) => {
const related = e.relatedTarget as Node | null;
if (
related &&
(dropdownRef.current?.contains(related) ||
buttonRef.current?.contains(related))
) {
const relatedTarget = e.relatedTarget as Node | null;
if (relatedTarget && focusAreaRef.current?.contains(relatedTarget)) {
return;
}
setSettingsOpen(false);
@ -185,27 +182,30 @@ export function InspectorControls({
missionType={missionType}
onChange={onChangeMission}
/>
<button
ref={buttonRef}
className="IconButton Controls-toggle"
onClick={() => setSettingsOpen((isOpen) => !isOpen)}
onDoubleClick={(e) => e.preventDefault()}
aria-expanded={settingsOpen}
aria-controls="settingsPanel"
aria-label="Settings"
>
<FiSettings />
</button>
<div
className="Controls-dropdown"
ref={dropdownRef}
id="settingsPanel"
tabIndex={-1}
onKeyDown={handlePanelKeyDown}
onBlur={handleDropdownBlur}
data-open={settingsOpen}
>
{settingsFields}
<div ref={focusAreaRef}>
<button
ref={buttonRef}
className="IconButton Controls-toggle"
onClick={() => {
setSettingsOpen((isOpen) => !isOpen);
}}
aria-expanded={settingsOpen}
aria-controls="settingsPanel"
aria-label="Settings"
>
<FiSettings />
</button>
<div
className="Controls-dropdown"
ref={dropdownRef}
id="settingsPanel"
tabIndex={-1}
onKeyDown={handlePanelKeyDown}
onBlur={handleDropdownBlur}
data-open={settingsOpen}
>
{settingsFields}
</div>
</div>
</div>
);

View file

@ -7,7 +7,7 @@ import { useControls } from "./SettingsProvider";
const BASE_SPEED = 80;
const LOOK_SENSITIVITY = 0.004;
const STICK_LOOK_SENSITIVITY = 2.5;
const SINGLE_STICK_DEADZONE = 0.25;
const SINGLE_STICK_DEADZONE = 0.15;
const MAX_PITCH = Math.PI / 2 - 0.01; // ~89°
export type JoystickState = {
@ -100,6 +100,12 @@ export function TouchJoystick({
};
}, [touchMode, lookJoystickState, lookJoystickZone]);
const blurActiveElement = () => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
};
if (touchMode === "dualStick") {
return (
<>
@ -107,11 +113,13 @@ export function TouchJoystick({
ref={joystickZone}
className="TouchJoystick TouchJoystick--left"
onContextMenu={(e) => e.preventDefault()}
onTouchStart={blurActiveElement}
/>
<div
ref={lookJoystickZone}
className="TouchJoystick TouchJoystick--right"
onContextMenu={(e) => e.preventDefault()}
onTouchStart={blurActiveElement}
/>
</>
);
@ -122,6 +130,7 @@ export function TouchJoystick({
ref={joystickZone}
className="TouchJoystick"
onContextMenu={(e) => e.preventDefault()}
onTouchStart={blurActiveElement}
/>
);
}