diff --git a/.changeset/eleven-lilies-film.md b/.changeset/eleven-lilies-film.md new file mode 100644 index 0000000000..8d37a2d4ca --- /dev/null +++ b/.changeset/eleven-lilies-film.md @@ -0,0 +1,5 @@ +--- +"@workflow/web-shared": patch +--- + +Detail panel cleanup: module copy button, step id spacing, line for trace state diff --git a/packages/web-shared/src/components/new-trace-viewer/components/timeline.tsx b/packages/web-shared/src/components/new-trace-viewer/components/timeline.tsx index 618db3874a..21d90fd3fb 100644 --- a/packages/web-shared/src/components/new-trace-viewer/components/timeline.tsx +++ b/packages/web-shared/src/components/new-trace-viewer/components/timeline.tsx @@ -2,7 +2,15 @@ import { ArrowLeft, ArrowRight } from 'lucide-react'; import type { CSSProperties, ReactNode } from 'react'; -import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { + Fragment, + memo, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import { cn } from '../../../lib/utils'; import { formatDuration, @@ -266,13 +274,23 @@ function SegmentBar({ segments }: { segments: VisibleSegment[] }): ReactNode { const leadInLabel = formatDurationPrecise(seg.fullDurationMs); const showLeadInLabel = seg.pixelWidth >= Math.max(40, leadInLabel.length * 6 + 12); + const isFullWidthQueued = segments.length === 1; return ( - + + + {isFullWidthQueued ? ( + + ) : null} + ); } diff --git a/packages/web-shared/src/components/new-trace-viewer/utils.ts b/packages/web-shared/src/components/new-trace-viewer/utils.ts index ea34bba74e..5295eb7355 100644 --- a/packages/web-shared/src/components/new-trace-viewer/utils.ts +++ b/packages/web-shared/src/components/new-trace-viewer/utils.ts @@ -243,7 +243,7 @@ function computeStepSegmentsFromSpan( ]); if (marks.length === 0) { - segments.push({ startFraction: 0, endFraction: 1, status: 'running' }); + segments.push({ startFraction: 0, endFraction: 1, status: 'queued' }); return segments; } diff --git a/packages/web-shared/src/components/sidebar/attribute-panel.tsx b/packages/web-shared/src/components/sidebar/attribute-panel.tsx index bd9bed416a..3bc7f65f6f 100644 --- a/packages/web-shared/src/components/sidebar/attribute-panel.tsx +++ b/packages/web-shared/src/components/sidebar/attribute-panel.tsx @@ -7,7 +7,6 @@ import { format } from 'date-fns'; import type { KeyboardEvent, ReactNode } from 'react'; import { useCallback, useContext, useMemo, useState } from 'react'; import { isEncryptedMarker, isExpiredMarker } from '../../lib/hydration'; -import { useToast } from '../../lib/toast'; import { extractConversation, isDoStreamStep } from '../../lib/utils'; import { CopyButton } from '../new-trace-viewer/components/copy-button'; import { MiddleTruncate } from '../new-trace-viewer/components/middle-truncate/middle-truncate'; @@ -616,6 +615,7 @@ const copyableBasicAttributes = new Set([ 'hookId', 'eventId', 'deploymentId', + 'moduleSpecifier', ]); export const AttributeBlock = ({ @@ -733,7 +733,6 @@ export const AttributePanel = ({ /** Resource type of the selected span — used to show targeted loading skeletons. */ resource?: string; }) => { - const toast = useToast(); // Extract workflowCoreVersion from executionContext for display const displayData = useMemo(() => { const result = { ...data }; @@ -819,17 +818,6 @@ export const AttributePanel = ({ }), [displayData.stepName] ); - const handleCopyModuleSpecifier = useCallback((value: string) => { - navigator.clipboard - .writeText(value) - .then(() => { - toast.success('moduleSpecifier copied'); - }) - .catch(() => { - toast.error('Failed to copy moduleSpecifier'); - }); - }, []); - const outerDecryptCtx = useContext(DecryptClickContext); const decryptValue = onDecrypt ? { @@ -850,16 +838,9 @@ export const AttributePanel = ({ const displayValue = attributeToDisplayFn[ attribute as keyof typeof attributeToDisplayFn ]?.(displayData[attribute as keyof typeof displayData]); - const isModuleSpecifier = attribute === 'moduleSpecifier'; const isCopyableBasicAttribute = copyableBasicAttributes.has(attribute as AttributeKey) && typeof displayValue === 'string'; - const moduleSpecifierValue = - typeof displayValue === 'string' - ? displayValue - : String( - displayValue ?? displayData.moduleSpecifier ?? '' - ); return ( {getAttributeDisplayName(attribute)} - {isModuleSpecifier ? ( - - handleCopyModuleSpecifier(moduleSpecifierValue) - } - > - {moduleSpecifierValue} - - ) : isCopyableBasicAttribute ? ( + {isCopyableBasicAttribute ? (