diff --git a/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte b/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte
new file mode 100644
index 00000000..8c3fb79c
--- /dev/null
+++ b/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte
@@ -0,0 +1,80 @@
+
+
+
+
+{#if arcs.length === 0}
+
+
+{:else if arcs.length === 1}
+
+
+{:else}
+
+
+{/if}
diff --git a/web/src/lib/components/repo/pipelines/PipelineWorkflows.stories.svelte b/web/src/lib/components/repo/pipelines/PipelineWorkflows.stories.svelte
new file mode 100644
index 00000000..9af695a5
--- /dev/null
+++ b/web/src/lib/components/repo/pipelines/PipelineWorkflows.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/src/lib/components/repo/pipelines/PipelineWorkflows.svelte b/web/src/lib/components/repo/pipelines/PipelineWorkflows.svelte
index ec565ade..9326eac2 100644
--- a/web/src/lib/components/repo/pipelines/PipelineWorkflows.svelte
+++ b/web/src/lib/components/repo/pipelines/PipelineWorkflows.svelte
@@ -12,7 +12,8 @@
row: "flex w-full items-center justify-between gap-2",
name: "flex min-w-0 items-center gap-1.5",
label: "truncate",
- outcome: "shrink-0 text-foreground-muted"
+ outcome: "shrink-0 text-foreground-muted",
+ status: "mt-0.5"
},
variants: {
variant: {
@@ -39,6 +40,7 @@
import { finishedCount, longSummary, shortSummary, STATUS_LABELS } from "./pipeline";
import PipelineStatusIcon from "./PipelineStatusIcon.svelte";
import PipelineSymbol from "./PipelineSymbol.svelte";
+ import ShimmerText from "$lib/components/ui/ShimmerText.svelte";
interface Props {
ownerHandle: string;
@@ -63,24 +65,36 @@
{#if count === 0}
-
-
- {#if variant === "count"}
- Waiting for a spindle…
- {/if}
-
+
+
+
+ {#if variant === "count"}
+ Waiting for a spindle…
+ {/if}
+
+
{:else}
-
+
{#snippet trigger()}
{#if variant === "symbol"}
- {summary === "long" ? longSummary(pipeline) : shortSummary(pipeline)}
+
+ {summary === "long" ? longSummary(pipeline) : shortSummary(pipeline)}
+
{:else}
- {label}
+
+ {label}
+
{/if}
diff --git a/web/src/lib/components/repo/pipelines/pipeline.ts b/web/src/lib/components/repo/pipelines/pipeline.ts
index f0f4dfb9..2ecb21a0 100644
--- a/web/src/lib/components/repo/pipelines/pipeline.ts
+++ b/web/src/lib/components/repo/pipelines/pipeline.ts
@@ -75,6 +75,10 @@ export const finishedCount = (pipeline: PipelineSummary): number => {
return counts.success + counts.failed + counts.timeout + counts.cancelled;
};
+/** "2/3" — how many workflows passed, for spots too tight for the breakdown */
+export const shortSummary = (pipeline: PipelineSummary): string =>
+ `${statusCounts(pipeline).success}/${pipeline.workflows.length}`;
+
/** "2/3 passed, 1/3 failed" */
export const longSummary = (pipeline: PipelineSummary): string => {
const counts = statusCounts(pipeline);
diff --git a/web/src/lib/components/ui/Dropdown.svelte b/web/src/lib/components/ui/Dropdown.svelte
index c6b910bd..d82f6f08 100644
--- a/web/src/lib/components/ui/Dropdown.svelte
+++ b/web/src/lib/components/ui/Dropdown.svelte
@@ -63,6 +63,7 @@
menuClass?: string;
trigger: Snippet;
children: Snippet;
+ xOffset?: number;
}
let {
@@ -76,7 +77,8 @@
label,
menuClass,
trigger,
- children
+ children,
+ xOffset
}: Props = $props();
let open = $state(false);
@@ -190,7 +192,7 @@
aria-expanded={open}
aria-controls={menuId}
aria-label={label}
- insetShadow={insetShadow}
+ {insetShadow}
>
{@render trigger()}
@@ -205,6 +207,7 @@
role="menu"
tabindex={-1}
onkeydown={onMenuKeydown}
+ style="transform: translateX({xOffset}px)"
>
{@render children()}