Skip to content

Commit 5a4c38f

Browse files
authored
style: enhance terminal loading (#45)
* feat: enhance Terminal component with loading state and styles - Updated Terminal component to include a loading state while the iframe is being rendered. - Added new styles for loading animation and logo in Terminal.scss. - Implemented a delay for iframe rendering to improve user experience during loading. * style: enhance terminal loading user experience - Added a wrapper for the iframe to manage loading states more effectively. - Introduced new CSS classes for loading and loaded states to enhance user experience. - Updated loading animation styles for better visibility and transitions during iframe loading.
1 parent ce3c3b8 commit 5a4c38f

File tree

2 files changed

+114
-6
lines changed

2 files changed

+114
-6
lines changed

src/frontend/src/pad/containers/Terminal.scss

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,81 @@
66
overflow: hidden;
77
}
88

9+
.terminal-iframe-wrapper {
10+
position: relative;
11+
flex: 1;
12+
height: 100%;
13+
width: 100%;
14+
overflow: hidden;
15+
border-bottom-left-radius: var(--embeddable-radius);
16+
border-bottom-right-radius: var(--embeddable-radius);
17+
background-color: #000000;
18+
}
19+
920
.terminal-iframe {
1021
flex: 1;
11-
background-color: #1e1e1e;
22+
background-color: #000000;
1223
height: 100%;
1324
width: 100%;
1425
border: 0px !important;
1526
overflow: hidden;
1627
border-bottom-left-radius: var(--embeddable-radius);
1728
border-bottom-right-radius: var(--embeddable-radius);
29+
30+
&--loading {
31+
display: flex;
32+
align-items: center;
33+
justify-content: center;
34+
position: relative;
35+
}
36+
37+
&--loading-fade {
38+
opacity: 0;
39+
transition: opacity 0.5s ease-in;
40+
}
41+
42+
&--loaded {
43+
opacity: 1;
44+
transition: opacity 0.5s ease-in;
45+
}
46+
}
47+
48+
.terminal-loading-animation {
49+
position: absolute;
50+
width: 100%;
51+
height: 100%;
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
56+
&--fade {
57+
opacity: 1;
58+
transition: opacity 0.15s ease-out;
59+
z-index: 1;
60+
background-color: #000000;
61+
}
62+
63+
&--hidden {
64+
opacity: 0;
65+
pointer-events: none;
66+
}
67+
}
68+
69+
.terminal-loading-logo {
70+
width: 60px;
71+
height: 60px;
72+
object-fit: contain;
73+
animation: terminal-logo-slide 300ms cubic-bezier(0.00, 1.26, 0.64, 0.95) forwards;
74+
position: relative;
75+
}
76+
77+
@keyframes terminal-logo-slide {
78+
from {
79+
transform: translateX(-100px);
80+
opacity: 0;
81+
}
82+
to {
83+
transform: translateX(0);
84+
opacity: 1;
85+
}
1886
}

src/frontend/src/pad/containers/Terminal.tsx

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export const Terminal: React.FC<TerminalProps> = ({
2626
}) => {
2727
const { data: workspaceState } = useWorkspaceState();
2828
const [terminalId, setTerminalId] = useState<string | null>(null);
29+
const [iframeLoaded, setIframeLoaded] = useState(false);
30+
const [shouldRenderIframe, setShouldRenderIframe] = useState(false);
2931
const elementIdRef = useRef(element?.id);
3032
const isInitializedRef = useRef(false);
3133

@@ -172,13 +174,51 @@ export const Terminal: React.FC<TerminalProps> = ({
172174

173175
const terminalUrl = getTerminalUrl();
174176

177+
// Effect to delay loading the iframe
178+
useEffect(() => {
179+
// Set a small timeout to allow the scrolling to complete first
180+
const timer = setTimeout(() => {
181+
setShouldRenderIframe(true);
182+
}, 500);
183+
184+
return () => clearTimeout(timer);
185+
}, []);
186+
187+
// Handle iframe load event
188+
const handleIframeLoad = () => {
189+
setIframeLoaded(true);
190+
console.debug('[pad.ws] Terminal iframe loaded');
191+
};
192+
175193
return (
176194
<div className="terminal-container">
177-
<iframe
178-
className="terminal-iframe"
179-
src={terminalUrl}
180-
title="Terminal"
181-
/>
195+
{shouldRenderIframe ? (
196+
<div className="terminal-iframe-wrapper">
197+
<iframe
198+
className={`terminal-iframe ${iframeLoaded ? 'terminal-iframe--loaded' : 'terminal-iframe--loading-fade'}`}
199+
src={terminalUrl}
200+
title="Terminal"
201+
onLoad={handleIframeLoad}
202+
/>
203+
<div className={`terminal-loading-animation terminal-loading-animation--fade ${iframeLoaded ? 'terminal-loading-animation--hidden' : ''}`}>
204+
<img
205+
src="/assets/images/favicon.png"
206+
alt="pad.ws logo"
207+
className="terminal-loading-logo"
208+
/>
209+
</div>
210+
</div>
211+
) : (
212+
<div className="terminal-iframe terminal-iframe--loading">
213+
<div className="terminal-loading-animation">
214+
<img
215+
src="/assets/images/favicon.png"
216+
alt="pad.ws logo"
217+
className="terminal-loading-logo"
218+
/>
219+
</div>
220+
</div>
221+
)}
182222
</div>
183223
);
184224
};

0 commit comments

Comments
 (0)