Skip to content

Commit 172d1eb

Browse files
bchapuisclaude
andcommitted
Restyle workflow preview with transparent background and refined layout
Adds an optional transparent-background mode to the workflow preview embed and redesigns the workflow detail page to place the CTA next to the title, tags under the title, and the description below the preview. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 17cc4c7 commit 172d1eb

6 files changed

Lines changed: 104 additions & 35 deletions

File tree

apps/app/src/components/workflow/workflow-builder.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export interface WorkflowBuilderProps {
8989
parameters?: Record<string, unknown>;
9090
}) => void;
9191
showSidebar?: boolean;
92+
showBackground?: boolean;
9293
isEnabled?: boolean;
9394
isTogglingEnabled?: boolean;
9495
onToggleEnabled?: (checked: boolean) => void;
@@ -116,6 +117,7 @@ export function WorkflowBuilder({
116117
orgId,
117118
wsExecuteWorkflow,
118119
showSidebar,
120+
showBackground = true,
119121
isEnabled,
120122
isTogglingEnabled,
121123
onToggleEnabled,
@@ -313,6 +315,7 @@ export function WorkflowBuilder({
313315
onPasteFromClipboard={readOnly ? undefined : pasteFromClipboard}
314316
hasClipboardData={hasClipboardData}
315317
showControls={interactive}
318+
showBackground={showBackground}
316319
/>
317320
</div>
318321

apps/app/src/components/workflow/workflow-canvas.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export interface WorkflowCanvasProps {
172172
onCutSelected?: () => void;
173173
onPasteFromClipboard?: () => void;
174174
hasClipboardData?: boolean;
175+
showBackground?: boolean;
175176
}
176177

177178
interface ActionButtonProps {
@@ -573,6 +574,7 @@ export function WorkflowCanvas({
573574
onCutSelected,
574575
onPasteFromClipboard,
575576
hasClipboardData = false,
577+
showBackground = true,
576578
}: WorkflowCanvasProps) {
577579
// Get selected elements for button states
578580
const hasSelectedElements =
@@ -606,9 +608,10 @@ export function WorkflowCanvas({
606608
}}
607609
minZoom={0.05}
608610
maxZoom={4}
609-
className={cn("bg-neutral-100/50", {
610-
"cursor-default": disabled,
611-
})}
611+
className={cn(
612+
showBackground && "bg-neutral-100/50",
613+
disabled && "cursor-default"
614+
)}
612615
nodesDraggable={!disabled && showControls}
613616
nodesConnectable={!disabled && showControls}
614617
elementsSelectable={showControls}
@@ -627,12 +630,14 @@ export function WorkflowCanvas({
627630
showFitView={false}
628631
/>
629632
)}
630-
<Background
631-
variant={BackgroundVariant.Dots}
632-
gap={12}
633-
size={1}
634-
className="stroke-foreground/5 opacity-50"
635-
/>
633+
{showBackground && (
634+
<Background
635+
variant={BackgroundVariant.Dots}
636+
gap={12}
637+
size={1}
638+
className="stroke-foreground/5 opacity-50"
639+
/>
640+
)}
636641

637642
{/* Status Bar - hidden in read-only mode */}
638643
{!disabled && (

apps/app/src/index.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,38 @@ html.dark .cm-scroller {
297297
html.dark .cm-content {
298298
color: #e0e0e0;
299299
}
300+
301+
/* React Flow attribution restyled as a small pill button */
302+
.react-flow__attribution {
303+
margin: 6px !important;
304+
padding: 2px 8px !important;
305+
border-radius: 9999px;
306+
background: rgba(255, 255, 255, 0.85) !important;
307+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
308+
border: 1px solid rgba(0, 0, 0, 0.06);
309+
backdrop-filter: blur(4px);
310+
font-size: 10px;
311+
line-height: 1.4;
312+
transition: background-color 0.15s ease;
313+
}
314+
315+
.react-flow__attribution:hover {
316+
background: rgba(255, 255, 255, 1) !important;
317+
}
318+
319+
.react-flow__attribution a {
320+
color: #666 !important;
321+
}
322+
323+
html.dark .react-flow__attribution {
324+
background: rgba(30, 30, 30, 0.7) !important;
325+
border-color: rgba(255, 255, 255, 0.08);
326+
}
327+
328+
html.dark .react-flow__attribution:hover {
329+
background: rgba(30, 30, 30, 0.9) !important;
330+
}
331+
332+
html.dark .react-flow__attribution a {
333+
color: #bbb !important;
334+
}

apps/app/src/pages/template-preview-page.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ export function TemplatePreviewPage() {
3535
}
3636
}, [templates, templateId]);
3737

38+
// When embedded without background, make html/body transparent so the
39+
// host page's background shows through the iframe.
40+
useEffect(() => {
41+
if (showBackground) return;
42+
const { documentElement, body } = document;
43+
const prevHtml = documentElement.style.background;
44+
const prevBody = body.style.background;
45+
documentElement.style.background = "transparent";
46+
body.style.background = "transparent";
47+
return () => {
48+
documentElement.style.background = prevHtml;
49+
body.style.background = prevBody;
50+
};
51+
}, [showBackground]);
52+
3853
// Convert template to React Flow nodes and edges
3954
const { nodes, edges } = useMemo(() => {
4055
if (!template || nodeTypes.length === 0) {
@@ -71,7 +86,14 @@ export function TemplatePreviewPage() {
7186
return (
7287
<div
7388
className="w-full h-screen"
74-
style={{ background: showBackground ? undefined : "transparent" }}
89+
style={
90+
showBackground
91+
? undefined
92+
: {
93+
background: "transparent",
94+
["--xy-background-color" as string]: "transparent",
95+
}
96+
}
7597
>
7698
<ReactFlowProvider>
7799
<WorkflowBuilder
@@ -84,6 +106,7 @@ export function TemplatePreviewPage() {
84106
expandedOutputs={false}
85107
createObjectUrl={() => ""}
86108
orgId=""
109+
showBackground={showBackground}
87110
/>
88111
</ReactFlowProvider>
89112
</div>

apps/www/src/components/workflow-preview.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ export function WorkflowPreview({
2121
const embedUrl = `${APP_URL}/embed/templates/${templateId}${showBackground ? "" : "?bg=false"}`;
2222

2323
return (
24-
<div className={cn("rounded-xl overflow-hidden bg-neutral-50", className)}>
24+
<div
25+
className={cn(
26+
"rounded-xl overflow-hidden",
27+
showBackground && "bg-neutral-50",
28+
className
29+
)}
30+
>
2531
<iframe
2632
src={embedUrl}
2733
title={`Workflow preview for ${templateId}`}

apps/www/src/routes/workflows/$workflowId.tsx

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -117,53 +117,50 @@ export default function WorkflowPage({
117117
&larr; All use cases
118118
</Link>
119119

120-
<div className="mb-12">
121-
<div className="flex items-start gap-6 mb-6">
122-
<div className="flex-shrink-0 w-16 h-16 bg-white rounded-xl shadow-sm flex items-center justify-center">
123-
<IconComponent className="w-8 h-8 text-gray-600" />
120+
<div className="mb-12 flex items-center justify-between gap-6">
121+
<div className="flex items-center gap-6 min-w-0">
122+
<div className="flex-shrink-0 w-24 h-24 bg-white rounded-2xl shadow-sm flex items-center justify-center">
123+
<IconComponent className="w-12 h-12 text-gray-600" />
124124
</div>
125-
<div>
125+
<div className="min-w-0">
126126
<h1 className="text-6xl font-light text-gray-900">
127127
{workflow.name}
128128
</h1>
129+
<div className="flex flex-wrap items-center gap-2 mt-3">
130+
{workflow.tags.map((tag) => (
131+
<span
132+
key={tag}
133+
className="px-3 py-1 bg-gray-200 text-gray-700 rounded-full text-sm"
134+
>
135+
{tag}
136+
</span>
137+
))}
138+
</div>
129139
</div>
130140
</div>
131141

132-
<p className="text-3xl text-gray-500 mb-6">{workflow.description}</p>
133-
134-
<div className="flex flex-wrap items-center gap-3 mb-8">
135-
{workflow.tags.map((tag) => (
136-
<span
137-
key={tag}
138-
className="px-3 py-1 bg-gray-200 text-gray-700 rounded-full text-sm"
139-
>
140-
{tag}
141-
</span>
142-
))}
143-
</div>
144-
145142
<a
146143
href={`${import.meta.env.VITE_APP_URL}/templates/${workflow.id}/try`}
147-
className="inline-block text-lg bg-black text-white px-8 py-4 rounded-lg hover:bg-gray-800 transition-colors"
144+
className="flex-shrink-0 inline-block text-lg bg-black text-white px-8 py-4 rounded-lg hover:bg-gray-800 transition-colors"
148145
>
149146
Try this workflow
150147
</a>
151148
</div>
152149

153150
{/* Workflow Preview */}
154151
<section className="mb-12">
155-
<h2 className="text-2xl font-light text-gray-900 mb-4">
156-
Workflow Preview
157-
</h2>
158152
<WorkflowPreview
159153
templateId={workflow.id}
160-
className="h-[40rem] border border-gray-200"
154+
className="h-[40rem]"
155+
showBackground={false}
161156
/>
162157
</section>
163158

159+
<p className="text-3xl text-gray-500 mb-12">{workflow.description}</p>
160+
164161
{/* Other Workflows */}
165162
{otherWorkflows.length > 0 && (
166-
<section className="mt-32 pt-8 border-t border-gray-200">
163+
<section className="mt-32">
167164
<h2 className="text-2xl font-light text-gray-900 mb-6">
168165
Other Workflows
169166
</h2>

0 commit comments

Comments
 (0)