From f1679e35f29405c40766a0929aae648ec5c65249 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa <4232207+hi-ogawa@users.noreply.github.com> Date: Tue, 6 Oct 2026 10:24:18 +0900 Subject: [PATCH] refactor(ui): make trace fit a one-time zoom Co-Authored-By: Claude Opus 5.5 --- .../ui/client/components/trace/TraceView.vue | 31 +++++++------------ .../client/components/trace/TraceViewPane.vue | 5 ++- .../components/trace/TraceZoomControl.vue | 31 ++++++++++++------- packages/ui/client/composables/trace-view.ts | 14 +++------ test/ui/test/trace.spec.ts | 8 ++--- 5 files changed, 42 insertions(+), 47 deletions(-) diff --git a/packages/ui/client/components/trace/TraceView.vue b/packages/ui/client/components/trace/TraceView.vue index b21b80200..f9c95be37 100644 --- a/packages/ui/client/components/trace/TraceView.vue +++ b/packages/ui/client/components/trace/TraceView.vue @@ -5,18 +5,17 @@ import type { NormalizedBrowserTraceEntry, TraceSelection, } from '~/composables/trace-view' -import { useElementSize } from '@vueuse/core' import { createCache, createMirror, rebuild } from 'rrweb-snapshot' import { Pane, Splitpanes } from 'splitpanes' -import { computed, ref, watch, watchEffect } from 'vue' +import { computed, ref, watch } from 'vue' import { openLocation } from '~/composables/location' import { traceViewSplitSizes } from '~/composables/navigation' import { getTraceEntryClass, selectActiveTraceStep, showTraceSelectorHighlight, - traceFitScale, - traceScale, + traceReplayElement, + traceZoom, } from '~/composables/trace-view' const props = defineProps<{ @@ -34,28 +33,20 @@ const iframeSandbox = computed(() => { return props.trace.recordCanvas ? 'allow-same-origin allow-scripts' : 'allow-same-origin' }) -const replayContainer = ref() -const replayContainerSize = useElementSize(replayContainer) const viewport = computed(() => selectedStep.value?.snapshot.viewport) -watchEffect(() => { - const { width, height } = replayContainerSize - if (viewport.value && width.value && height.value) { - traceFitScale.value = Math.min( - width.value / viewport.value.width, - height.value / viewport.value.height, - 1, - ) - } -}) const scaledViewportStyle = computed(() => viewport.value ? { - width: `${Math.floor(viewport.value.width * traceScale.value)}px`, - height: `${Math.floor(viewport.value.height * traceScale.value)}px`, + width: `${Math.floor(viewport.value.width * traceZoom.value)}px`, + height: `${Math.floor(viewport.value.height * traceZoom.value)}px`, } : undefined, ) +function setReplayElement(el: unknown) { + traceReplayElement.value = el instanceof HTMLElement ? el : undefined +} + function onSelectStep(index: number) { selectActiveTraceStep(index) const step = entries.value[index] @@ -280,7 +271,7 @@ function onSplitpanesResized({ panes }: SplitpanesResizedPayload) {
-
+
No trace step found
diff --git a/packages/ui/client/components/trace/TraceViewPane.vue b/packages/ui/client/components/trace/TraceViewPane.vue index 414983736..d04284dde 100644 --- a/packages/ui/client/components/trace/TraceViewPane.vue +++ b/packages/ui/client/components/trace/TraceViewPane.vue @@ -20,6 +20,9 @@ const props = defineProps<{ }>() const trace = computed(() => getSelectedTrace(props.selection)) +const selectedViewport = computed( + () => trace.value?.entries[props.selection.selectedStepIndex]?.snapshot.viewport, +) const attemptLabel = computed(() => (trace.value ? getTraceAttemptLabel(trace.value) : '')) const traceAttempts = computed(() => [...getTraceAttemptMap(props.selection.test.artifacts)].map(([key, trace]) => ({ @@ -74,7 +77,7 @@ const traceLayoutPageUrl = computed(() => { {{ attemptLabel }} - +