@shipfox/client-workflows 20.0.0 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +51 -0
  3. package/dist/components/job-detail/job-detail-view.d.ts.map +1 -1
  4. package/dist/components/job-detail/job-detail-view.js +232 -44
  5. package/dist/components/job-detail/job-detail-view.js.map +1 -1
  6. package/dist/components/job-detail/job-empty-states.js +2 -2
  7. package/dist/components/job-detail/job-empty-states.js.map +1 -1
  8. package/dist/components/job-detail/step-attempt-log-panel.d.ts +7 -1
  9. package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -1
  10. package/dist/components/job-detail/step-attempt-log-panel.js +37 -10
  11. package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -1
  12. package/dist/components/job-graph/job-graph-content.js +2 -2
  13. package/dist/components/job-graph/job-graph-content.js.map +1 -1
  14. package/dist/components/step-list/step-list-model.d.ts +1 -0
  15. package/dist/components/step-list/step-list-model.d.ts.map +1 -1
  16. package/dist/components/step-list/step-list-model.js +1 -1
  17. package/dist/components/step-list/step-list-model.js.map +1 -1
  18. package/dist/components/step-list/step-list.d.ts +2 -1
  19. package/dist/components/step-list/step-list.d.ts.map +1 -1
  20. package/dist/components/step-list/step-list.js +25 -9
  21. package/dist/components/step-list/step-list.js.map +1 -1
  22. package/dist/components/workflow-run-list/job-status-strip.d.ts +9 -1
  23. package/dist/components/workflow-run-list/job-status-strip.d.ts.map +1 -1
  24. package/dist/components/workflow-run-list/job-status-strip.js +22 -11
  25. package/dist/components/workflow-run-list/job-status-strip.js.map +1 -1
  26. package/dist/components/workflow-run-list/workflow-run-filters.js +1 -1
  27. package/dist/components/workflow-run-list/workflow-run-filters.js.map +1 -1
  28. package/dist/components/workflow-run-list/workflow-run-list-content.d.ts.map +1 -1
  29. package/dist/components/workflow-run-list/workflow-run-list-content.js +13 -7
  30. package/dist/components/workflow-run-list/workflow-run-list-content.js.map +1 -1
  31. package/dist/components/workflow-run-list/workflow-run-list-states.d.ts.map +1 -1
  32. package/dist/components/workflow-run-list/workflow-run-list-states.js +43 -38
  33. package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -1
  34. package/dist/components/workflow-run-list/workflow-run-list-view.d.ts.map +1 -1
  35. package/dist/components/workflow-run-list/workflow-run-list-view.js +34 -22
  36. package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -1
  37. package/dist/components/workflow-run-list/workflow-run-row.d.ts +3 -3
  38. package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -1
  39. package/dist/components/workflow-run-list/workflow-run-row.js +25 -18
  40. package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
  41. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
  42. package/dist/components/workflow-run-summary/workflow-run-summary.js +4 -4
  43. package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
  44. package/dist/components/workflow-run-view/run-workspace-nav.d.ts.map +1 -1
  45. package/dist/components/workflow-run-view/run-workspace-nav.js +20 -7
  46. package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -1
  47. package/dist/components/workflow-run-view/workflow-run-states.d.ts.map +1 -1
  48. package/dist/components/workflow-run-view/workflow-run-states.js +1 -1
  49. package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -1
  50. package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
  51. package/dist/components/workflow-run-view/workflow-run-view.js +103 -78
  52. package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
  53. package/dist/components/workflow-source-panel/workflow-source-content.js +1 -1
  54. package/dist/components/workflow-source-panel/workflow-source-content.js.map +1 -1
  55. package/dist/pages/project-workflows-page.d.ts.map +1 -1
  56. package/dist/pages/project-workflows-page.js +171 -158
  57. package/dist/pages/project-workflows-page.js.map +1 -1
  58. package/dist/pages/workflow-job-detail-page.d.ts.map +1 -1
  59. package/dist/pages/workflow-job-detail-page.js +3 -2
  60. package/dist/pages/workflow-job-detail-page.js.map +1 -1
  61. package/dist/pages/workflow-run-detail-page.js +2 -1
  62. package/dist/pages/workflow-run-detail-page.js.map +1 -1
  63. package/dist/pages/workflow-run-list-page.d.ts.map +1 -1
  64. package/dist/pages/workflow-run-list-page.js +9 -11
  65. package/dist/pages/workflow-run-list-page.js.map +1 -1
  66. package/dist/routes/job-detail.d.ts +1 -1
  67. package/dist/routes/job-detail.js +1 -1
  68. package/dist/routes/job-detail.js.map +1 -1
  69. package/dist/routes/run-detail.d.ts +1 -1
  70. package/dist/routes/run-detail.js +1 -1
  71. package/dist/routes/run-detail.js.map +1 -1
  72. package/dist/routes/runs.d.ts +1 -1
  73. package/dist/routes/runs.js +1 -1
  74. package/dist/routes/runs.js.map +1 -1
  75. package/dist/routes/workflows.d.ts +3 -0
  76. package/dist/routes/workflows.js +3 -0
  77. package/dist/routes/workflows.js.map +1 -1
  78. package/dist/tsconfig.test.tsbuildinfo +1 -1
  79. package/package.json +8 -8
  80. package/src/components/job-detail/job-detail-view.tsx +264 -49
  81. package/src/components/job-detail/job-empty-states.tsx +2 -2
  82. package/src/components/job-detail/step-attempt-log-panel.test.tsx +30 -12
  83. package/src/components/job-detail/step-attempt-log-panel.tsx +68 -10
  84. package/src/components/job-graph/job-graph-content.tsx +2 -2
  85. package/src/components/job-graph/job-graph.stories.tsx +1 -1
  86. package/src/components/job-graph/job-node.stories.tsx +1 -1
  87. package/src/components/step-list/step-list-model.ts +1 -1
  88. package/src/components/step-list/step-list.test.tsx +29 -1
  89. package/src/components/step-list/step-list.tsx +29 -11
  90. package/src/components/workflow-run-list/job-status-strip.tsx +25 -12
  91. package/src/components/workflow-run-list/workflow-run-filters.tsx +1 -1
  92. package/src/components/workflow-run-list/workflow-run-list-content.tsx +7 -2
  93. package/src/components/workflow-run-list/workflow-run-list-states.tsx +42 -41
  94. package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +53 -4
  95. package/src/components/workflow-run-list/workflow-run-list-view.tsx +28 -22
  96. package/src/components/workflow-run-list/workflow-run-list.stories.tsx +9 -20
  97. package/src/components/workflow-run-list/workflow-run-row.tsx +26 -19
  98. package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +3 -3
  99. package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +11 -2
  100. package/src/components/workflow-run-summary/workflow-run-summary.tsx +4 -7
  101. package/src/components/workflow-run-view/run-workspace-nav.test.tsx +40 -2
  102. package/src/components/workflow-run-view/run-workspace-nav.tsx +28 -9
  103. package/src/components/workflow-run-view/workflow-run-states.tsx +1 -4
  104. package/src/components/workflow-run-view/workflow-run-view.stories.tsx +142 -0
  105. package/src/components/workflow-run-view/workflow-run-view.test.tsx +42 -8
  106. package/src/components/workflow-run-view/workflow-run-view.tsx +112 -96
  107. package/src/components/workflow-source-panel/workflow-source-content.tsx +2 -2
  108. package/src/pages/project-workflows-page.tsx +135 -125
  109. package/src/pages/workflow-job-detail-page.test.tsx +32 -0
  110. package/src/pages/workflow-job-detail-page.tsx +5 -1
  111. package/src/pages/workflow-run-detail-page.tsx +1 -1
  112. package/src/pages/workflow-run-list-page.tsx +9 -11
  113. package/src/pages/workflow-run-pages.test.tsx +26 -0
  114. package/src/routes/job-detail.tsx +1 -1
  115. package/src/routes/run-detail.tsx +1 -1
  116. package/src/routes/runs.tsx +1 -1
  117. package/src/routes/workflows.tsx +1 -0
  118. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { TriggerSourceIcon } from '@shipfox/client-triggers';
3
3
  import { Icon } from '@shipfox/react-ui/icon';
4
+ import { Panel } from '@shipfox/react-ui/panel';
4
5
  import { RelativeTime } from '@shipfox/react-ui/relative-time';
5
6
  import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
6
7
  import { Code, Text } from '@shipfox/react-ui/typography';
@@ -12,20 +13,23 @@ import { getWorkflowStatusVisual } from '#components/workflow-status/status-visu
12
13
  import { WorkflowStatusIcon } from '#components/workflow-status/workflow-status-icon.js';
13
14
  import { workflowRunActor, workflowRunBranchLabel, workflowRunCommitLabel } from '#core/workflow-run.js';
14
15
  import { withoutWorkflowRunSelectionSearch } from '#core/workflow-run-url-state.js';
