Skip to content

Commit 01a2732

Browse files
committed
truncate workflow title and add copy action
1 parent 60ae010 commit 01a2732

2 files changed

Lines changed: 43 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Workflow detail: add on-canvas zoom controls for click/touch navigation and improve controls styling for dark mode. [PR #524](https://github.com/riverqueue/riverui/pull/524).
1313
- Workflow detail: improve default workflow diagram framing for legibility while still allowing manual zoom-out to view the full graph. [PR #524](https://github.com/riverqueue/riverui/pull/524).
14+
- Workflow detail: truncate long workflow names in the header to prevent overflow and add a copy button for the full name. [PR #524](https://github.com/riverqueue/riverui/pull/524).
1415

1516
## [v0.15.0] - 2026-02-26
1617

src/components/WorkflowDetail.tsx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ import TopNavTitleOnly from "@components/TopNavTitleOnly";
88
import WorkflowDiagram from "@components/workflow-diagram/WorkflowDiagram";
99
import { useFeatures } from "@contexts/Features.hook";
1010
// (Dialog is now encapsulated in RetryWorkflowDialog)
11-
import { ArrowPathIcon, XCircleIcon } from "@heroicons/react/24/outline";
11+
import { CheckIcon } from "@heroicons/react/16/solid";
12+
import {
13+
ArrowPathIcon,
14+
ClipboardIcon,
15+
XCircleIcon,
16+
} from "@heroicons/react/24/outline";
1217
import { JobWithKnownMetadata } from "@services/jobs";
18+
import { toastSuccess } from "@services/toast";
1319
import { JobState } from "@services/types";
1420
import { Workflow, type WorkflowRetryMode } from "@services/workflows";
1521
import { Link } from "@tanstack/react-router";
@@ -76,6 +82,7 @@ export default function WorkflowDetail({
7682
// Modal state for retry
7783
const [retryOpen, setRetryOpen] = useState(false);
7884
const [retryMode, setRetryMode] = useState<undefined | WorkflowRetryMode>();
85+
const [workflowNameCopied, setWorkflowNameCopied] = useState(false);
7986

8087
if (!features.workflowQueries) {
8188
return (
@@ -93,23 +100,51 @@ export default function WorkflowDetail({
93100
return <h4>No workflow data available</h4>;
94101
}
95102

96-
const { tasks } = workflow;
97-
98103
// Ensure firstTask exists before rendering
99104
if (!firstTask) {
100105
return <h4>No tasks available</h4>;
101106
}
107+
const { tasks } = workflow;
108+
const workflowName = firstTask.metadata.workflow_name || "Unnamed Workflow";
102109

103110
return (
104111
<>
105112
<TopNavTitleOnly title="Workflow Detail" />
106113
<header>
107114
{/* Heading */}
108115
<div className="mb-4 flex flex-col items-start justify-between gap-x-8 gap-y-4 bg-gray-300/10 p-4 sm:flex-row sm:items-center sm:px-6 lg:px-8 dark:bg-gray-700/10">
109-
<div>
110-
<h1 className="flex gap-x-3 text-2xl leading-7">
111-
<span className="font-semibold text-slate-900 dark:text-white">
112-
{firstTask.metadata.workflow_name || "Unnamed Workflow"}
116+
<div className="w-full min-w-0 flex-1">
117+
<h1 className="text-2xl leading-7">
118+
<span className="inline-flex max-w-full items-center gap-x-2">
119+
<span
120+
className="block min-w-0 truncate font-semibold text-slate-900 dark:text-white"
121+
title={workflowName}
122+
>
123+
{workflowName}
124+
</span>
125+
<button
126+
className="inline-flex shrink-0 cursor-pointer items-center rounded p-1 text-slate-500 hover:text-brand-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-primary dark:text-slate-400 dark:hover:text-brand-primary"
127+
onClick={() => {
128+
navigator.clipboard.writeText(workflowName).then(() => {
129+
setWorkflowNameCopied(true);
130+
toastSuccess({
131+
message: "Workflow name copied to clipboard",
132+
});
133+
setTimeout(() => setWorkflowNameCopied(false), 2000);
134+
});
135+
}}
136+
title="Copy workflow name"
137+
type="button"
138+
>
139+
{workflowNameCopied ? (
140+
<CheckIcon
141+
aria-hidden="true"
142+
className="size-4 text-green-500"
143+
/>
144+
) : (
145+
<ClipboardIcon aria-hidden="true" className="size-4" />
146+
)}
147+
</button>
113148
</span>
114149
</h1>
115150
<p className="mt-2 text-base leading-6 text-slate-600 dark:text-slate-400">

0 commit comments

Comments
 (0)