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
29 changes: 27 additions & 2 deletions src/ui/temporal/TemporalView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
* glow and sweep as the storm passes when the weather is switched on.
*/
import { useEffect, useMemo, useRef, useState } from 'react';
import type { PointerEvent as ReactPointerEvent, RefObject } from 'react';
import type {
KeyboardEvent as ReactKeyboardEvent,
PointerEvent as ReactPointerEvent,
RefObject,
} from 'react';
import * as THREE from 'three';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
Expand Down Expand Up @@ -849,6 +853,19 @@ function TimeWheel({
};
inertiaRaf.current = requestAnimationFrame(step);
};
// Arrow keys step one slice at a time when the reel is focused, matching the
// drag metaphor: up = later time, down = earlier.
const onKeyDown = (e: ReactKeyboardEvent) => {
if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;
e.preventDefault();
stopInertia();
const dir = e.key === 'ArrowUp' ? 1 : -1;
const { interval, max } = cfgRef.current;
const slice = Math.round(curRef.current / interval);
const next = clampN((slice + dir) * interval, 0, max);
curRef.current = next;
setCurrentMin(next);
};
// Wheel over the controller scrubs time a slice at a time; Ctrl+wheel zooms the
// time step instead, staying on the current time. Native + non-passive so it can
// preventDefault — which also stops page zoom and the native <select> cycling
Expand Down Expand Up @@ -905,10 +922,18 @@ function TimeWheel({
</div>
<div
className="temporal-wheel-reel"
tabIndex={0}
role="slider"
aria-label="Time of day"
aria-valuemin={0}
aria-valuemax={maxMin}
aria-valuenow={Math.round(currentMin)}
aria-valuetext={formatTime(clampMin(Math.round(currentMin / intervalMin) * intervalMin))}
onPointerDown={onDown}
onPointerMove={onMove}
onPointerUp={onUp}
onPointerCancel={onUp}
onKeyDown={onKeyDown}
>
<div className="temporal-wheel-band" />
{ticks.map((t) => (
Expand All @@ -921,7 +946,7 @@ function TimeWheel({
</div>
))}
</div>
<div className="temporal-wheel-hint">drag ↕ or scroll · ctrl-scroll = zoom step · flick to spin</div>
<div className="temporal-wheel-hint">drag ↕ or scroll · ↑/↓ keys when focused · ctrl-scroll = zoom step · flick to spin</div>
</div>
);
}
Expand Down
5 changes: 5 additions & 0 deletions src/ui/temporal/temporal.css
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ body {
cursor: ns-resize;
touch-action: none;
}
.temporal-wheel-reel:focus-visible {
outline: none;
border-color: #2f6df0;
box-shadow: 0 0 0 2px rgba(47, 109, 240, 0.4);
}
.temporal-wheel-reel::before,
.temporal-wheel-reel::after {
content: '';
Expand Down
Loading