From 6816f3b17ca8368578bc3d223f872f20fcfff421 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 19 Aug 2026 15:51:48 +0900 Subject: [PATCH] feat(ui): navigate trace steps with keyboard and remove indirect editor focus (#11005) Co-authored-by: Hiroshi Ogawa <4232207+hi-ogawa@users.noreply.github.com> Co-authored-by: OpenCode --- .../ui/client/components/trace/TraceView.vue | 42 ++++++++++++++++++- .../ui/client/components/views/ViewEditor.vue | 7 ---- test/ui/test/trace-stream.spec.ts | 8 ++-- test/ui/test/trace.spec.ts | 23 +++++++--- test/ui/test/ui.spec.ts | 1 + 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/packages/ui/client/components/trace/TraceView.vue b/packages/ui/client/components/trace/TraceView.vue index 4286e840f..744debad2 100644 --- a/packages/ui/client/components/trace/TraceView.vue +++ b/packages/ui/client/components/trace/TraceView.vue @@ -29,6 +29,35 @@ function onSelectStep(index: number) { } } +function onStepKeydown(event: KeyboardEvent, index: number) { + let nextIndex: number + if (event.key === 'ArrowUp') { + nextIndex = Math.max(index - 1, 0) + } + else if (event.key === 'ArrowDown') { + nextIndex = Math.min(index + 1, entries.value.length - 1) + } + else if (event.key === 'Home') { + nextIndex = 0 + } + else if (event.key === 'End') { + nextIndex = entries.value.length - 1 + } + else { + return + } + + event.preventDefault() + if (nextIndex === index) { + return + } + onSelectStep(nextIndex) + const nextButton = (event.currentTarget as HTMLButtonElement).parentElement?.children[nextIndex] + if (nextButton instanceof HTMLButtonElement) { + nextButton.focus() + } +} + watch([selectedStep, iframeEl], ([step, iframe]) => { if (!step || !iframe) { return @@ -143,18 +172,27 @@ function isTraceStepInProgress(step: NormalizedBrowserTraceEntry) { class="h-full min-h-0" > -
+