From a53e76a0ab0a6c8f744456aad1dcc34b447785ef Mon Sep 17 00:00:00 2001 From: Wojtek Majewski Date: Thu, 6 Nov 2025 19:14:28 +0100 Subject: [PATCH] style: improve UI layout and add descriptive annotations to components Refactored layout styles for desktop and mobile views, including flexbox adjustments, spacing, and responsive behavior. Enhanced ExplanationPanel with detailed step descriptions. Added reliability features and "what it does" explanations to flow components. Updated DAG visualization and event stream sections for better usability and clarity. --- .../lib/components/DAGVisualization.svelte | 1 + .../lib/components/ExplanationPanel.svelte | 45 ++- apps/demo/src/routes/+page.svelte | 367 +++++++++++++----- 3 files changed, 310 insertions(+), 103 deletions(-) diff --git a/apps/demo/src/lib/components/DAGVisualization.svelte b/apps/demo/src/lib/components/DAGVisualization.svelte index 6061bdac6..11d9b5bf1 100644 --- a/apps/demo/src/lib/components/DAGVisualization.svelte +++ b/apps/demo/src/lib/components/DAGVisualization.svelte @@ -314,6 +314,7 @@ outline-offset: 2px !important; box-shadow: 0 0 20px rgba(88, 166, 255, 0.4) !important; cursor: pointer !important; + opacity: 1 !important; /* Ensure selected nodes are never dimmed */ } @keyframes pulse { diff --git a/apps/demo/src/lib/components/ExplanationPanel.svelte b/apps/demo/src/lib/components/ExplanationPanel.svelte index 53e7864bb..554d796d3 100644 --- a/apps/demo/src/lib/components/ExplanationPanel.svelte +++ b/apps/demo/src/lib/components/ExplanationPanel.svelte @@ -45,6 +45,18 @@ displayName: 'Article Processing Flow', description: 'This flow processes web articles by fetching content, generating summaries and keywords, then publishing the results.', + whatItDoes: + 'Demonstrates parallel execution, automatic retries, and dependency management—all core pgflow features.', + reliabilityFeatures: [ + { + setting: 'maxAttempts: 3', + explanation: 'Automatically retries failed steps up to 3 times before giving up' + }, + { + setting: 'timeout: 60', + explanation: 'Tasks become visible for retry after 60 seconds if worker crashes' + } + ], inputType: `{ url: string }`, @@ -57,6 +69,7 @@ { name: string; displayName: string; + whatItDoes: string; dependsOn: string[]; dependents: string[]; inputType: string; @@ -66,6 +79,7 @@ fetch_article: { name: 'fetch_article', displayName: 'Fetch Article', + whatItDoes: 'Fetches article content from the provided URL using r.jina.ai. Returns both the article text and title for downstream processing.', dependsOn: [], dependents: ['summarize', 'extract_keywords'], inputType: `{ @@ -81,6 +95,7 @@ summarize: { name: 'summarize', displayName: 'Summarize', + whatItDoes: 'Uses an LLM (Groq) to generate a concise summary of the article content. Runs in parallel with keyword extraction for efficiency.', dependsOn: ['fetch_article'], dependents: ['publish'], inputType: `{ @@ -94,6 +109,7 @@ extract_keywords: { name: 'extract_keywords', displayName: 'Extract Keywords', + whatItDoes: 'Uses an LLM (Groq) to extract key terms and topics from the article. Runs in parallel with summarization for efficiency.', dependsOn: ['fetch_article'], dependents: ['publish'], inputType: `{ @@ -106,6 +122,7 @@ publish: { name: 'publish', displayName: 'Publish', + whatItDoes: 'Combines the summary and keywords and publishes the processed article. In this demo, generates a mock article ID—in production, this would save to a database.', dependsOn: ['summarize', 'extract_keywords'], dependents: [], inputType: `{ @@ -254,6 +271,13 @@ {#if currentStepInfo} + +
+

+ {currentStepInfo.whatItDoes} +

+
+
@@ -333,10 +357,25 @@ {:else}
- + +
+

{flowInfo.description}

+

{flowInfo.whatItDoes}

+
+ +
-
Description
-

{flowInfo.description}

+
+ 🛡️ Reliability Configuration +
+
+ {#each flowInfo.reliabilityFeatures as feature} +
+ {feature.setting} +

{feature.explanation}

+
+ {/each} +
diff --git a/apps/demo/src/routes/+page.svelte b/apps/demo/src/routes/+page.svelte index 291f36584..ab0718897 100644 --- a/apps/demo/src/routes/+page.svelte +++ b/apps/demo/src/routes/+page.svelte @@ -152,6 +152,13 @@ onDestroy(() => flowState.dispose()); const isRunning = $derived(flowState.status === 'starting' || flowState.status === 'started'); + + // Event stream collapsed state + let eventStreamCollapsed = $state(false); + + function toggleEventStream() { + eventStreamCollapsed = !eventStreamCollapsed; + }
- -
- -
- - - - - {#if flowState.events.length > 0} - - {/if} + + - -
- -
- {#if explanationVisible} - - {/if} + +
+ +
+
- -
- -
+ + {#if flowState.events.length > 0} +
+ + +
+ Event Stream + + {eventStreamCollapsed ? '▶' : '▼'} Click to {eventStreamCollapsed ? 'expand' : 'collapse'} + +
+
+ {#if !eventStreamCollapsed} + + + + {/if} +
+
+ {/if} +
- -
@@ -355,41 +429,125 @@ width: 100%; max-width: 1440px; height: 100%; + display: flex; + flex-direction: column; + gap: 1rem; } - /* Desktop: Two columns using flexbox */ + /* Header section with logo and input */ + .header-section { + flex-shrink: 0; + align-items: center; + gap: 1rem; + padding: 0.75rem 0; + border-bottom: 1px solid hsl(var(--border)); + margin-bottom: 0.5rem; + } + + /* Main layout: Code + Event Stream (left) | DAG & Details (right) */ .main-layout { display: flex; - height: 100%; + flex: 1; + min-height: 0; gap: 1rem; } .left-column { - flex: 1; + flex: 1 1 auto; + min-width: 850px; /* Code panel needs generous space */ display: flex; flex-direction: column; - min-width: 0; + overflow: hidden; + gap: 0.75rem; + } + + .code-panel-container { + flex: 1; + min-height: 0; overflow: hidden; } + /* Event stream in left column (bottom) */ + .event-stream-section-left { + flex-shrink: 0; + max-height: 35vh; + overflow: hidden; + } + + .event-stream-section-left .collapsed { + max-height: 3rem; + } + + .event-stream-section-left .expanded { + display: flex; + flex-direction: column; + max-height: 35vh; + } + + .event-stream-section-left .expanded .event-stream-content { + flex: 1; + overflow: auto; + min-height: 0; + } + .right-column { flex: 0 0 auto; - width: 720px; - min-width: 720px; + width: 520px; + min-width: 520px; display: flex; flex-direction: column; min-height: 0; overflow: hidden; } - /* Mobile: Single column, hide left, right takes full width */ + .dag-card { + flex-shrink: 0; + } + + /* Tablet/Small Desktop (769px-1400px): Stack columns vertically */ + @media (max-width: 1400px) and (min-width: 769px) { + .main-layout { + flex-direction: column; + gap: 1rem; + } + + .left-column { + min-width: 0; + flex: 0 0 auto; + height: auto; + max-height: none; /* Remove height limit */ + } + + .code-panel-container { + height: 500px; /* Fixed height for code when stacked */ + } + + .event-stream-section-left { + max-height: 250px; /* Smaller event stream when stacked */ + } + + .event-stream-section-left .expanded { + max-height: 250px; + } + + .right-column { + flex: 1; + width: 100%; + min-width: 0; + } + } + + /* Mobile: Single column, simplified layout */ @media (max-width: 768px) { .main-layout { + flex-direction: column; gap: 0; } .left-column { - display: none; + flex: 0 0 auto; + height: auto; + min-width: 0; } .right-column { @@ -398,8 +556,8 @@ min-width: 0; } - .mobile-code-wrapper { - flex-shrink: 0; + .event-stream-section-left { + display: none; /* Hide on mobile */ } .mobile-dag-container { @@ -418,6 +576,15 @@ } } + /* Welcome guide card styling */ + :global(.welcome-guide) { + overflow-y: auto; + } + + :global(.welcome-guide h3) { + color: hsl(var(--foreground)); + } + /* Contact banner using pgflow palette */ :global(.contact-banner) { background: linear-gradient(135deg, #007b6e 0%, #9979d3 100%);