Skip to content

Commit 71a783f

Browse files
authored
Add 'fill' prop to Stack Components (#1509)
## Description <!-- Please provide a brief description of the changes made in this pull request. Include any relevant context or reasoning for the changes. --> Add a "fill" prop to InlineStack and BlockStack. And a LoadingScreen component which consumes it. Also propagate the"fill" prop to a few other locations where it's useful. "fill" prop fills all available space and centres content inside of it. ## Related Issue and Pull requests <!-- Link to any related issues using the format #<issue-number> --> ## Type of Change <!-- Please delete options that are not relevant --> - [x] Improvement ## Checklist <!-- Please ensure the following are completed before submitting the PR --> - [ ] I have tested this does not break current pipelines / runs functionality - [ ] I have tested the changes on staging ## Screenshots (if applicable) <!-- Include any screenshots that might help explain the changes or provide visual context --> ## Test Instructions <!-- Detail steps and prerequisites for testing the changes in this PR --> ## Additional Comments <!-- Add any additional context or information that reviewers might need to know regarding this PR -->
1 parent c2959e5 commit 71a783f

File tree

9 files changed

+61
-48
lines changed

9 files changed

+61
-48
lines changed

src/components/Editor/PipelineEditor.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
} from "@/components/shared/ReactFlow";
1212
import { UndoRedo } from "@/components/shared/UndoRedo";
1313
import { BlockStack, InlineStack } from "@/components/ui/layout";
14-
import { Spinner } from "@/components/ui/spinner";
1514
import { AutoSaveProvider } from "@/providers/AutoSaveProvider";
1615
import { ComponentLibraryProvider } from "@/providers/ComponentLibraryProvider";
1716
import { ForcedSearchProvider } from "@/providers/ComponentLibraryProvider/ForcedSearchProvider";
@@ -22,6 +21,7 @@ import {
2221
import { ContextPanelProvider } from "@/providers/ContextPanelProvider";
2322
import { PipelineRunsProvider } from "@/providers/PipelineRunsProvider";
2423

24+
import { LoadingScreen } from "../shared/LoadingScreen";
2525
import { NodesOverlayProvider } from "../shared/ReactFlow/NodesOverlay/NodesOverlayProvider";
2626
import PipelineDetails from "./PipelineDetails";
2727

@@ -47,12 +47,7 @@ const PipelineEditor = () => {
4747

4848
// If the pipeline is loading or the component spec is empty, show a loading spinner
4949
if (isLoading || componentSpec === EMPTY_GRAPH_COMPONENT_SPEC) {
50-
return (
51-
<div className="w-full h-full flex flex-col items-center justify-center">
52-
<Spinner className="mr-2 w-10 h-10" />
53-
<p className="text-secondary-foreground">Loading pipeline...</p>
54-
</div>
55-
);
50+
return <LoadingScreen message="Loading Pipeline" />;
5651
}
5752

5853
return (
@@ -62,9 +57,9 @@ const PipelineEditor = () => {
6257
<ContextPanelProvider defaultContent={<PipelineDetails />}>
6358
<ForcedSearchProvider>
6459
<ComponentLibraryProvider>
65-
<InlineStack className="w-full h-full" align="start">
60+
<InlineStack fill>
6661
<FlowSidebar />
67-
<BlockStack className="flex-1 h-full relative">
62+
<BlockStack fill className="flex-1 relative">
6863
<FlowCanvas {...flowConfig}>
6964
<MiniMap position="bottom-left" pannable />
7065
<FlowControls

src/components/Home/PipelineSection/PipelineSection.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useNavigate } from "@tanstack/react-router";
22
import { type ChangeEvent, useEffect, useState } from "react";
33

4+
import { LoadingScreen } from "@/components/shared/LoadingScreen";
45
import NewPipelineButton from "@/components/shared/NewPipelineButton";
56
import QuickStartCards from "@/components/shared/QuickStart/QuickStartCards";
67
import { withSuspenseWrapper } from "@/components/shared/SuspenseWrapper";
@@ -12,7 +13,6 @@ import { Input } from "@/components/ui/input";
1213
import { Label } from "@/components/ui/label";
1314
import { BlockStack, InlineStack } from "@/components/ui/layout";
1415
import { Skeleton } from "@/components/ui/skeleton";
15-
import { Spinner } from "@/components/ui/spinner";
1616
import {
1717
Table,
1818
TableBody,
@@ -126,11 +126,7 @@ export const PipelineSection = withSuspenseWrapper(() => {
126126
}, []);
127127

128128
if (isLoading) {
129-
return (
130-
<InlineStack gap="2" className="mt-4">
131-
<Spinner /> Loading...
132-
</InlineStack>
133-
);
129+
return <LoadingScreen message="Loading Pipelines" />;
134130
}
135131

136132
if (pipelines.size === 0) {

src/components/PipelineRun/PipelineRunPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ const PipelineRunPage = () => {
3333
return (
3434
<ContextPanelProvider defaultContent={<RunDetails />}>
3535
<ComponentLibraryProvider>
36-
<InlineStack className="w-full h-full" align="start">
37-
<BlockStack className="flex-1 h-full">
36+
<InlineStack fill>
37+
<BlockStack fill className="flex-1">
3838
<FlowCanvas {...flowConfig} readOnly>
3939
<MiniMap position="bottom-left" pannable />
4040
<FlowControls
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { BlockStack } from "@/components/ui/layout";
2+
import { Spinner } from "@/components/ui/spinner";
3+
import { Paragraph } from "@/components/ui/typography";
4+
5+
interface LoadingScreenProps {
6+
message?: string;
7+
}
8+
9+
export const LoadingScreen = ({
10+
message = "Loading content",
11+
}: LoadingScreenProps) => {
12+
return (
13+
<BlockStack fill>
14+
<Spinner size={32} />
15+
<Paragraph tone="subdued" size="sm">
16+
{message}
17+
</Paragraph>
18+
</BlockStack>
19+
);
20+
};

src/components/shared/ReactFlow/FlowCanvas/FlowCanvas.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ const FlowCanvas = ({
947947
const selectionMode = getSelectionMode();
948948

949949
return (
950-
<BlockStack className="h-full w-full">
950+
<BlockStack fill>
951951
<SubgraphBreadcrumbs />
952952
<ReactFlow
953953
{...rest}

src/components/ui/layout.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ interface BlockStackProps
4545
* @default 'div'
4646
*/
4747
as?: StackElement;
48+
/** Fill the container and center content */
49+
fill?: boolean;
4850
/** Additional CSS classes */
4951
className?: string;
5052
}
@@ -55,9 +57,10 @@ export const BlockStack = forwardRef<
5557
>((props, ref) => {
5658
const {
5759
as: Element = "div",
60+
fill = false,
5861
className = "",
59-
align = "start",
60-
inlineAlign = "start",
62+
align = fill ? "center" : "start",
63+
inlineAlign = fill ? "center" : "start",
6164
gap = "0",
6265
children,
6366
...rest
@@ -66,6 +69,7 @@ export const BlockStack = forwardRef<
6669
return (
6770
<Element
6871
className={cn(
72+
{ "h-full w-full": fill },
6973
blockStackVariants({ align, inlineAlign, gap }),
7074
className.split(" "),
7175
)}
@@ -119,6 +123,8 @@ interface InlineStackProps
119123
* @default 'div'
120124
*/
121125
as?: StackElement;
126+
/** Fill the container and center content */
127+
fill?: boolean;
122128
/** Additional CSS classes */
123129
className?: string;
124130
}
@@ -129,7 +135,8 @@ export const InlineStack = forwardRef<
129135
>((props, ref) => {
130136
const {
131137
as: Element = "div",
132-
align = "start",
138+
fill = false,
139+
align = fill ? "center" : "start",
133140
blockAlign = "center",
134141
gap = "0",
135142
wrap = "wrap",
@@ -141,6 +148,7 @@ export const InlineStack = forwardRef<
141148
return (
142149
<Element
143150
className={cn(
151+
{ "h-full w-full": fill },
144152
inlineStackVariants({ align, blockAlign, gap, wrap }),
145153
className,
146154
)}

src/routes/Editor/Editor.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,30 @@ import { ReactFlowProvider } from "@xyflow/react";
55

66
import PipelineEditor from "@/components/Editor/PipelineEditor";
77
import { InfoBox } from "@/components/shared/InfoBox";
8+
import { LoadingScreen } from "@/components/shared/LoadingScreen";
89
import { BlockStack } from "@/components/ui/layout";
9-
import { Text } from "@/components/ui/typography";
10+
import { Paragraph } from "@/components/ui/typography";
1011
import { useLoadComponentSpecFromPath } from "@/hooks/useLoadComponentSpecFromPath";
1112

1213
const Editor = () => {
1314
const { componentSpec, error } = useLoadComponentSpecFromPath();
1415

1516
if (error) {
1617
return (
17-
<BlockStack
18-
align="center"
19-
inlineAlign="center"
20-
gap="4"
21-
className="h-full"
22-
>
18+
<BlockStack fill gap="4">
2319
<InfoBox variant="error" title="Error loading pipeline">
2420
{error}
2521
</InfoBox>
26-
<Text tone="subdued" size="sm">
22+
<Paragraph tone="subdued" size="sm">
2723
Tip: Pipelines are stored locally and are not shareable by URL. To
2824
share a pipeline it needs to be exported.
29-
</Text>
25+
</Paragraph>
3026
</BlockStack>
3127
);
3228
}
3329

3430
if (!componentSpec) {
35-
return <div>Loading...</div>;
31+
return <LoadingScreen message="Loading Pipeline" />;
3632
}
3733

3834
return (

src/routes/PipelineRun/PipelineRun.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,6 @@ describe("<PipelineRun/>", () => {
254254
);
255255

256256
// assert
257-
expect(getByText("Loading Pipeline Run...")).toBeInTheDocument();
257+
expect(getByText("Loading Pipeline Run")).toBeInTheDocument();
258258
});
259259
});

src/routes/PipelineRun/PipelineRun.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { useEffect } from "react";
55

66
import PipelineRunPage from "@/components/PipelineRun";
77
import { InfoBox } from "@/components/shared/InfoBox";
8-
import { Spinner } from "@/components/ui/spinner";
8+
import { LoadingScreen } from "@/components/shared/LoadingScreen";
9+
import { BlockStack } from "@/components/ui/layout";
10+
import { Paragraph } from "@/components/ui/typography";
911
import { faviconManager } from "@/favicon";
1012
import { useDocumentTitle } from "@/hooks/useDocumentTitle";
1113
import { useBackend } from "@/providers/BackendProvider";
@@ -72,52 +74,48 @@ const PipelineRunContent = () => {
7274
});
7375

7476
if (isLoading || !ready) {
75-
return (
76-
<div className="flex items-center justify-center h-full w-full gap-2">
77-
<Spinner /> Loading Pipeline Run...
78-
</div>
79-
);
77+
return <LoadingScreen message="Loading Pipeline Run" />;
8078
}
8179

8280
if (!configured) {
8381
return (
84-
<div className="flex items-center justify-center h-full w-full">
82+
<BlockStack fill>
8583
<InfoBox title="Backend not configured" variant="warning">
8684
Configure a backend to view this pipeline run.
8785
</InfoBox>
88-
</div>
86+
</BlockStack>
8987
);
9088
}
9189

9290
if (!available) {
9391
return (
94-
<div className="flex items-center justify-center h-full w-full">
92+
<BlockStack fill>
9593
<InfoBox title="Backend not available" variant="error">
9694
The configured backend is not available.
9795
</InfoBox>
98-
</div>
96+
</BlockStack>
9997
);
10098
}
10199

102100
if (!componentSpec) {
103101
return (
104-
<div className="flex items-center justify-center h-full w-full">
102+
<BlockStack fill>
105103
<InfoBox title="Error loading pipeline run" variant="error">
106104
No pipeline data available.
107105
</InfoBox>
108-
</div>
106+
</BlockStack>
109107
);
110108
}
111109

112110
if (error) {
113111
const backendStatusString = getBackendStatusString(configured, available);
114112
return (
115-
<div className="flex items-center justify-center h-full w-full gap-2">
113+
<BlockStack fill>
116114
<InfoBox title="Error loading pipeline run" variant="error">
117-
<div className="mb-2">{error.message}</div>
118-
<div className="text-black italic">{backendStatusString}</div>
115+
<Paragraph className="mb-2">{error.message}</Paragraph>
116+
<Paragraph className="italic">{backendStatusString}</Paragraph>
119117
</InfoBox>
120-
</div>
118+
</BlockStack>
121119
);
122120
}
123121

0 commit comments

Comments
 (0)