@@ -149,6 +149,21 @@ export const Playback: FC = () => {
149149
150150 const disabled = events . length === 0 ;
151151
152+ // Button refs for focus management
153+ const playPauseRef = useRef < HTMLButtonElement > ( null ) ;
154+ const stepSmallBackwardRef = useRef < HTMLButtonElement > ( null ) ;
155+ const stepBigBackwardRef = useRef < HTMLButtonElement > ( null ) ;
156+ const stepSmallForwardRef = useRef < HTMLButtonElement > ( null ) ;
157+ const stepBigForwardRef = useRef < HTMLButtonElement > ( null ) ;
158+ const speedSelectRef = useRef < HTMLSelectElement > ( null ) ;
159+
160+ const focusButton = ( ref : React . RefObject < HTMLElement | null > ) => {
161+ ref . current ?. focus ( ) ;
162+ setTimeout ( ( ) => {
163+ ref . current ?. blur ( ) ;
164+ } , 200 ) ; // Show focus for 200ms
165+ } ;
166+
152167 // Keyboard event handler
153168 useEffect ( ( ) => {
154169 const handleKeyDown = ( event : KeyboardEvent ) => {
@@ -157,26 +172,32 @@ export const Playback: FC = () => {
157172 switch ( event . code ) {
158173 case "Space" :
159174 event . preventDefault ( ) ;
175+ focusButton ( playPauseRef ) ;
160176 handlePlayPause ( ) ;
161177 break ;
162178 case "ArrowRight" :
163179 event . preventDefault ( ) ;
164180 if ( event . ctrlKey ) {
181+ focusButton ( stepBigForwardRef ) ;
165182 handleStep ( 1.0 * speedMultiplier ) ; // 10x forward (big step)
166183 } else {
184+ focusButton ( stepSmallForwardRef ) ;
167185 handleStep ( 0.1 * speedMultiplier ) ; // 1x forward (small step)
168186 }
169187 break ;
170188 case "ArrowLeft" :
171189 event . preventDefault ( ) ;
172190 if ( event . ctrlKey ) {
191+ focusButton ( stepBigBackwardRef ) ;
173192 handleStep ( - 1.0 * speedMultiplier ) ; // 10x backward (big step)
174193 } else {
194+ focusButton ( stepSmallBackwardRef ) ;
175195 handleStep ( - 0.1 * speedMultiplier ) ; // 1x backward (small step)
176196 }
177197 break ;
178198 case "ArrowUp" :
179199 event . preventDefault ( ) ;
200+ focusButton ( speedSelectRef ) ;
180201 // Increase speed to next available option
181202 {
182203 const currentIndex = SPEED_OPTIONS . indexOf ( speedMultiplier ) ;
@@ -190,6 +211,7 @@ export const Playback: FC = () => {
190211 break ;
191212 case "ArrowDown" :
192213 event . preventDefault ( ) ;
214+ focusButton ( speedSelectRef ) ;
193215 // Decrease speed to previous available option
194216 {
195217 const currentIndex = SPEED_OPTIONS . indexOf ( speedMultiplier ) ;
@@ -211,6 +233,7 @@ export const Playback: FC = () => {
211233 return (
212234 < div className = "flex items-center gap-2" >
213235 < Button
236+ ref = { playPauseRef }
214237 onClick = { handlePlayPause }
215238 disabled = { disabled }
216239 variant = "primary"
@@ -221,6 +244,7 @@ export const Playback: FC = () => {
221244 </ Button >
222245
223246 < Button
247+ ref = { stepBigBackwardRef }
224248 onClick = { ( ) => handleStep ( - 1.0 * speedMultiplier ) }
225249 onMouseDown = { ( e ) => {
226250 e . preventDefault ( ) ;
@@ -241,6 +265,7 @@ export const Playback: FC = () => {
241265 </ Button >
242266
243267 < Button
268+ ref = { stepSmallBackwardRef }
244269 onClick = { ( ) => handleStep ( - 0.1 * speedMultiplier ) }
245270 onMouseDown = { ( e ) => {
246271 e . preventDefault ( ) ;
@@ -261,6 +286,7 @@ export const Playback: FC = () => {
261286 </ Button >
262287
263288 < Button
289+ ref = { stepSmallForwardRef }
264290 onClick = { ( ) => handleStep ( 0.1 * speedMultiplier ) }
265291 onMouseDown = { ( e ) => {
266292 e . preventDefault ( ) ;
@@ -281,6 +307,7 @@ export const Playback: FC = () => {
281307 </ Button >
282308
283309 < Button
310+ ref = { stepBigForwardRef }
284311 onClick = { ( ) => handleStep ( 1.0 * speedMultiplier ) }
285312 onMouseDown = { ( e ) => {
286313 e . preventDefault ( ) ;
@@ -305,6 +332,7 @@ export const Playback: FC = () => {
305332 Speed
306333 </ label >
307334 < select
335+ ref = { speedSelectRef }
308336 name = "timelineSpeed"
309337 className = "mt-1 w-full text-sm"
310338 value = { speedMultiplier }
0 commit comments