15
- import { JobStatusStrip, jobStatusSummary } from './job-status-strip.js';
16
+ import { JOB_STATUS_STRIP_WIDTH, JobStatusStrip, jobStatusSummary } from './job-status-strip.js';
16
17
  export function WorkflowRunRowList({ runs, workspaceSlug, projectSlug }) {
17
- return(// A container, not the viewport, drives the row's breakpoints. The list is capped at
18
- // 1120px inside a wider page, so what a row can afford is its own width; keying off the
19
- // viewport would keep the job strip hidden on a wide screen or crush it on a narrow one.
20
- /*#__PURE__*/ _jsx("ul", {
21
- className: "@container divide-y divide-border-neutral-base border-t border-border-neutral-base",
22
- children: runs.map((run)=>/*#__PURE__*/ _jsx("li", {
23
- children: /*#__PURE__*/ _jsx(WorkflowRunRow, {
24
- run: run,
25
- workspaceSlug: workspaceSlug,
26
- projectSlug: projectSlug
27
- })
28
- }, run.id))
18
+ return(// A container, not the viewport, drives the row's breakpoints. What a row can afford is its
19
+ // own width; keying off the viewport would keep the job strip hidden on a wide screen or
20
+ // crush it on a narrow one.
21
+ /*#__PURE__*/ _jsx(Panel, {
22
+ className: "@container",
23
+ children: /*#__PURE__*/ _jsx("ul", {
24
+ className: "divide-y divide-border-neutral-base",
25
+ children: runs.map((run)=>/*#__PURE__*/ _jsx("li", {
26
+ children: /*#__PURE__*/ _jsx(WorkflowRunRow, {
27
+ run: run,
28
+ workspaceSlug: workspaceSlug,
29
+ projectSlug: projectSlug
30
+ })
31
+ }, run.id))
32
+ })
29
33
  }));
30
34
  }
31
35
  /**
@@ -36,9 +40,9 @@ export function WorkflowRunRowList({ runs, workspaceSlug, projectSlug }) {
36
40
  * drops beneath. The numeric columns are fixed-width so duration and time form real columns
37
41
  * down the list rather than tracking each row's name length.
38
42
  *
39
- * The thresholds are the container widths the spec's viewport breakpoints produce, given a
40
- * column capped at 1120px with 24px of page padding on each side: a 1280px viewport leaves
41
- * the row 1072px, and a 1024px viewport leaves it 976px.
43
+ * The 976px threshold keeps identity and provenance on one line; below it, provenance drops
44
+ * beneath the identity. The 1200px threshold keeps the full job preview and numeric columns
45
+ * readable together; below it, the strip is hidden so the numeric columns remain aligned.
42
46
  */ export function WorkflowRunRow({ run, workspaceSlug, projectSlug }) {
43
47
  const duration = run.runAttempt.displayDuration;
44
48
  const hasStarted = run.jobs.hasStartedJobExecution;
@@ -97,7 +101,10 @@ export function WorkflowRunRowList({ runs, workspaceSlug, projectSlug }) {
97
101
  className: "flex shrink-0 items-center gap-cluster",
98
102
  children: [
99
103
  /*#__PURE__*/ _jsx("span", {
100
- className: "hidden w-160 @min-[1040px]:flex",
104
+ className: "hidden w-max shrink-0 @min-[1200px]:flex",
105
+ style: {
106
+ minWidth: JOB_STATUS_STRIP_WIDTH
107
+ },
101
108
  children: /*#__PURE__*/ _jsx(JobStatusStrip, {
102
109
  jobs: run.jobs
103
110
  })
@@ -122,7 +129,7 @@ export function WorkflowRunRowList({ runs, workspaceSlug, projectSlug }) {
122
129
  });
123
130
  // Rows run edge to edge inside the list's scroll container, which would clip the standard
124
131
  // outset focus ring, so this one is inset per the design system's focus-ring rule.
125
- const rowClassName = 'flex w-full min-w-0 items-center gap-inline px-row py-row text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-[inset_0_0_0_2px_var(--color-primary-500)] focus-visible:outline-none @min-[976px]:h-44 @min-[976px]:py-0';
132
+ const rowClassName = 'flex w-full min-w-0 items-center gap-inline px-row py-row text-left transition-colors hover:bg-background-neutral-hover focus-visible:shadow-focus-inset focus-visible:outline-none @min-[976px]:h-44 @min-[976px]:py-0';
126
133
  // Optimistic manual runs (temp-<uuid>) have no detail page until the canonical row
127
134
  // replaces them on the next poll, so they render non-interactively instead of as a link
128
135
  // that would navigate to a workflow run id the detail route rejects.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-list/workflow-run-row.tsx"],"sourcesContent":["import {TriggerSourceIcon} from '@shipfox/client-triggers';\nimport {Icon, type IconName} from '@shipfox/react-ui/icon';\nimport {RelativeTime} from '@shipfox/react-ui/relative-time';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport {\n useWorkflowRunDurationAccessibleLabel,\n WorkflowRunDurationLabel,\n} from '#components/workflow-run-duration-label.js';\nimport {\n formatWorkflowRunNumberLabel,\n WorkflowRunNumberLabel,\n} from '#components/workflow-run-number-label.js';\nimport {getWorkflowStatusVisual} from '#components/workflow-status/status-visuals.js';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport {\n type WorkflowRunListItem,\n workflowRunActor,\n workflowRunBranchLabel,\n workflowRunCommitLabel,\n} from '#core/workflow-run.js';\nimport {withoutWorkflowRunSelectionSearch} from '#core/workflow-run-url-state.js';\nimport {JobStatusStrip, jobStatusSummary} from './job-status-strip.js';\n\nexport function WorkflowRunRowList({\n runs,\n workspaceSlug,\n projectSlug,\n}: {\n runs: WorkflowRunListItem[];\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n}) {\n return (\n // A container, not the viewport, drives the row's breakpoints. The list is capped at\n // 1120px inside a wider page, so what a row can afford is its own width; keying off the\n // viewport would keep the job strip hidden on a wide screen or crush it on a narrow one.\n <ul className=\"@container divide-y divide-border-neutral-base border-t border-border-neutral-base\">\n {runs.map((run) => (\n <li key={run.id}>\n <WorkflowRunRow run={run} workspaceSlug={workspaceSlug} projectSlug={projectSlug} />\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * One run at full width.\n *\n * A single 44px line once the list is at least 976px wide, reflowing to two lines below that:\n * the identity and the numerics keep their places on line one, and the provenance metadata\n * drops beneath. The numeric columns are fixed-width so duration and time form real columns\n * down the list rather than tracking each row's name length.\n *\n * The thresholds are the container widths the spec's viewport breakpoints produce, given a\n * column capped at 1120px with 24px of page padding on each side: a 1280px viewport leaves\n * the row 1072px, and a 1024px viewport leaves it 976px.\n */\nexport function WorkflowRunRow({\n run,\n workspaceSlug,\n projectSlug,\n}: {\n run: WorkflowRunListItem;\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n}) {\n const duration = run.runAttempt.displayDuration;\n const hasStarted = run.jobs.hasStartedJobExecution;\n const durationLabel = useWorkflowRunDurationAccessibleLabel(duration, hasStarted);\n const status = run.runAttempt.status;\n const statusLabel = getWorkflowStatusVisual(status).label;\n const runNumberLabel = formatWorkflowRunNumberLabel(run);\n const branch = workflowRunBranchLabel(run);\n const commit = workflowRunCommitLabel(run);\n const actor = workflowRunActor(run);\n\n const body = (\n <>\n <WorkflowStatusIcon status={status} size={14} className=\"shrink-0\" />\n\n <div className=\"flex min-w-0 flex-1 flex-col gap-tight @min-[976px]:flex-row @min-[976px]:items-center @min-[976px]:gap-cluster\">\n <span className=\"flex min-w-0 items-center gap-inline @min-[976px]:flex-1\">\n <Code variant=\"label\" bold className=\"truncate text-foreground-neutral-base\">\n {run.name}\n </Code>\n {run.number !== null ? <WorkflowRunNumberLabel run={run} /> : null}\n </span>\n\n <span className=\"flex min-w-0 flex-wrap items-center gap-inline text-foreground-neutral-subtle @min-[976px]:flex-nowrap @min-[976px]:shrink-0\">\n {run.triggerDisplayLabel ? <TriggerLabel run={run} /> : null}\n {branch ? <BranchLabel branch={branch} isPullRequest={branch.startsWith('#')} /> : null}\n {commit ? <CommitLabel commit={commit} /> : null}\n {actor ? <ActorLabel actor={actor} /> : null}\n </span>\n </div>\n\n <span className=\"flex shrink-0 items-center gap-cluster\">\n {/* Fixed at the strip's worst case (see MAX_VISIBLE_JOBS) so the overflow count cannot\n paint over the duration, and kept even when a run has no jobs planned yet, so the\n numerics stay in line down the list instead of stepping in and out. */}\n <span className=\"hidden w-160 @min-[1040px]:flex\">\n <JobStatusStrip jobs={run.jobs} />\n </span>\n <span className=\"flex w-64 justify-end\">\n <WorkflowRunDurationLabel duration={duration} hasStarted={hasStarted} />\n </span>\n <Code\n variant=\"label\"\n className=\"w-64 shrink-0 text-right tabular-nums text-foreground-neutral-muted\"\n >\n <RelativeTime value={run.createdAt} />\n </Code>\n </span>\n </>\n );\n\n // Rows run edge to edge inside the list's scroll container, which would clip the standard\n // outset focus ring, so this one is inset per the design system's focus-ring rule.\n const rowClassName =\n 'flex w-full min-w-0 items-center gap-inline px-row py-row text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-[inset_0_0_0_2px_var(--color-primary-500)] focus-visible:outline-none @min-[976px]:h-44 @min-[976px]:py-0';\n\n // Optimistic manual runs (temp-<uuid>) have no detail page until the canonical row\n // replaces them on the next poll, so they render non-interactively instead of as a link\n // that would navigate to a workflow run id the detail route rejects.\n if (run.isTemporary || !workspaceSlug || !projectSlug) {\n return <div className={rowClassName}>{body}</div>;\n }\n\n return (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId: run.id}}\n search={\n ((previous: Record<string, unknown>) =>\n withoutWorkflowRunSelectionSearch(previous)) as never\n }\n // An aria-label is the link's whole accessible name, so anything inside the row that\n // carries its own label (the status glyph, the job strip) goes unspoken unless it is\n // curated in here. The job breakdown is the reason this list is worth its width, so it\n // belongs in what a tabbing user hears, not only in browse mode.\n aria-label={[\n run.name,\n runNumberLabel,\n statusLabel,\n durationLabel,\n run.triggerLabel,\n branch ? `branch ${branch}` : undefined,\n actor ? `by ${actor}` : undefined,\n run.jobs.total > 0 ? jobStatusSummary(run.jobs) : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(', ')}\n className={rowClassName}\n >\n {body}\n </Link>\n );\n}\n\nfunction TriggerLabel({run}: {run: WorkflowRunListItem}) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"flex min-w-0 max-w-[140px] items-center gap-tight outline-none\">\n <TriggerSourceIcon\n provider={run.triggerProvider}\n source={run.triggerSource}\n aria-hidden=\"true\"\n className=\"size-12 shrink-0 text-foreground-neutral-muted\"\n />\n <Text as=\"span\" size=\"xs\" className=\"min-w-0 truncate\">\n {run.triggerDisplayLabel}\n </Text>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n <Text as=\"span\" size=\"xs\" className=\"block max-w-[360px] break-words\">\n {run.triggerLabel}\n </Text>\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction BranchLabel({branch, isPullRequest}: {branch: string; isPullRequest: boolean}) {\n return (\n <MetadataChip\n icon={isPullRequest ? 'gitPullRequestLine' : 'gitBranchLine'}\n title={isPullRequest ? `Pull request ${branch}` : `Branch ${branch}`}\n className=\"max-w-[180px]\"\n >\n {branch}\n </MetadataChip>\n );\n}\n\nfunction CommitLabel({commit}: {commit: string}) {\n return (\n <MetadataChip icon=\"gitCommitLine\" title={`Commit ${commit}`}>\n {commit}\n </MetadataChip>\n );\n}\n\nfunction ActorLabel({actor}: {actor: string}) {\n return (\n <MetadataChip\n icon=\"userLine\"\n title={`Triggered by ${actor}`}\n // Dropped once the row is two lines, where the provenance line has to stay readable on\n // a phone.\n className=\"hidden max-w-[120px] @min-[976px]:flex\"\n >\n {actor}\n </MetadataChip>\n );\n}\n\n/**\n * A ref, SHA, or handle: monospace because it is content a user copies or pattern-matches,\n * with the icon carrying the kind so the value itself never needs a written label.\n */\nfunction MetadataChip({\n icon,\n title,\n className,\n children,\n}: {\n icon: IconName;\n title: string;\n className?: string | undefined;\n children: string;\n}) {\n return (\n <span className={cn('flex min-w-0 shrink-0 items-center gap-tight', className)} title={title}>\n <Icon name={icon} className=\"size-12 shrink-0 text-foreground-neutral-muted\" aria-hidden />\n <Code as=\"span\" variant=\"label\" className=\"min-w-0 truncate\">\n {children}\n </Code>\n </span>\n );\n}\n"],"names":["TriggerSourceIcon","Icon","RelativeTime","Tooltip","TooltipContent","TooltipTrigger","Code","Text","cn","Link","useWorkflowRunDurationAccessibleLabel","WorkflowRunDurationLabel","formatWorkflowRunNumberLabel","WorkflowRunNumberLabel","getWorkflowStatusVisual","WorkflowStatusIcon","workflowRunActor","workflowRunBranchLabel","workflowRunCommitLabel","withoutWorkflowRunSelectionSearch","JobStatusStrip","jobStatusSummary","WorkflowRunRowList","runs","workspaceSlug","projectSlug","ul","className","map","run","li","WorkflowRunRow","id","duration","runAttempt","displayDuration","hasStarted","jobs","hasStartedJobExecution","durationLabel","status","statusLabel","label","runNumberLabel","branch","commit","actor","body","size","div","span","variant","bold","name","number","triggerDisplayLabel","TriggerLabel","BranchLabel","isPullRequest","startsWith","CommitLabel","ActorLabel","value","createdAt","rowClassName","isTemporary","to","params","workflowRunId","search","previous","aria-label","triggerLabel","undefined","total","filter","part","Boolean","join","asChild","provider","triggerProvider","source","triggerSource","aria-hidden","as","MetadataChip","icon","title","children"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-list/workflow-run-row.tsx"],"sourcesContent":["import {TriggerSourceIcon} from '@shipfox/client-triggers';\nimport {Icon, type IconName} from '@shipfox/react-ui/icon';\nimport {Panel} from '@shipfox/react-ui/panel';\nimport {RelativeTime} from '@shipfox/react-ui/relative-time';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport {\n useWorkflowRunDurationAccessibleLabel,\n WorkflowRunDurationLabel,\n} from '#components/workflow-run-duration-label.js';\nimport {\n formatWorkflowRunNumberLabel,\n WorkflowRunNumberLabel,\n} from '#components/workflow-run-number-label.js';\nimport {getWorkflowStatusVisual} from '#components/workflow-status/status-visuals.js';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport {\n type WorkflowRunListItem,\n workflowRunActor,\n workflowRunBranchLabel,\n workflowRunCommitLabel,\n} from '#core/workflow-run.js';\nimport {withoutWorkflowRunSelectionSearch} from '#core/workflow-run-url-state.js';\nimport {JOB_STATUS_STRIP_WIDTH, JobStatusStrip, jobStatusSummary} from './job-status-strip.js';\n\nexport function WorkflowRunRowList({\n runs,\n workspaceSlug,\n projectSlug,\n}: {\n runs: WorkflowRunListItem[];\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n}) {\n return (\n // A container, not the viewport, drives the row's breakpoints. What a row can afford is its\n // own width; keying off the viewport would keep the job strip hidden on a wide screen or\n // crush it on a narrow one.\n <Panel className=\"@container\">\n <ul className=\"divide-y divide-border-neutral-base\">\n {runs.map((run) => (\n <li key={run.id}>\n <WorkflowRunRow run={run} workspaceSlug={workspaceSlug} projectSlug={projectSlug} />\n </li>\n ))}\n </ul>\n </Panel>\n );\n}\n\n/**\n * One run at full width.\n *\n * A single 44px line once the list is at least 976px wide, reflowing to two lines below that:\n * the identity and the numerics keep their places on line one, and the provenance metadata\n * drops beneath. The numeric columns are fixed-width so duration and time form real columns\n * down the list rather than tracking each row's name length.\n *\n * The 976px threshold keeps identity and provenance on one line; below it, provenance drops\n * beneath the identity. The 1200px threshold keeps the full job preview and numeric columns\n * readable together; below it, the strip is hidden so the numeric columns remain aligned.\n */\nexport function WorkflowRunRow({\n run,\n workspaceSlug,\n projectSlug,\n}: {\n run: WorkflowRunListItem;\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n}) {\n const duration = run.runAttempt.displayDuration;\n const hasStarted = run.jobs.hasStartedJobExecution;\n const durationLabel = useWorkflowRunDurationAccessibleLabel(duration, hasStarted);\n const status = run.runAttempt.status;\n const statusLabel = getWorkflowStatusVisual(status).label;\n const runNumberLabel = formatWorkflowRunNumberLabel(run);\n const branch = workflowRunBranchLabel(run);\n const commit = workflowRunCommitLabel(run);\n const actor = workflowRunActor(run);\n\n const body = (\n <>\n <WorkflowStatusIcon status={status} size={14} className=\"shrink-0\" />\n\n <div className=\"flex min-w-0 flex-1 flex-col gap-tight @min-[976px]:flex-row @min-[976px]:items-center @min-[976px]:gap-cluster\">\n <span className=\"flex min-w-0 items-center gap-inline @min-[976px]:flex-1\">\n <Code variant=\"label\" bold className=\"truncate text-foreground-neutral-base\">\n {run.name}\n </Code>\n {run.number !== null ? <WorkflowRunNumberLabel run={run} /> : null}\n </span>\n\n <span className=\"flex min-w-0 flex-wrap items-center gap-inline text-foreground-neutral-subtle @min-[976px]:flex-nowrap @min-[976px]:shrink-0\">\n {run.triggerDisplayLabel ? <TriggerLabel run={run} /> : null}\n {branch ? <BranchLabel branch={branch} isPullRequest={branch.startsWith('#')} /> : null}\n {commit ? <CommitLabel commit={commit} /> : null}\n {actor ? <ActorLabel actor={actor} /> : null}\n </span>\n </div>\n\n <span className=\"flex shrink-0 items-center gap-cluster\">\n {/* Reserve the API preview's full width so the overflow count cannot paint over the\n duration, and keep it even when a run has no jobs planned yet so the numerics stay in\n line down the list instead of stepping in and out. The max-content width expands if\n the payload ever exceeds the current API preview bound. */}\n <span\n className=\"hidden w-max shrink-0 @min-[1200px]:flex\"\n style={{minWidth: JOB_STATUS_STRIP_WIDTH}}\n >\n <JobStatusStrip jobs={run.jobs} />\n </span>\n <span className=\"flex w-64 justify-end\">\n <WorkflowRunDurationLabel duration={duration} hasStarted={hasStarted} />\n </span>\n <Code\n variant=\"label\"\n className=\"w-64 shrink-0 text-right tabular-nums text-foreground-neutral-muted\"\n >\n <RelativeTime value={run.createdAt} />\n </Code>\n </span>\n </>\n );\n\n // Rows run edge to edge inside the list's scroll container, which would clip the standard\n // outset focus ring, so this one is inset per the design system's focus-ring rule.\n const rowClassName =\n 'flex w-full min-w-0 items-center gap-inline px-row py-row text-left transition-colors hover:bg-background-neutral-hover focus-visible:shadow-focus-inset focus-visible:outline-none @min-[976px]:h-44 @min-[976px]:py-0';\n\n // Optimistic manual runs (temp-<uuid>) have no detail page until the canonical row\n // replaces them on the next poll, so they render non-interactively instead of as a link\n // that would navigate to a workflow run id the detail route rejects.\n if (run.isTemporary || !workspaceSlug || !projectSlug) {\n return <div className={rowClassName}>{body}</div>;\n }\n\n return (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId: run.id}}\n search={\n ((previous: Record<string, unknown>) =>\n withoutWorkflowRunSelectionSearch(previous)) as never\n }\n // An aria-label is the link's whole accessible name, so anything inside the row that\n // carries its own label (the status glyph, the job strip) goes unspoken unless it is\n // curated in here. The job breakdown is the reason this list is worth its width, so it\n // belongs in what a tabbing user hears, not only in browse mode.\n aria-label={[\n run.name,\n runNumberLabel,\n statusLabel,\n durationLabel,\n run.triggerLabel,\n branch ? `branch ${branch}` : undefined,\n actor ? `by ${actor}` : undefined,\n run.jobs.total > 0 ? jobStatusSummary(run.jobs) : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(', ')}\n className={rowClassName}\n >\n {body}\n </Link>\n );\n}\n\nfunction TriggerLabel({run}: {run: WorkflowRunListItem}) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"flex min-w-0 max-w-[140px] items-center gap-tight outline-none\">\n <TriggerSourceIcon\n provider={run.triggerProvider}\n source={run.triggerSource}\n aria-hidden=\"true\"\n className=\"size-12 shrink-0 text-foreground-neutral-muted\"\n />\n <Text as=\"span\" size=\"xs\" className=\"min-w-0 truncate\">\n {run.triggerDisplayLabel}\n </Text>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n <Text as=\"span\" size=\"xs\" className=\"block max-w-[360px] break-words\">\n {run.triggerLabel}\n </Text>\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction BranchLabel({branch, isPullRequest}: {branch: string; isPullRequest: boolean}) {\n return (\n <MetadataChip\n icon={isPullRequest ? 'gitPullRequestLine' : 'gitBranchLine'}\n title={isPullRequest ? `Pull request ${branch}` : `Branch ${branch}`}\n className=\"max-w-[180px]\"\n >\n {branch}\n </MetadataChip>\n );\n}\n\nfunction CommitLabel({commit}: {commit: string}) {\n return (\n <MetadataChip icon=\"gitCommitLine\" title={`Commit ${commit}`}>\n {commit}\n </MetadataChip>\n );\n}\n\nfunction ActorLabel({actor}: {actor: string}) {\n return (\n <MetadataChip\n icon=\"userLine\"\n title={`Triggered by ${actor}`}\n // Dropped once the row is two lines, where the provenance line has to stay readable on\n // a phone.\n className=\"hidden max-w-[120px] @min-[976px]:flex\"\n >\n {actor}\n </MetadataChip>\n );\n}\n\n/**\n * A ref, SHA, or handle: monospace because it is content a user copies or pattern-matches,\n * with the icon carrying the kind so the value itself never needs a written label.\n */\nfunction MetadataChip({\n icon,\n title,\n className,\n children,\n}: {\n icon: IconName;\n title: string;\n className?: string | undefined;\n children: string;\n}) {\n return (\n <span className={cn('flex min-w-0 shrink-0 items-center gap-tight', className)} title={title}>\n <Icon name={icon} className=\"size-12 shrink-0 text-foreground-neutral-muted\" aria-hidden />\n <Code as=\"span\" variant=\"label\" className=\"min-w-0 truncate\">\n {children}\n </Code>\n </span>\n );\n}\n"],"names":["TriggerSourceIcon","Icon","Panel","RelativeTime","Tooltip","TooltipContent","TooltipTrigger","Code","Text","cn","Link","useWorkflowRunDurationAccessibleLabel","WorkflowRunDurationLabel","formatWorkflowRunNumberLabel","WorkflowRunNumberLabel","getWorkflowStatusVisual","WorkflowStatusIcon","workflowRunActor","workflowRunBranchLabel","workflowRunCommitLabel","withoutWorkflowRunSelectionSearch","JOB_STATUS_STRIP_WIDTH","JobStatusStrip","jobStatusSummary","WorkflowRunRowList","runs","workspaceSlug","projectSlug","className","ul","map","run","li","WorkflowRunRow","id","duration","runAttempt","displayDuration","hasStarted","jobs","hasStartedJobExecution","durationLabel","status","statusLabel","label","runNumberLabel","branch","commit","actor","body","size","div","span","variant","bold","name","number","triggerDisplayLabel","TriggerLabel","BranchLabel","isPullRequest","startsWith","CommitLabel","ActorLabel","style","minWidth","value","createdAt","rowClassName","isTemporary","to","params","workflowRunId","search","previous","aria-label","triggerLabel","undefined","total","filter","part","Boolean","join","asChild","provider","triggerProvider","source","triggerSource","aria-hidden","as","MetadataChip","icon","title","children"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run-summary.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-summary/workflow-run-summary.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAC;AAa/B,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,GAAG,EAAE,iBAAiB,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,aAAa,EACb,WAAW,EACX,GAAG,EACH,UAAkB,EAClB,QAAQ,EACR,YAAoB,EACpB,OAAO,EACP,aAAa,GACd,EAAE,uBAAuB,+BAoIzB"}
1
+ {"version":3,"file":"workflow-run-summary.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-summary/workflow-run-summary.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAC;AAa/B,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,GAAG,EAAE,iBAAiB,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,aAAa,EACb,WAAW,EACX,GAAG,EACH,UAAkB,EAClB,QAAQ,EACR,YAAoB,EACpB,OAAO,EACP,aAAa,GACd,EAAE,uBAAuB,+BAiIzB"}
@@ -16,7 +16,7 @@ import { WorkflowRunDurationLabel } from '../workflow-run-duration-label.js';
16
16
  import { getWorkflowStatusVisual } from '../workflow-status/status-visuals.js';
17
17
  import { WorkflowRunAttemptSwitcher } from './workflow-run-attempt-switcher.js';
18
18
  const STATUS_BADGE_LABEL_WIDTH_CH = Math.max(...WORKFLOW_RUN_STATUSES.map((status)=>getWorkflowStatusVisual(status).label.length));
19
- const RERUN_BUTTON_SURFACE_CLASS_NAME = 'bg-background-neutral-base hover:bg-background-neutral-hover active:bg-background-neutral-pressed';
19
+ const NEUTRAL_ACTION_SURFACE_CLASS_NAME = 'bg-background-neutral-base hover:bg-background-neutral-hover active:bg-background-neutral-pressed';
20
20
  export function WorkflowRunSummary({ workspaceSlug, projectSlug, run, cancelling = false, onCancel, rerunPending = false, onRerun, latestAttempt }) {
21
21
  const headingId = useId();
22
22
  const status = getWorkflowStatusVisual(run.runAttempt.status);
@@ -35,7 +35,7 @@ export function WorkflowRunSummary({ workspaceSlug, projectSlug, run, cancelling
35
35
  reducedMotionIntervalMs: 10_000,
36
36
  children: /*#__PURE__*/ _jsx("section", {
37
37
  "aria-labelledby": headingId,
38
- className: "bg-background-neutral-background px-row py-row",
38
+ className: "px-row py-row",
39
39
  children: /*#__PURE__*/ _jsxs("div", {
40
40
  className: "grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-cluster gap-y-inline overflow-hidden max-[480px]:grid-cols-1",
41
41
  children: [
@@ -195,7 +195,7 @@ function WorkflowRunActionSlot({ action, cancelling, onCancel, rerunPending, onR
195
195
  type: "button",
196
196
  variant: "secondary",
197
197
  size: "xs",
198
- className: RERUN_BUTTON_SURFACE_CLASS_NAME,
198
+ className: NEUTRAL_ACTION_SURFACE_CLASS_NAME,
199
199
  isLoading: rerunPending,
200
200
  disabled: rerunPending,
201
201
  onClick: ()=>onRerun('all'),
@@ -211,7 +211,7 @@ function WorkflowRunActionSlot({ action, cancelling, onCancel, rerunPending, onR
211
211
  type: "button",
212
212
  variant: "secondary",
213
213
  size: "xs",
214
- className: RERUN_BUTTON_SURFACE_CLASS_NAME,
214
+ className: NEUTRAL_ACTION_SURFACE_CLASS_NAME,
215
215
  iconRight: "arrowDownSLine",
216
216
  isLoading: rerunPending,
217
217
  disabled: rerunPending,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-summary/workflow-run-summary.tsx"],"sourcesContent":["import {TriggerSourceIcon} from '@shipfox/client-triggers';\nimport {MetadataSeparator} from '@shipfox/client-ui';\nimport {Badge} from '@shipfox/react-ui/badge';\nimport {Button} from '@shipfox/react-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {useIsTextTruncated} from '@shipfox/react-ui/hooks';\nimport {RelativeTime} from '@shipfox/react-ui/relative-time';\nimport {TimeTickerProvider} from '@shipfox/react-ui/time-ticker';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useId} from 'react';\nimport {WorkflowRunNumberLabel} from '#components/workflow-run-number-label.js';\nimport {\n isWorkflowRunTerminal,\n type Job,\n WORKFLOW_RUN_STATUSES,\n type WorkflowRunDetail,\n type WorkflowRunRerunMode,\n} from '#core/workflow-run.js';\nimport {WorkflowRunDurationLabel} from '../workflow-run-duration-label.js';\nimport {getWorkflowStatusVisual} from '../workflow-status/status-visuals.js';\nimport {WorkflowRunAttemptSwitcher} from './workflow-run-attempt-switcher.js';\n\nconst STATUS_BADGE_LABEL_WIDTH_CH = Math.max(\n ...WORKFLOW_RUN_STATUSES.map((status) => getWorkflowStatusVisual(status).label.length),\n);\nconst RERUN_BUTTON_SURFACE_CLASS_NAME =\n 'bg-background-neutral-base hover:bg-background-neutral-hover active:bg-background-neutral-pressed';\n\ntype WorkflowRunAction = 'cancel' | 'rerun-all' | 'rerun-menu' | 'none';\n\nexport interface WorkflowRunSummaryProps {\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n run: WorkflowRunDetail;\n cancelling?: boolean | undefined;\n onCancel?: (() => void) | undefined;\n rerunPending?: boolean | undefined;\n onRerun?: ((mode: WorkflowRunRerunMode) => void) | undefined;\n latestAttempt?: number | undefined;\n}\n\nexport function WorkflowRunSummary({\n workspaceSlug,\n projectSlug,\n run,\n cancelling = false,\n onCancel,\n rerunPending = false,\n onRerun,\n latestAttempt,\n}: WorkflowRunSummaryProps) {\n const headingId = useId();\n const status = getWorkflowStatusVisual(run.runAttempt.status);\n const action = workflowRunActionForRun(run);\n const hasAction = canRenderWorkflowRunAction(action, onCancel, onRerun);\n const attemptSwitcher =\n latestAttempt && latestAttempt > 1 && workspaceSlug && projectSlug\n ? {workspaceSlug, projectSlug, latestAttempt}\n : null;\n const displayDuration = run.runAttempt.displayDuration;\n const hasStarted = run.hasStartedJobExecution;\n const {ref: headingTextRef, isTruncated: isHeadingTruncated} =\n useIsTextTruncated<HTMLSpanElement>(run.name);\n\n return (\n <TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>\n <section\n aria-labelledby={headingId}\n className=\"bg-background-neutral-background px-row py-row\"\n >\n <div className=\"grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-cluster gap-y-inline overflow-hidden max-[480px]:grid-cols-1\">\n <div className=\"col-start-1 row-start-1 min-w-0 max-[480px]:col-start-auto max-[480px]:row-start-auto\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n <Badge variant={status.badge} size=\"xs\">\n <span className=\"text-center\" style={{width: `${STATUS_BADGE_LABEL_WIDTH_CH}ch`}}>\n {status.label}\n </span>\n </Badge>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <Header as=\"h1\" id={headingId} variant=\"h3\" className=\"min-w-0 truncate\">\n <span ref={headingTextRef} className=\"block min-w-0 truncate\">\n {run.name}\n </span>\n </Header>\n </TooltipTrigger>\n {isHeadingTruncated ? (\n <TooltipContent>\n <Text as=\"span\" size=\"xs\" className=\"max-w-[360px] break-words\">\n {run.name}\n </Text>\n </TooltipContent>\n ) : null}\n </Tooltip>\n </div>\n </div>\n\n {hasAction ? (\n <div className=\"col-start-2 row-start-1 flex min-w-max items-center gap-inline justify-self-end max-[480px]:col-start-auto max-[480px]:row-start-auto max-[480px]:justify-self-start\">\n <WorkflowRunActionSlot\n action={action}\n cancelling={cancelling}\n onCancel={onCancel}\n rerunPending={rerunPending}\n onRerun={onRerun}\n />\n </div>\n ) : null}\n\n <div className=\"col-span-2 row-start-2 flex min-w-0 items-center gap-cluster overflow-hidden text-foreground-neutral-subtle max-[480px]:col-span-1 max-[480px]:row-start-auto\">\n {run.number !== null ? (\n <>\n <WorkflowRunNumberLabel run={run} />\n {attemptSwitcher || run.triggerDisplayLabel ? <MetadataSeparator /> : null}\n </>\n ) : null}\n\n {attemptSwitcher ? (\n <WorkflowRunAttemptSwitcher\n workspaceSlug={attemptSwitcher.workspaceSlug}\n projectSlug={attemptSwitcher.projectSlug}\n run={run}\n latestAttempt={attemptSwitcher.latestAttempt}\n />\n ) : null}\n\n {run.triggerDisplayLabel ? (\n <>\n {attemptSwitcher ? <MetadataSeparator /> : null}\n <span className=\"min-w-0\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label={run.triggerLabel}\n className=\"inline-flex max-w-full min-w-0 cursor-help items-center gap-tight rounded-6 border-0 bg-transparent p-0 text-left text-foreground-neutral-subtle outline-none focus-visible:shadow-button-neutral-focus\"\n >\n <TriggerSourceIcon\n provider={run.triggerProvider}\n source={run.triggerSource}\n aria-hidden=\"true\"\n className=\"size-12 shrink-0\"\n />\n <Text as=\"span\" size=\"xs\" className=\"min-w-0 truncate\">\n {run.triggerDisplayLabel}\n </Text>\n </button>\n </TooltipTrigger>\n <TooltipContent>\n <Text as=\"span\" size=\"xs\" className=\"block max-w-[360px] break-words\">\n {run.triggerLabel}\n </Text>\n </TooltipContent>\n </Tooltip>\n </span>\n </>\n ) : null}\n\n {run.number !== null || attemptSwitcher || run.triggerDisplayLabel ? (\n <MetadataSeparator />\n ) : null}\n <RelativeTime\n value={run.runAttempt.createdAt}\n className=\"shrink-0 whitespace-nowrap text-xs leading-20 text-foreground-neutral-subtle\"\n />\n\n {displayDuration ? (\n <>\n <MetadataSeparator />\n <WorkflowRunDurationLabel\n duration={displayDuration}\n hasStarted={hasStarted}\n className=\"text-foreground-neutral-subtle\"\n />\n </>\n ) : null}\n </div>\n </div>\n </section>\n </TimeTickerProvider>\n );\n}\n\nfunction WorkflowRunActionSlot({\n action,\n cancelling,\n onCancel,\n rerunPending,\n onRerun,\n}: {\n action: WorkflowRunAction;\n cancelling: boolean;\n onCancel?: (() => void) | undefined;\n rerunPending: boolean;\n onRerun?: ((mode: WorkflowRunRerunMode) => void) | undefined;\n}) {\n if (action === 'none') return null;\n\n if (action === 'cancel') {\n if (!onCancel) return null;\n\n return (\n <Button\n type=\"button\"\n variant=\"danger\"\n size=\"xs\"\n isLoading={cancelling}\n disabled={cancelling}\n onClick={onCancel}\n >\n Cancel workflow\n </Button>\n );\n }\n\n if (action === 'rerun-all') {\n if (!onRerun) return null;\n\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"xs\"\n className={RERUN_BUTTON_SURFACE_CLASS_NAME}\n isLoading={rerunPending}\n disabled={rerunPending}\n onClick={() => onRerun('all')}\n >\n Re-run workflow\n </Button>\n );\n }\n\n if (!onRerun) return null;\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"xs\"\n className={RERUN_BUTTON_SURFACE_CLASS_NAME}\n iconRight=\"arrowDownSLine\"\n isLoading={rerunPending}\n disabled={rerunPending}\n >\n Re-run jobs\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={rerunPending} onSelect={() => onRerun('all')}>\n Re-run all jobs\n </DropdownMenuItem>\n <DropdownMenuItem disabled={rerunPending} onSelect={() => onRerun('failed')}>\n Re-run failed jobs\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction workflowRunActionForRun(run: WorkflowRunDetail): WorkflowRunAction {\n if (run.runAttempt.attempt !== run.currentAttempt) return 'none';\n if (!isWorkflowRunTerminal(run.runAttempt.status)) return 'cancel';\n if (run.runAttempt.status === 'succeeded' || !hasFailedOrCancelledJobs(run)) return 'rerun-all';\n return 'rerun-menu';\n}\n\nfunction canRenderWorkflowRunAction(\n action: WorkflowRunAction,\n onCancel: (() => void) | undefined,\n onRerun: ((mode: WorkflowRunRerunMode) => void) | undefined,\n): boolean {\n if (action === 'cancel') return onCancel !== undefined;\n if (action === 'rerun-all' || action === 'rerun-menu') return onRerun !== undefined;\n return false;\n}\n\nfunction hasFailedOrCancelledJobs(run: WorkflowRunDetail): boolean {\n if (!workflowRunHasJobs(run)) return false;\n\n return run.jobs.some((job) => job.status === 'failed' || job.status === 'cancelled');\n}\n\nfunction workflowRunHasJobs(run: WorkflowRunDetail): run is WorkflowRunDetail & {jobs: Job[]} {\n return 'jobs' in run && Array.isArray(run.jobs);\n}\n"],"names":["TriggerSourceIcon","MetadataSeparator","Badge","Button","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuTrigger","useIsTextTruncated","RelativeTime","TimeTickerProvider","Tooltip","TooltipContent","TooltipTrigger","Header","Text","useId","WorkflowRunNumberLabel","isWorkflowRunTerminal","WORKFLOW_RUN_STATUSES","WorkflowRunDurationLabel","getWorkflowStatusVisual","WorkflowRunAttemptSwitcher","STATUS_BADGE_LABEL_WIDTH_CH","Math","max","map","status","label","length","RERUN_BUTTON_SURFACE_CLASS_NAME","WorkflowRunSummary","workspaceSlug","projectSlug","run","cancelling","onCancel","rerunPending","onRerun","latestAttempt","headingId","runAttempt","action","workflowRunActionForRun","hasAction","canRenderWorkflowRunAction","attemptSwitcher","displayDuration","hasStarted","hasStartedJobExecution","ref","headingTextRef","isTruncated","isHeadingTruncated","name","intervalMs","reducedMotionIntervalMs","section","aria-labelledby","className","div","variant","badge","size","span","style","width","asChild","as","id","WorkflowRunActionSlot","number","triggerDisplayLabel","button","type","aria-label","triggerLabel","provider","triggerProvider","source","triggerSource","aria-hidden","value","createdAt","duration","isLoading","disabled","onClick","iconRight","align","onSelect","attempt","currentAttempt","hasFailedOrCancelledJobs","undefined","workflowRunHasJobs","jobs","some","job","Array","isArray"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-summary/workflow-run-summary.tsx"],"sourcesContent":["import {TriggerSourceIcon} from '@shipfox/client-triggers';\nimport {MetadataSeparator} from '@shipfox/client-ui';\nimport {Badge} from '@shipfox/react-ui/badge';\nimport {Button} from '@shipfox/react-ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {useIsTextTruncated} from '@shipfox/react-ui/hooks';\nimport {RelativeTime} from '@shipfox/react-ui/relative-time';\nimport {TimeTickerProvider} from '@shipfox/react-ui/time-ticker';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useId} from 'react';\nimport {WorkflowRunNumberLabel} from '#components/workflow-run-number-label.js';\nimport {\n isWorkflowRunTerminal,\n type Job,\n WORKFLOW_RUN_STATUSES,\n type WorkflowRunDetail,\n type WorkflowRunRerunMode,\n} from '#core/workflow-run.js';\nimport {WorkflowRunDurationLabel} from '../workflow-run-duration-label.js';\nimport {getWorkflowStatusVisual} from '../workflow-status/status-visuals.js';\nimport {WorkflowRunAttemptSwitcher} from './workflow-run-attempt-switcher.js';\n\nconst STATUS_BADGE_LABEL_WIDTH_CH = Math.max(\n ...WORKFLOW_RUN_STATUSES.map((status) => getWorkflowStatusVisual(status).label.length),\n);\nconst NEUTRAL_ACTION_SURFACE_CLASS_NAME =\n 'bg-background-neutral-base hover:bg-background-neutral-hover active:bg-background-neutral-pressed';\n\ntype WorkflowRunAction = 'cancel' | 'rerun-all' | 'rerun-menu' | 'none';\n\nexport interface WorkflowRunSummaryProps {\n workspaceSlug?: string | undefined;\n projectSlug?: string | undefined;\n run: WorkflowRunDetail;\n cancelling?: boolean | undefined;\n onCancel?: (() => void) | undefined;\n rerunPending?: boolean | undefined;\n onRerun?: ((mode: WorkflowRunRerunMode) => void) | undefined;\n latestAttempt?: number | undefined;\n}\n\nexport function WorkflowRunSummary({\n workspaceSlug,\n projectSlug,\n run,\n cancelling = false,\n onCancel,\n rerunPending = false,\n onRerun,\n latestAttempt,\n}: WorkflowRunSummaryProps) {\n const headingId = useId();\n const status = getWorkflowStatusVisual(run.runAttempt.status);\n const action = workflowRunActionForRun(run);\n const hasAction = canRenderWorkflowRunAction(action, onCancel, onRerun);\n const attemptSwitcher =\n latestAttempt && latestAttempt > 1 && workspaceSlug && projectSlug\n ? {workspaceSlug, projectSlug, latestAttempt}\n : null;\n const displayDuration = run.runAttempt.displayDuration;\n const hasStarted = run.hasStartedJobExecution;\n const {ref: headingTextRef, isTruncated: isHeadingTruncated} =\n useIsTextTruncated<HTMLSpanElement>(run.name);\n\n return (\n <TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>\n <section aria-labelledby={headingId} className=\"px-row py-row\">\n <div className=\"grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-cluster gap-y-inline overflow-hidden max-[480px]:grid-cols-1\">\n <div className=\"col-start-1 row-start-1 min-w-0 max-[480px]:col-start-auto max-[480px]:row-start-auto\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n <Badge variant={status.badge} size=\"xs\">\n <span className=\"text-center\" style={{width: `${STATUS_BADGE_LABEL_WIDTH_CH}ch`}}>\n {status.label}\n </span>\n </Badge>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <Header as=\"h1\" id={headingId} variant=\"h3\" className=\"min-w-0 truncate\">\n <span ref={headingTextRef} className=\"block min-w-0 truncate\">\n {run.name}\n </span>\n </Header>\n </TooltipTrigger>\n {isHeadingTruncated ? (\n <TooltipContent>\n <Text as=\"span\" size=\"xs\" className=\"max-w-[360px] break-words\">\n {run.name}\n </Text>\n </TooltipContent>\n ) : null}\n </Tooltip>\n </div>\n </div>\n\n {hasAction ? (\n <div className=\"col-start-2 row-start-1 flex min-w-max items-center gap-inline justify-self-end max-[480px]:col-start-auto max-[480px]:row-start-auto max-[480px]:justify-self-start\">\n <WorkflowRunActionSlot\n action={action}\n cancelling={cancelling}\n onCancel={onCancel}\n rerunPending={rerunPending}\n onRerun={onRerun}\n />\n </div>\n ) : null}\n\n <div className=\"col-span-2 row-start-2 flex min-w-0 items-center gap-cluster overflow-hidden text-foreground-neutral-subtle max-[480px]:col-span-1 max-[480px]:row-start-auto\">\n {run.number !== null ? (\n <>\n <WorkflowRunNumberLabel run={run} />\n {attemptSwitcher || run.triggerDisplayLabel ? <MetadataSeparator /> : null}\n </>\n ) : null}\n\n {attemptSwitcher ? (\n <WorkflowRunAttemptSwitcher\n workspaceSlug={attemptSwitcher.workspaceSlug}\n projectSlug={attemptSwitcher.projectSlug}\n run={run}\n latestAttempt={attemptSwitcher.latestAttempt}\n />\n ) : null}\n\n {run.triggerDisplayLabel ? (\n <>\n {attemptSwitcher ? <MetadataSeparator /> : null}\n <span className=\"min-w-0\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label={run.triggerLabel}\n className=\"inline-flex max-w-full min-w-0 cursor-help items-center gap-tight rounded-6 border-0 bg-transparent p-0 text-left text-foreground-neutral-subtle outline-none focus-visible:shadow-button-neutral-focus\"\n >\n <TriggerSourceIcon\n provider={run.triggerProvider}\n source={run.triggerSource}\n aria-hidden=\"true\"\n className=\"size-12 shrink-0\"\n />\n <Text as=\"span\" size=\"xs\" className=\"min-w-0 truncate\">\n {run.triggerDisplayLabel}\n </Text>\n </button>\n </TooltipTrigger>\n <TooltipContent>\n <Text as=\"span\" size=\"xs\" className=\"block max-w-[360px] break-words\">\n {run.triggerLabel}\n </Text>\n </TooltipContent>\n </Tooltip>\n </span>\n </>\n ) : null}\n\n {run.number !== null || attemptSwitcher || run.triggerDisplayLabel ? (\n <MetadataSeparator />\n ) : null}\n <RelativeTime\n value={run.runAttempt.createdAt}\n className=\"shrink-0 whitespace-nowrap text-xs leading-20 text-foreground-neutral-subtle\"\n />\n\n {displayDuration ? (\n <>\n <MetadataSeparator />\n <WorkflowRunDurationLabel\n duration={displayDuration}\n hasStarted={hasStarted}\n className=\"text-foreground-neutral-subtle\"\n />\n </>\n ) : null}\n </div>\n </div>\n </section>\n </TimeTickerProvider>\n );\n}\n\nfunction WorkflowRunActionSlot({\n action,\n cancelling,\n onCancel,\n rerunPending,\n onRerun,\n}: {\n action: WorkflowRunAction;\n cancelling: boolean;\n onCancel?: (() => void) | undefined;\n rerunPending: boolean;\n onRerun?: ((mode: WorkflowRunRerunMode) => void) | undefined;\n}) {\n if (action === 'none') return null;\n\n if (action === 'cancel') {\n if (!onCancel) return null;\n\n return (\n <Button\n type=\"button\"\n variant=\"danger\"\n size=\"xs\"\n isLoading={cancelling}\n disabled={cancelling}\n onClick={onCancel}\n >\n Cancel workflow\n </Button>\n );\n }\n\n if (action === 'rerun-all') {\n if (!onRerun) return null;\n\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"xs\"\n className={NEUTRAL_ACTION_SURFACE_CLASS_NAME}\n isLoading={rerunPending}\n disabled={rerunPending}\n onClick={() => onRerun('all')}\n >\n Re-run workflow\n </Button>\n );\n }\n\n if (!onRerun) return null;\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"xs\"\n className={NEUTRAL_ACTION_SURFACE_CLASS_NAME}\n iconRight=\"arrowDownSLine\"\n isLoading={rerunPending}\n disabled={rerunPending}\n >\n Re-run jobs\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={rerunPending} onSelect={() => onRerun('all')}>\n Re-run all jobs\n </DropdownMenuItem>\n <DropdownMenuItem disabled={rerunPending} onSelect={() => onRerun('failed')}>\n Re-run failed jobs\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction workflowRunActionForRun(run: WorkflowRunDetail): WorkflowRunAction {\n if (run.runAttempt.attempt !== run.currentAttempt) return 'none';\n if (!isWorkflowRunTerminal(run.runAttempt.status)) return 'cancel';\n if (run.runAttempt.status === 'succeeded' || !hasFailedOrCancelledJobs(run)) return 'rerun-all';\n return 'rerun-menu';\n}\n\nfunction canRenderWorkflowRunAction(\n action: WorkflowRunAction,\n onCancel: (() => void) | undefined,\n onRerun: ((mode: WorkflowRunRerunMode) => void) | undefined,\n): boolean {\n if (action === 'cancel') return onCancel !== undefined;\n if (action === 'rerun-all' || action === 'rerun-menu') return onRerun !== undefined;\n return false;\n}\n\nfunction hasFailedOrCancelledJobs(run: WorkflowRunDetail): boolean {\n if (!workflowRunHasJobs(run)) return false;\n\n return run.jobs.some((job) => job.status === 'failed' || job.status === 'cancelled');\n}\n\nfunction workflowRunHasJobs(run: WorkflowRunDetail): run is WorkflowRunDetail & {jobs: Job[]} {\n return 'jobs' in run && Array.isArray(run.jobs);\n}\n"],"names":["TriggerSourceIcon","MetadataSeparator","Badge","Button","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuTrigger","useIsTextTruncated","RelativeTime","TimeTickerProvider","Tooltip","TooltipContent","TooltipTrigger","Header","Text","useId","WorkflowRunNumberLabel","isWorkflowRunTerminal","WORKFLOW_RUN_STATUSES","WorkflowRunDurationLabel","getWorkflowStatusVisual","WorkflowRunAttemptSwitcher","STATUS_BADGE_LABEL_WIDTH_CH","Math","max","map","status","label","length","NEUTRAL_ACTION_SURFACE_CLASS_NAME","WorkflowRunSummary","workspaceSlug","projectSlug","run","cancelling","onCancel","rerunPending","onRerun","latestAttempt","headingId","runAttempt","action","workflowRunActionForRun","hasAction","canRenderWorkflowRunAction","attemptSwitcher","displayDuration","hasStarted","hasStartedJobExecution","ref","headingTextRef","isTruncated","isHeadingTruncated","name","intervalMs","reducedMotionIntervalMs","section","aria-labelledby","className","div","variant","badge","size","span","style","width","asChild","as","id","WorkflowRunActionSlot","number","triggerDisplayLabel","button","type","aria-label","triggerLabel","provider","triggerProvider","source","triggerSource","aria-hidden","value","createdAt","duration","isLoading","disabled","onClick","iconRight","align","onSelect","attempt","currentAttempt","hasFailedOrCancelledJobs","undefined","workflowRunHasJobs","jobs","some","job","Array","isArray"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-workspace-nav.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/run-workspace-nav.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAG3B,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,iBAAiB,CAAC;IACvB,aAAa,EAAE,mBAAmB,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1C,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,aAAa,EACb,WAAW,EACX,GAAG,EACH,aAAa,EACb,YAAY,EACZ,SAAc,EACd,iBAAiB,GAClB,EAAE,oBAAoB,+BA8DtB"}
1
+ {"version":3,"file":"run-workspace-nav.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/run-workspace-nav.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAG3B,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAK3D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,iBAAiB,CAAC;IACvB,aAAa,EAAE,mBAAmB,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1C,iBAAiB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,aAAa,EACb,WAAW,EACX,GAAG,EACH,aAAa,EACb,YAAY,EACZ,SAAc,EACd,iBAAiB,GAClB,EAAE,oBAAoB,+BAgEtB"}
@@ -10,6 +10,7 @@ import { WorkflowStatusIcon } from '#components/workflow-status/workflow-status-
10
10
  import { defaultJobExecution, deriveJobDisplayStatus } from '#core/workflow-run.js';
11
11
  import { workflowJobSearchParams, workflowRunSearchParams } from '#routes/inputs.js';
12
12
  import { JobExecutionTimeText } from '../job-detail/job-execution-time-text.js';
13
+ const RUN_WORKSPACE_LINK_CLASS_NAME = 'relative flex min-h-32 items-center gap-inline rounded-4 px-tight outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44';
13
14
  /**
14
15
  * The stable navigation model shared by run-level and job-level routes. The graph explains
15
16
  * topology; this compact index makes moving between dedicated job pages predictable.
@@ -20,13 +21,14 @@ import { JobExecutionTimeText } from '../job-detail/job-execution-time-text.js';
20
21
  run.jobs
21
22
  ]);
22
23
  const [mobileOpen, setMobileOpen] = useState(false);
23
- const currentJob = jobs.find((job)=>job.id === currentJobId);
24
+ const currentJob = jobs.find((job)=>job.id === currentJobId) ?? (currentJobId ? jobs[0] : undefined);
25
+ const resolvedCurrentJobId = currentJob?.id;
24
26
  const currentLabel = currentJob?.displayName ?? sectionLabel(activeSection);
25
27
  return /*#__PURE__*/ _jsx(TimeTickerProvider, {
26
28
  intervalMs: 1000,
27
29
  reducedMotionIntervalMs: 10_000,
28
30
  children: /*#__PURE__*/ _jsx("aside", {
29
- className: "flex min-h-0 w-full shrink-0 flex-col border-b border-border-neutral-base bg-background-neutral-background min-[768px]:w-240 min-[768px]:border-b-0 min-[768px]:border-r",
31
+ className: "flex min-h-0 w-full shrink-0 flex-col border-b border-border-neutral-base min-[768px]:w-240 min-[768px]:border-b-0",
30
32
  children: /*#__PURE__*/ _jsxs(Collapsible, {
31
33
  open: mobileOpen,
32
34
  onOpenChange: setMobileOpen,
@@ -71,7 +73,7 @@ import { JobExecutionTimeText } from '../job-detail/job-execution-time-text.js';
71
73
  run: run,
72
74
  jobs: jobs,
73
75
  activeSection: activeSection,
74
- currentJobId: currentJobId,
76
+ currentJobId: resolvedCurrentJobId,
75
77
  jobSearch: jobSearch,
76
78
  annotationSummary: annotationSummary,
77
79
  mobileOpen: mobileOpen,
@@ -106,9 +108,10 @@ function RunWorkspaceNavContent({ workspaceSlug, projectSlug, run, jobs, activeS
106
108
  ]);
107
109
  return /*#__PURE__*/ _jsxs("nav", {
108
110
  "aria-label": "Run workspace",
109
- className: "flex min-h-0 min-w-0 flex-1 flex-col gap-group",
111
+ className: "flex min-h-0 min-w-0 flex-1 flex-col",
110
112
  children: [
111
113
  /*#__PURE__*/ _jsx("ul", {
114
+ className: "border-b border-border-neutral-base pb-row",
112
115
  children: /*#__PURE__*/ _jsx("li", {
113
116
  children: /*#__PURE__*/ _jsx(RunSectionLink, {
114
117
  workspaceSlug: workspaceSlug,
@@ -123,7 +126,7 @@ function RunWorkspaceNavContent({ workspaceSlug, projectSlug, run, jobs, activeS
123
126
  }),
124
127
  /*#__PURE__*/ _jsxs("section", {
125
128
  "aria-labelledby": "run-workspace-jobs-heading",
126
- className: "flex min-h-0 min-w-0 flex-1 flex-col",
129
+ className: "flex min-h-0 min-w-0 flex-1 flex-col border-b border-border-neutral-base py-row",
127
130
  children: [
128
131
  /*#__PURE__*/ _jsxs("div", {
129
132
  className: "flex items-center justify-between gap-inline px-tight pb-[6px]",
@@ -165,8 +168,9 @@ function RunWorkspaceNavContent({ workspaceSlug, projectSlug, run, jobs, activeS
165
168
  }),
166
169
  onClick: onNavigate,
167
170
  "aria-current": current ? 'page' : undefined,
168
- className: cn('flex min-h-32 min-w-0 items-center gap-inline rounded-4 px-tight text-left outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44', current && 'bg-background-neutral-hover'),
171
+ className: cn(RUN_WORKSPACE_LINK_CLASS_NAME, 'min-w-0 text-left', current && 'bg-background-neutral-hover'),
169
172
  children: [
173
+ current ? /*#__PURE__*/ _jsx(RunWorkspaceActiveBar, {}) : null,
170
174
  /*#__PURE__*/ _jsx(WorkflowStatusIcon, {
171
175
  status: deriveJobDisplayStatus(job),
172
176
  size: 12,
@@ -191,6 +195,7 @@ function RunWorkspaceNavContent({ workspaceSlug, projectSlug, run, jobs, activeS
191
195
  }),
192
196
  /*#__PURE__*/ _jsxs("section", {
193
197
  "aria-labelledby": "run-workspace-details-heading",
198
+ className: "pt-row",
194
199
  children: [
195
200
  /*#__PURE__*/ _jsx(Text, {
196
201
  as: "h2",
@@ -252,8 +257,9 @@ function RunSectionLink({ workspaceSlug, projectSlug, runId, runAttempt, section
252
257
  onClick: onNavigate,
253
258
  "aria-current": current ? 'page' : undefined,
254
259
  "aria-label": count ? `${sectionLabel(section)}, ${countTruncated ? `${count} or more` : count}` : undefined,
255
- className: cn('flex min-h-32 items-center gap-inline rounded-4 px-tight text-xs font-medium text-foreground-neutral-base outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44', current && 'bg-background-neutral-hover'),
260
+ className: cn(RUN_WORKSPACE_LINK_CLASS_NAME, 'text-xs font-medium text-foreground-neutral-base', current && 'bg-background-neutral-hover'),
256
261
  children: [
262
+ current ? /*#__PURE__*/ _jsx(RunWorkspaceActiveBar, {}) : null,
257
263
  sectionLabel(section),
258
264
  count ? /*#__PURE__*/ _jsxs("span", {
259
265
  "aria-hidden": "true",
@@ -266,6 +272,13 @@ function RunSectionLink({ workspaceSlug, projectSlug, runId, runAttempt, section
266
272
  ]
267
273
  });
268
274
  }
275
+ function RunWorkspaceActiveBar() {
276
+ return /*#__PURE__*/ _jsx("span", {
277
+ "aria-hidden": "true",
278
+ "data-run-workspace-active-bar": true,
279
+ className: "absolute inset-y-0 left-0 w-2 rounded-l-4 bg-border-highlights-interactive"
280
+ });
281
+ }
269
282
  function sectionLabel(section) {
270
283
  if (section === 'annotations') return 'Annotations';
271
284
  if (section === 'source') return 'Source';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-view/run-workspace-nav.tsx"],"sourcesContent":["import {Collapsible, CollapsibleTrigger} from '@shipfox/react-ui/collapsible';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {TimeTickerProvider} from '@shipfox/react-ui/time-ticker';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport type {RunAnnotationSummary} from '#core/run-annotation.js';\nimport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n type Job,\n type WorkflowRunDetail,\n} from '#core/workflow-run.js';\nimport {\n type WorkflowJobSearch,\n type WorkflowRunTab,\n workflowJobSearchParams,\n workflowRunSearchParams,\n} from '#routes/inputs.js';\nimport {JobExecutionTimeText} from '../job-detail/job-execution-time-text.js';\n\ntype RunWorkspaceSection = Exclude<WorkflowRunTab, 'jobs'>;\n\nexport interface RunWorkspaceNavProps {\n workspaceSlug: string;\n projectSlug: string;\n run: WorkflowRunDetail;\n activeSection: RunWorkspaceSection;\n currentJobId?: string | undefined;\n jobSearch?: WorkflowJobSearch | undefined;\n annotationSummary?: RunAnnotationSummary | undefined;\n}\n\n/**\n * The stable navigation model shared by run-level and job-level routes. The graph explains\n * topology; this compact index makes moving between dedicated job pages predictable.\n */\nexport function RunWorkspaceNav({\n workspaceSlug,\n projectSlug,\n run,\n activeSection,\n currentJobId,\n jobSearch = {},\n annotationSummary,\n}: RunWorkspaceNavProps) {\n const jobs = useMemo(() => [...run.jobs].sort(compareJobs), [run.jobs]);\n const [mobileOpen, setMobileOpen] = useState(false);\n const currentJob = jobs.find((job) => job.id === currentJobId);\n const currentLabel = currentJob?.displayName ?? sectionLabel(activeSection);\n\n return (\n <TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>\n <aside className=\"flex min-h-0 w-full shrink-0 flex-col border-b border-border-neutral-base bg-background-neutral-background min-[768px]:w-240 min-[768px]:border-b-0 min-[768px]:border-r\">\n <Collapsible\n open={mobileOpen}\n onOpenChange={setMobileOpen}\n className=\"flex min-h-0 flex-col min-[768px]:flex-1\"\n >\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n className=\"flex min-h-44 w-full items-center justify-between gap-cluster px-row text-left outline-none focus-visible:shadow-border-interactive-with-active min-[768px]:hidden\"\n aria-label=\"Toggle run navigation\"\n >\n <span className=\"min-w-0\">\n <Text as=\"span\" size=\"xs\" className=\"block text-foreground-neutral-muted\">\n Run navigation\n </Text>\n <span className=\"block truncate font-code text-xs leading-20 text-foreground-neutral-base\">\n {currentLabel}\n </span>\n </span>\n <Icon\n name=\"chevronDown\"\n size={14}\n aria-hidden=\"true\"\n className={cn(\n 'shrink-0 text-foreground-neutral-muted transition-transform',\n mobileOpen && 'rotate-180',\n )}\n />\n </button>\n </CollapsibleTrigger>\n <div\n className={cn(\n 'flex min-h-0 max-h-[50vh] flex-col overflow-y-auto p-tight scrollbar min-[768px]:min-h-0 min-[768px]:max-h-none min-[768px]:flex-1 min-[768px]:flex min-[768px]:overflow-hidden min-[768px]:p-[12px]',\n !mobileOpen && 'hidden',\n )}\n >\n <RunWorkspaceNavContent\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n run={run}\n jobs={jobs}\n activeSection={activeSection}\n currentJobId={currentJobId}\n jobSearch={jobSearch}\n annotationSummary={annotationSummary}\n mobileOpen={mobileOpen}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </Collapsible>\n </aside>\n </TimeTickerProvider>\n );\n}\n\nfunction RunWorkspaceNavContent({\n workspaceSlug,\n projectSlug,\n run,\n jobs,\n activeSection,\n currentJobId,\n jobSearch,\n annotationSummary,\n mobileOpen,\n onNavigate,\n}: RunWorkspaceNavProps & {\n jobs: Job[];\n jobSearch: WorkflowJobSearch;\n mobileOpen: boolean;\n onNavigate: () => void;\n}) {\n const currentRowRef = useRef<HTMLAnchorElement>(null);\n const runAttempt = jobSearch.runAttempt ?? run.runAttempt.attempt;\n\n useEffect(() => {\n if (!currentJobId || mobileOpen) return;\n currentRowRef.current?.scrollIntoView({block: 'nearest'});\n }, [currentJobId, mobileOpen]);\n\n useEffect(() => {\n if (!currentJobId || !mobileOpen) return;\n currentRowRef.current?.scrollIntoView({block: 'nearest'});\n }, [currentJobId, mobileOpen]);\n\n return (\n <nav aria-label=\"Run workspace\" className=\"flex min-h-0 min-w-0 flex-1 flex-col gap-group\">\n <ul>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"summary\"\n current={!currentJobId && activeSection === 'summary'}\n onNavigate={onNavigate}\n />\n </li>\n </ul>\n\n <section\n aria-labelledby=\"run-workspace-jobs-heading\"\n className=\"flex min-h-0 min-w-0 flex-1 flex-col\"\n >\n <div className=\"flex items-center justify-between gap-inline px-tight pb-[6px]\">\n <Text\n as=\"h2\"\n id=\"run-workspace-jobs-heading\"\n size=\"xs\"\n bold\n className=\"text-foreground-neutral-muted\"\n >\n Jobs\n </Text>\n <Text as=\"span\" size=\"xs\" className=\"font-code text-foreground-neutral-subtle\">\n {jobs.length}\n </Text>\n </div>\n <ol className=\"min-h-0 flex-1 overflow-y-auto scrollbar\">\n {jobs.map((job) => {\n const current = job.id === currentJobId;\n const execution = defaultJobExecution(job);\n const duration = execution?.displayDuration ?? job.displayDuration;\n\n return (\n <li key={job.id}>\n <Link\n ref={current ? currentRowRef : undefined}\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId\"\n params={{workspaceSlug, projectSlug, workflowRunId: run.id, jobId: job.id}}\n search={workflowJobSearchParams({runAttempt}) as never}\n onClick={onNavigate}\n aria-current={current ? 'page' : undefined}\n className={cn(\n 'flex min-h-32 min-w-0 items-center gap-inline rounded-4 px-tight text-left outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44',\n current && 'bg-background-neutral-hover',\n )}\n >\n <WorkflowStatusIcon\n status={deriveJobDisplayStatus(job)}\n size={12}\n tooltip={false}\n />\n <span className=\"min-w-0 truncate font-code text-xs leading-20 text-foreground-neutral-base\">\n {job.displayName}\n </span>\n <span className=\"ml-auto shrink-0 font-code text-xs leading-20 text-foreground-neutral-muted tabular-nums\">\n {duration ? <JobExecutionTimeText time={duration} /> : '—'}\n </span>\n </Link>\n </li>\n );\n })}\n </ol>\n </section>\n\n <section aria-labelledby=\"run-workspace-details-heading\">\n <Text\n as=\"h2\"\n id=\"run-workspace-details-heading\"\n size=\"xs\"\n bold\n className=\"px-tight pb-[6px] text-foreground-neutral-muted\"\n >\n Run details\n </Text>\n <ul>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"annotations\"\n current={!currentJobId && activeSection === 'annotations'}\n count={annotationSummary?.total}\n countTruncated={annotationSummary?.truncated}\n onNavigate={onNavigate}\n />\n </li>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"source\"\n current={!currentJobId && activeSection === 'source'}\n onNavigate={onNavigate}\n />\n </li>\n </ul>\n </section>\n </nav>\n );\n}\n\nfunction RunSectionLink({\n workspaceSlug,\n projectSlug,\n runId,\n runAttempt,\n section,\n current,\n count,\n countTruncated = false,\n onNavigate,\n}: {\n workspaceSlug: string;\n projectSlug: string;\n runId: string;\n runAttempt: number;\n section: RunWorkspaceSection;\n current: boolean;\n count?: number | undefined;\n /** The read hit its page budget, so the count is a lower bound and renders as `N+`. */\n countTruncated?: boolean | undefined;\n onNavigate?: (() => void) | undefined;\n}) {\n return (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId: runId}}\n search={\n workflowRunSearchParams(\n {runAttempt, ...(section === 'summary' ? {} : {tab: section})},\n {runAttempt},\n ) as never\n }\n onClick={onNavigate}\n aria-current={current ? 'page' : undefined}\n aria-label={\n count\n ? `${sectionLabel(section)}, ${countTruncated ? `${count} or more` : count}`\n : undefined\n }\n className={cn(\n 'flex min-h-32 items-center gap-inline rounded-4 px-tight text-xs font-medium text-foreground-neutral-base outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44',\n current && 'bg-background-neutral-hover',\n )}\n >\n {sectionLabel(section)}\n {count ? (\n <span\n aria-hidden=\"true\"\n className=\"ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums\"\n >\n {count}\n {countTruncated ? '+' : ''}\n </span>\n ) : null}\n </Link>\n );\n}\n\nfunction sectionLabel(section: RunWorkspaceSection): string {\n if (section === 'annotations') return 'Annotations';\n if (section === 'source') return 'Source';\n return 'Summary';\n}\n\nfunction compareJobs(left: Job, right: Job): number {\n return left.position - right.position || left.id.localeCompare(right.id);\n}\n"],"names":["Collapsible","CollapsibleTrigger","Icon","TimeTickerProvider","Text","cn","Link","useEffect","useMemo","useRef","useState","WorkflowStatusIcon","defaultJobExecution","deriveJobDisplayStatus","workflowJobSearchParams","workflowRunSearchParams","JobExecutionTimeText","RunWorkspaceNav","workspaceSlug","projectSlug","run","activeSection","currentJobId","jobSearch","annotationSummary","jobs","sort","compareJobs","mobileOpen","setMobileOpen","currentJob","find","job","id","currentLabel","displayName","sectionLabel","intervalMs","reducedMotionIntervalMs","aside","className","open","onOpenChange","asChild","button","type","aria-label","span","as","size","name","aria-hidden","div","RunWorkspaceNavContent","onNavigate","currentRowRef","runAttempt","attempt","current","scrollIntoView","block","nav","ul","li","RunSectionLink","runId","section","aria-labelledby","bold","length","ol","map","execution","duration","displayDuration","ref","undefined","to","params","workflowRunId","jobId","search","onClick","aria-current","status","tooltip","time","count","total","countTruncated","truncated","tab","left","right","position","localeCompare"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-view/run-workspace-nav.tsx"],"sourcesContent":["import {Collapsible, CollapsibleTrigger} from '@shipfox/react-ui/collapsible';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {TimeTickerProvider} from '@shipfox/react-ui/time-ticker';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport type {RunAnnotationSummary} from '#core/run-annotation.js';\nimport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n type Job,\n type WorkflowRunDetail,\n} from '#core/workflow-run.js';\nimport {\n type WorkflowJobSearch,\n type WorkflowRunTab,\n workflowJobSearchParams,\n workflowRunSearchParams,\n} from '#routes/inputs.js';\nimport {JobExecutionTimeText} from '../job-detail/job-execution-time-text.js';\n\ntype RunWorkspaceSection = Exclude<WorkflowRunTab, 'jobs'>;\n\nconst RUN_WORKSPACE_LINK_CLASS_NAME =\n 'relative flex min-h-32 items-center gap-inline rounded-4 px-tight outline-none transition-colors hover:bg-background-neutral-hover focus-visible:shadow-border-interactive-with-active @max-[767px]:min-h-44 [@media(pointer:coarse)]:min-h-44';\n\nexport interface RunWorkspaceNavProps {\n workspaceSlug: string;\n projectSlug: string;\n run: WorkflowRunDetail;\n activeSection: RunWorkspaceSection;\n currentJobId?: string | undefined;\n jobSearch?: WorkflowJobSearch | undefined;\n annotationSummary?: RunAnnotationSummary | undefined;\n}\n\n/**\n * The stable navigation model shared by run-level and job-level routes. The graph explains\n * topology; this compact index makes moving between dedicated job pages predictable.\n */\nexport function RunWorkspaceNav({\n workspaceSlug,\n projectSlug,\n run,\n activeSection,\n currentJobId,\n jobSearch = {},\n annotationSummary,\n}: RunWorkspaceNavProps) {\n const jobs = useMemo(() => [...run.jobs].sort(compareJobs), [run.jobs]);\n const [mobileOpen, setMobileOpen] = useState(false);\n const currentJob =\n jobs.find((job) => job.id === currentJobId) ?? (currentJobId ? jobs[0] : undefined);\n const resolvedCurrentJobId = currentJob?.id;\n const currentLabel = currentJob?.displayName ?? sectionLabel(activeSection);\n\n return (\n <TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>\n <aside className=\"flex min-h-0 w-full shrink-0 flex-col border-b border-border-neutral-base min-[768px]:w-240 min-[768px]:border-b-0\">\n <Collapsible\n open={mobileOpen}\n onOpenChange={setMobileOpen}\n className=\"flex min-h-0 flex-col min-[768px]:flex-1\"\n >\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n className=\"flex min-h-44 w-full items-center justify-between gap-cluster px-row text-left outline-none focus-visible:shadow-border-interactive-with-active min-[768px]:hidden\"\n aria-label=\"Toggle run navigation\"\n >\n <span className=\"min-w-0\">\n <Text as=\"span\" size=\"xs\" className=\"block text-foreground-neutral-muted\">\n Run navigation\n </Text>\n <span className=\"block truncate font-code text-xs leading-20 text-foreground-neutral-base\">\n {currentLabel}\n </span>\n </span>\n <Icon\n name=\"chevronDown\"\n size={14}\n aria-hidden=\"true\"\n className={cn(\n 'shrink-0 text-foreground-neutral-muted transition-transform',\n mobileOpen && 'rotate-180',\n )}\n />\n </button>\n </CollapsibleTrigger>\n <div\n className={cn(\n 'flex min-h-0 max-h-[50vh] flex-col overflow-y-auto p-tight scrollbar min-[768px]:min-h-0 min-[768px]:max-h-none min-[768px]:flex-1 min-[768px]:flex min-[768px]:overflow-hidden min-[768px]:p-[12px]',\n !mobileOpen && 'hidden',\n )}\n >\n <RunWorkspaceNavContent\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n run={run}\n jobs={jobs}\n activeSection={activeSection}\n currentJobId={resolvedCurrentJobId}\n jobSearch={jobSearch}\n annotationSummary={annotationSummary}\n mobileOpen={mobileOpen}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </Collapsible>\n </aside>\n </TimeTickerProvider>\n );\n}\n\nfunction RunWorkspaceNavContent({\n workspaceSlug,\n projectSlug,\n run,\n jobs,\n activeSection,\n currentJobId,\n jobSearch,\n annotationSummary,\n mobileOpen,\n onNavigate,\n}: RunWorkspaceNavProps & {\n jobs: Job[];\n jobSearch: WorkflowJobSearch;\n mobileOpen: boolean;\n onNavigate: () => void;\n}) {\n const currentRowRef = useRef<HTMLAnchorElement>(null);\n const runAttempt = jobSearch.runAttempt ?? run.runAttempt.attempt;\n\n useEffect(() => {\n if (!currentJobId || mobileOpen) return;\n currentRowRef.current?.scrollIntoView({block: 'nearest'});\n }, [currentJobId, mobileOpen]);\n\n useEffect(() => {\n if (!currentJobId || !mobileOpen) return;\n currentRowRef.current?.scrollIntoView({block: 'nearest'});\n }, [currentJobId, mobileOpen]);\n\n return (\n <nav aria-label=\"Run workspace\" className=\"flex min-h-0 min-w-0 flex-1 flex-col\">\n <ul className=\"border-b border-border-neutral-base pb-row\">\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"summary\"\n current={!currentJobId && activeSection === 'summary'}\n onNavigate={onNavigate}\n />\n </li>\n </ul>\n\n <section\n aria-labelledby=\"run-workspace-jobs-heading\"\n className=\"flex min-h-0 min-w-0 flex-1 flex-col border-b border-border-neutral-base py-row\"\n >\n <div className=\"flex items-center justify-between gap-inline px-tight pb-[6px]\">\n <Text\n as=\"h2\"\n id=\"run-workspace-jobs-heading\"\n size=\"xs\"\n bold\n className=\"text-foreground-neutral-muted\"\n >\n Jobs\n </Text>\n <Text as=\"span\" size=\"xs\" className=\"font-code text-foreground-neutral-subtle\">\n {jobs.length}\n </Text>\n </div>\n <ol className=\"min-h-0 flex-1 overflow-y-auto scrollbar\">\n {jobs.map((job) => {\n const current = job.id === currentJobId;\n const execution = defaultJobExecution(job);\n const duration = execution?.displayDuration ?? job.displayDuration;\n\n return (\n <li key={job.id}>\n <Link\n ref={current ? currentRowRef : undefined}\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId\"\n params={{workspaceSlug, projectSlug, workflowRunId: run.id, jobId: job.id}}\n search={workflowJobSearchParams({runAttempt}) as never}\n onClick={onNavigate}\n aria-current={current ? 'page' : undefined}\n className={cn(\n RUN_WORKSPACE_LINK_CLASS_NAME,\n 'min-w-0 text-left',\n current && 'bg-background-neutral-hover',\n )}\n >\n {current ? <RunWorkspaceActiveBar /> : null}\n <WorkflowStatusIcon\n status={deriveJobDisplayStatus(job)}\n size={12}\n tooltip={false}\n />\n <span className=\"min-w-0 truncate font-code text-xs leading-20 text-foreground-neutral-base\">\n {job.displayName}\n </span>\n <span className=\"ml-auto shrink-0 font-code text-xs leading-20 text-foreground-neutral-muted tabular-nums\">\n {duration ? <JobExecutionTimeText time={duration} /> : '—'}\n </span>\n </Link>\n </li>\n );\n })}\n </ol>\n </section>\n\n <section aria-labelledby=\"run-workspace-details-heading\" className=\"pt-row\">\n <Text\n as=\"h2\"\n id=\"run-workspace-details-heading\"\n size=\"xs\"\n bold\n className=\"px-tight pb-[6px] text-foreground-neutral-muted\"\n >\n Run details\n </Text>\n <ul>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"annotations\"\n current={!currentJobId && activeSection === 'annotations'}\n count={annotationSummary?.total}\n countTruncated={annotationSummary?.truncated}\n onNavigate={onNavigate}\n />\n </li>\n <li>\n <RunSectionLink\n workspaceSlug={workspaceSlug}\n projectSlug={projectSlug}\n runId={run.id}\n runAttempt={runAttempt}\n section=\"source\"\n current={!currentJobId && activeSection === 'source'}\n onNavigate={onNavigate}\n />\n </li>\n </ul>\n </section>\n </nav>\n );\n}\n\nfunction RunSectionLink({\n workspaceSlug,\n projectSlug,\n runId,\n runAttempt,\n section,\n current,\n count,\n countTruncated = false,\n onNavigate,\n}: {\n workspaceSlug: string;\n projectSlug: string;\n runId: string;\n runAttempt: number;\n section: RunWorkspaceSection;\n current: boolean;\n count?: number | undefined;\n /** The read hit its page budget, so the count is a lower bound and renders as `N+`. */\n countTruncated?: boolean | undefined;\n onNavigate?: (() => void) | undefined;\n}) {\n return (\n <Link\n to=\"/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId\"\n params={{workspaceSlug, projectSlug, workflowRunId: runId}}\n search={\n workflowRunSearchParams(\n {runAttempt, ...(section === 'summary' ? {} : {tab: section})},\n {runAttempt},\n ) as never\n }\n onClick={onNavigate}\n aria-current={current ? 'page' : undefined}\n aria-label={\n count\n ? `${sectionLabel(section)}, ${countTruncated ? `${count} or more` : count}`\n : undefined\n }\n className={cn(\n RUN_WORKSPACE_LINK_CLASS_NAME,\n 'text-xs font-medium text-foreground-neutral-base',\n current && 'bg-background-neutral-hover',\n )}\n >\n {current ? <RunWorkspaceActiveBar /> : null}\n {sectionLabel(section)}\n {count ? (\n <span\n aria-hidden=\"true\"\n className=\"ml-auto font-code text-xs text-foreground-neutral-muted tabular-nums\"\n >\n {count}\n {countTruncated ? '+' : ''}\n </span>\n ) : null}\n </Link>\n );\n}\n\nfunction RunWorkspaceActiveBar() {\n return (\n <span\n aria-hidden=\"true\"\n data-run-workspace-active-bar\n className=\"absolute inset-y-0 left-0 w-2 rounded-l-4 bg-border-highlights-interactive\"\n />\n );\n}\n\nfunction sectionLabel(section: RunWorkspaceSection): string {\n if (section === 'annotations') return 'Annotations';\n if (section === 'source') return 'Source';\n return 'Summary';\n}\n\nfunction compareJobs(left: Job, right: Job): number {\n return left.position - right.position || left.id.localeCompare(right.id);\n}\n"],"names":["Collapsible","CollapsibleTrigger","Icon","TimeTickerProvider","Text","cn","Link","useEffect","useMemo","useRef","useState","WorkflowStatusIcon","defaultJobExecution","deriveJobDisplayStatus","workflowJobSearchParams","workflowRunSearchParams","JobExecutionTimeText","RUN_WORKSPACE_LINK_CLASS_NAME","RunWorkspaceNav","workspaceSlug","projectSlug","run","activeSection","currentJobId","jobSearch","annotationSummary","jobs","sort","compareJobs","mobileOpen","setMobileOpen","currentJob","find","job","id","undefined","resolvedCurrentJobId","currentLabel","displayName","sectionLabel","intervalMs","reducedMotionIntervalMs","aside","className","open","onOpenChange","asChild","button","type","aria-label","span","as","size","name","aria-hidden","div","RunWorkspaceNavContent","onNavigate","currentRowRef","runAttempt","attempt","current","scrollIntoView","block","nav","ul","li","RunSectionLink","runId","section","aria-labelledby","bold","length","ol","map","execution","duration","displayDuration","ref","to","params","workflowRunId","jobId","search","onClick","aria-current","RunWorkspaceActiveBar","status","tooltip","time","count","total","countTruncated","truncated","tab","data-run-workspace-active-bar","left","right","position","localeCompare"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run-states.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAO5D,wBAAgB,mBAAmB,gCAwBlC;AAED,wBAAgB,0BAA0B,gCASzC;AAED,wBAAgB,mBAAmB,gCAQlC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAC,+BAqB1E"}
1
+ {"version":3,"file":"workflow-run-states.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,oBAAoB,CAAC;AAO5D,wBAAgB,mBAAmB,gCAqBlC;AAED,wBAAgB,0BAA0B,gCASzC;AAED,wBAAgB,mBAAmB,gCAQlC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAC,+BAqB1E"}
@@ -7,7 +7,7 @@ import { Text } from '@shipfox/react-ui/typography';
7
7
  export function WorkflowRunSkeleton() {
8
8
  return /*#__PURE__*/ _jsx("section", {
9
9
  "aria-label": "Loading workflow run",
10
- className: "bg-background-neutral-background px-row py-row",
10
+ className: "px-row py-row",
11
11
  children: /*#__PURE__*/ _jsxs("div", {
12
12
  className: "flex min-w-0 flex-wrap items-center gap-x-cluster gap-y-inline",
13
13
  children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"sourcesContent":["import type {QueryLoadErrorQuery} from '@shipfox/client-ui';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\n\nexport function WorkflowRunSkeleton() {\n return (\n <section\n aria-label=\"Loading workflow run\"\n className=\"bg-background-neutral-background px-row py-row\"\n >\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-cluster gap-y-inline\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n <Skeleton className=\"size-8 rounded-full\" />\n <Skeleton className=\"h-24 w-180 rounded-6\" />\n </div>\n <Skeleton className=\"h-24 w-88 rounded-6\" />\n <span\n aria-hidden=\"true\"\n className=\"hidden h-20 w-px shrink-0 bg-border-neutral-base sm:block\"\n />\n <Skeleton className=\"h-20 w-64 rounded-4\" />\n <Skeleton className=\"h-20 w-112 rounded-4\" />\n <span className=\"min-w-0 flex-1\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n </div>\n </section>\n );\n}\n\nexport function WorkflowRunContentSkeleton() {\n return (\n <section\n aria-label=\"Loading workflow run content\"\n className=\"min-h-160 rounded-8 border border-border-neutral-base bg-background-components-base p-panel-compact\"\n >\n <Skeleton className=\"h-160 w-full rounded-6\" />\n </section>\n );\n}\n\nexport function WorkflowRunNotFound() {\n return (\n <EmptyState\n icon=\"pulseLine\"\n title=\"Run not found\"\n description=\"This run does not exist or is no longer available.\"\n />\n );\n}\n\n/**\n * Slim non-blocking banner shown when a background refetch fails after the run already\n * loaded (active-run polling can hit a transient API error), so the loaded run stays on\n * screen with an inline retry instead of being wiped by a full error placeholder.\n */\nexport function WorkflowRunStaleError({query}: {query: QueryLoadErrorQuery}) {\n return (\n <div className=\"border-b border-border-neutral-base p-tight\">\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex items-center justify-between gap-inline\">\n <Text size=\"xs\">Could not refresh this run.</Text>\n <Button\n type=\"button\"\n size=\"2xs\"\n variant=\"secondary\"\n isLoading={query.isFetching}\n onClick={() => {\n void query.refetch();\n }}\n >\n Retry\n </Button>\n </div>\n </Callout>\n </div>\n );\n}\n"],"names":["Button","Callout","EmptyState","Skeleton","Text","WorkflowRunSkeleton","section","aria-label","className","div","span","aria-hidden","WorkflowRunContentSkeleton","WorkflowRunNotFound","icon","title","description","WorkflowRunStaleError","query","role","type","size","variant","isLoading","isFetching","onClick","refetch"],"mappings":";AACA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,IAAI,QAAO,+BAA+B;AAElD,OAAO,SAASC;IACd,qBACE,KAACC;QACCC,cAAW;QACXC,WAAU;kBAEV,cAAA,MAACC;YAAID,WAAU;;8BACb,MAACC;oBAAID,WAAU;;sCACb,KAACL;4BAASK,WAAU;;sCACpB,KAACL;4BAASK,WAAU;;;;8BAEtB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBACCC,eAAY;oBACZH,WAAU;;8BAEZ,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBAAKF,WAAU;;8BAChB,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;;;;AAI5B;AAEA,OAAO,SAASI;IACd,qBACE,KAACN;QACCC,cAAW;QACXC,WAAU;kBAEV,cAAA,KAACL;YAASK,WAAU;;;AAG1B;AAEA,OAAO,SAASK;IACd,qBACE,KAACX;QACCY,MAAK;QACLC,OAAM;QACNC,aAAY;;AAGlB;AAEA;;;;CAIC,GACD,OAAO,SAASC,sBAAsB,EAACC,KAAK,EAA+B;IACzE,qBACE,KAACT;QAAID,WAAU;kBACb,cAAA,KAACP;YAAQkB,MAAK;YAAQC,MAAK;sBACzB,cAAA,MAACX;gBAAID,WAAU;;kCACb,KAACJ;wBAAKiB,MAAK;kCAAK;;kCAChB,KAACrB;wBACCoB,MAAK;wBACLC,MAAK;wBACLC,SAAQ;wBACRC,WAAWL,MAAMM,UAAU;wBAC3BC,SAAS;4BACP,KAAKP,MAAMQ,OAAO;wBACpB;kCACD;;;;;;AAOX"}
1
+ {"version":3,"sources":["../../../src/components/workflow-run-view/workflow-run-states.tsx"],"sourcesContent":["import type {QueryLoadErrorQuery} from '@shipfox/client-ui';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\n\nexport function WorkflowRunSkeleton() {\n return (\n <section aria-label=\"Loading workflow run\" className=\"px-row py-row\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-cluster gap-y-inline\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n <Skeleton className=\"size-8 rounded-full\" />\n <Skeleton className=\"h-24 w-180 rounded-6\" />\n </div>\n <Skeleton className=\"h-24 w-88 rounded-6\" />\n <span\n aria-hidden=\"true\"\n className=\"hidden h-20 w-px shrink-0 bg-border-neutral-base sm:block\"\n />\n <Skeleton className=\"h-20 w-64 rounded-4\" />\n <Skeleton className=\"h-20 w-112 rounded-4\" />\n <span className=\"min-w-0 flex-1\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n <Skeleton className=\"h-20 w-88 rounded-4\" />\n </div>\n </section>\n );\n}\n\nexport function WorkflowRunContentSkeleton() {\n return (\n <section\n aria-label=\"Loading workflow run content\"\n className=\"min-h-160 rounded-8 border border-border-neutral-base bg-background-components-base p-panel-compact\"\n >\n <Skeleton className=\"h-160 w-full rounded-6\" />\n </section>\n );\n}\n\nexport function WorkflowRunNotFound() {\n return (\n <EmptyState\n icon=\"pulseLine\"\n title=\"Run not found\"\n description=\"This run does not exist or is no longer available.\"\n />\n );\n}\n\n/**\n * Slim non-blocking banner shown when a background refetch fails after the run already\n * loaded (active-run polling can hit a transient API error), so the loaded run stays on\n * screen with an inline retry instead of being wiped by a full error placeholder.\n */\nexport function WorkflowRunStaleError({query}: {query: QueryLoadErrorQuery}) {\n return (\n <div className=\"border-b border-border-neutral-base p-tight\">\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex items-center justify-between gap-inline\">\n <Text size=\"xs\">Could not refresh this run.</Text>\n <Button\n type=\"button\"\n size=\"2xs\"\n variant=\"secondary\"\n isLoading={query.isFetching}\n onClick={() => {\n void query.refetch();\n }}\n >\n Retry\n </Button>\n </div>\n </Callout>\n </div>\n );\n}\n"],"names":["Button","Callout","EmptyState","Skeleton","Text","WorkflowRunSkeleton","section","aria-label","className","div","span","aria-hidden","WorkflowRunContentSkeleton","WorkflowRunNotFound","icon","title","description","WorkflowRunStaleError","query","role","type","size","variant","isLoading","isFetching","onClick","refetch"],"mappings":";AACA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,IAAI,QAAO,+BAA+B;AAElD,OAAO,SAASC;IACd,qBACE,KAACC;QAAQC,cAAW;QAAuBC,WAAU;kBACnD,cAAA,MAACC;YAAID,WAAU;;8BACb,MAACC;oBAAID,WAAU;;sCACb,KAACL;4BAASK,WAAU;;sCACpB,KAACL;4BAASK,WAAU;;;;8BAEtB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBACCC,eAAY;oBACZH,WAAU;;8BAEZ,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;8BACpB,KAACE;oBAAKF,WAAU;;8BAChB,KAACL;oBAASK,WAAU;;8BACpB,KAACL;oBAASK,WAAU;;;;;AAI5B;AAEA,OAAO,SAASI;IACd,qBACE,KAACN;QACCC,cAAW;QACXC,WAAU;kBAEV,cAAA,KAACL;YAASK,WAAU;;;AAG1B;AAEA,OAAO,SAASK;IACd,qBACE,KAACX;QACCY,MAAK;QACLC,OAAM;QACNC,aAAY;;AAGlB;AAEA;;;;CAIC,GACD,OAAO,SAASC,sBAAsB,EAACC,KAAK,EAA+B;IACzE,qBACE,KAACT;QAAID,WAAU;kBACb,cAAA,KAACP;YAAQkB,MAAK;YAAQC,MAAK;sBACzB,cAAA,MAACX;gBAAID,WAAU;;kCACb,KAACJ;wBAAKiB,MAAK;kCAAK;;kCAChB,KAACrB;wBACCoB,MAAK;wBACLC,MAAK;wBACLC,SAAQ;wBACRC,WAAWL,MAAMM,UAAU;wBAC3BC,SAAS;4BACP,KAAKP,MAAMQ,OAAO;wBACpB;kCACD;;;;;;AAOX"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-run-view.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-view.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAezD,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAqB3B,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC3C,GAAG,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,EACT,GAAG,EACH,WAAW,EACX,SAAS,EACT,UAAU,GACX,EAAE,oBAAoB,+BA0CtB"}
1
+ {"version":3,"file":"workflow-run-view.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-view/workflow-run-view.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAezD,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAqB3B,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC3C,GAAG,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,EACT,GAAG,EACH,WAAW,EACX,SAAS,EACT,UAAU,GACX,EAAE,oBAAoB,+BA0CtB"}