Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ Fully functional emergency evacuation simulation:

Immersive walkthrough experience with:
- **WASD movement** with collision detection against machines
- **Q/E vertical movement** for elevated inspection
- **Sprint mode** (Shift key) for faster exploration
- **Mouse look** with pointer lock controls
- **105° FOV** for immersive factory tours
Expand Down Expand Up @@ -791,6 +792,7 @@ MODBUS_PORT=502
|-------|--------|
| **V** | Toggle first-person mode |
| **WASD** | Move forward/left/back/right |
| **Q / E** | Move down/up |
| **Shift** | Sprint (3.6x speed) |
| **Mouse** | Look around |
| **Esc** | Exit first-person mode |
Expand Down
11 changes: 4 additions & 7 deletions docs/ACCESSIBILITY_AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -415,16 +415,13 @@ const shouldReduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)')

---

### 23. 3D Canvas Not Keyboard Accessible
**Location:** `src/App.tsx:202-253`, `src/components/MillScene.tsx`
### 23. 3D Canvas Keyboard Navigation
**Location:** `src/components/CameraController.tsx`, `src/utils/cameraNavigation.ts`
**WCAG:** 2.1.1 Keyboard (Level A)

**Issue:**
3D scene with OrbitControls is mouse-only. No keyboard controls for camera navigation.

**Current State:** OrbitControls exist but don't support keyboard by default.
**Current State:** Remediated. WASD and the arrow keys translate the camera, Q/E move down and up, and Shift increases travel speed. Movement uses physical key codes for keyboard-layout independence, stops when browser focus is lost, and remains inactive while an interface control has focus.

**Recommendation:** Implement keyboard camera controls (arrow keys for rotation, +/- for zoom) or provide alternative 2D representations of critical data.
**Residual Recommendation:** Continue providing the existing DOM control panels as the accessible representation of operational data that is also shown in the 3D scene.

---

Expand Down
86 changes: 4 additions & 82 deletions docs/ACCESSIBILITY_RECOMMENDATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,91 +344,13 @@ export const MyComponent = () => {

---

### 23. 3D Canvas Not Keyboard Accessible (WCAG 2.1.1 Keyboard - Level A)
### 23. 3D Canvas Keyboard Navigation (WCAG 2.1.1 Keyboard - Level A)

**Issue:** OrbitControls only work with mouse, no keyboard camera navigation.
**Status:** Implemented in `CameraController.tsx`, `FirstPersonController.tsx`, and `PhysicsFirstPersonController.tsx`, with shared input policy in `cameraNavigation.ts`.

**Impact:** Keyboard-only users cannot explore the 3D environment.
**Controls:** WASD and arrow keys translate, Q/E move down and up, and Shift increases speed. Physical key codes keep movement consistent across keyboard layouts. Navigation pauses for focused interface controls, browser blur, and hidden tabs. Collision resolution preserves the orbit target offset so blocked movement does not twist the view.

**Recommendation:**

Implement keyboard controls for 3D navigation:

```tsx
// src/components/KeyboardCameraControls.tsx
import { useEffect } from 'react';
import { useThree } from '@react-three/fiber';

interface KeyboardCameraControlsProps {
enabled?: boolean;
rotateSpeed?: number;
zoomSpeed?: number;
}

export const KeyboardCameraControls: React.FC<KeyboardCameraControlsProps> = ({
enabled = true,
rotateSpeed = 0.05,
zoomSpeed = 0.5,
}) => {
const { camera } = useThree();

useEffect(() => {
if (!enabled) return;

const handleKeyDown = (e: KeyboardEvent) => {
// Prevent default if we handle the key
const handled = true;

switch (e.key) {
case 'ArrowLeft':
// Rotate camera left
camera.position.x -= rotateSpeed;
break;
case 'ArrowRight':
// Rotate camera right
camera.position.x += rotateSpeed;
break;
case 'ArrowUp':
// Rotate camera up
camera.position.y += rotateSpeed;
break;
case 'ArrowDown':
// Rotate camera down
camera.position.y -= rotateSpeed;
break;
case '+':
case '=':
// Zoom in
camera.position.z -= zoomSpeed;
break;
case '-':
case '_':
// Zoom out
camera.position.z += zoomSpeed;
break;
default:
return; // Don't prevent default for unhandled keys
}

if (handled) {
e.preventDefault();
camera.lookAt(0, 0, 0); // Keep looking at center
}
};

window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [camera, enabled, rotateSpeed, zoomSpeed]);

return null;
};

// Usage in MillScene.tsx
<Canvas>
<KeyboardCameraControls />
{/* Rest of scene */}
</Canvas>
```
**Ongoing Recommendation:** Keep the DOM dashboards and panels fully operable without navigating the 3D scene, and retain automated keyboard and focus-safety coverage.

**Alternative: Provide 2D Representations**

Expand Down
7 changes: 4 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -661,9 +661,10 @@ const App: React.FC = () => {

{/* 3D Canvas keyboard accessibility notice - visible to screen readers */}
<div role="note" aria-label="3D visualization keyboard controls" className="sr-only">
The 3D factory visualization is interactive. Press V to toggle first-person view mode. Use
keyboard shortcuts: I for AI panel, O for SCADA, Escape to close panels. Press 1-5 to switch
camera presets. Arrow keys control camera in first-person mode.
The 3D factory visualization is interactive. Use W, A, S, D or the arrow keys to move, Q and
E to move down and up, and Shift to move faster. Press V to toggle first-person view mode.
Press 1-5 to switch camera presets. Keyboard movement pauses while an interface control has
focus.
</div>

{!runtimeMode.benchmark && !deferredUIReady && <StartupInterface />}
Expand Down
Loading