Skip to content

Commit ffa9f99

Browse files
committed
style: loading and big UI change
1 parent eb47982 commit ffa9f99

File tree

10 files changed

+175
-106
lines changed

10 files changed

+175
-106
lines changed

index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500;700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap">
3939
<!-- Critical CSS -->
4040
<style>
41-
body {
41+
* {
4242
font-family: "Fira Mono", monospace;
4343
}
4444

@@ -56,7 +56,7 @@
5656
</head>
5757

5858
<body>
59-
<div id="root"></div>
59+
<div id="root" class="bg-background"></div>
6060
<script type="module" src="/src/main.tsx"></script>
6161
<noscript>
6262
<div class="no-js-message">

src/App.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ import Editor from "./components/editor/editor";
77
import ButtonsNav from "./components/nav-buttons";
88
import Stats from "./components/editor/stats";
99
import Terminal from "./components/editor/terminal";
10+
import Ripple from "@/components/magicui/ripple";
1011
import {
1112
ResizableHandle,
1213
ResizablePanel,
1314
ResizablePanelGroup
1415
} from "./components/ui/resizable";
1516

16-
import { LoaderCircleIcon } from "lucide-react";
17-
1817
function App() {
1918
const { direction, setCode, initializePyodide, isPyodideLoading } =
2019
useStore();
@@ -36,16 +35,23 @@ function App() {
3635
if (isPyodideLoading) {
3736
return (
3837
<section className="absolute z-[999] flex h-screen w-full flex-col items-center justify-center gap-3 bg-background text-foreground">
39-
<LoaderCircleIcon className="h-32 w-32 animate-spin" />
40-
<h1 className="font-bold">Loading Python Playground</h1>
38+
<div className="relative flex h-full w-full flex-col items-center justify-center overflow-hidden bg-background md:shadow-xl">
39+
<p className="z-10 animate-pulse whitespace-pre-wrap text-center text-2xl font-bold tracking-tighter text-white">
40+
Loading
41+
</p>
42+
<Ripple />
43+
</div>
4144
</section>
4245
);
4346
}
4447

4548
return (
46-
<main className="flex h-screen flex-col">
49+
<main className="flex h-screen flex-col bg-background md:mx-2 md:pb-3">
4750
<ButtonsNav />
48-
<ResizablePanelGroup direction={direction}>
51+
<ResizablePanelGroup
52+
className="border-t border-accent md:rounded-lg md:border"
53+
direction={direction}
54+
>
4955
<ResizablePanel defaultSize={65}>
5056
<Editor />
5157
</ResizablePanel>

src/components/editor/editor.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useStore } from "@/store/useStore";
33
import { useTheme } from "@/hooks/useTheme";
44

55
import MonacoEditor from "@monaco-editor/react";
6-
import { Separator } from "@/components/ui/separator";
76
import Loader from "@/components/loader";
87

98
export default function Editor() {
@@ -33,7 +32,6 @@ export default function Editor() {
3332
fontSize: 14
3433
}}
3534
/>
36-
<Separator />
3735
</div>
3836
);
3937
}

src/components/editor/stats.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default function Stats() {
1919
}, [code]);
2020

2121
return (
22-
<section className="pointer-events-none absolute bottom-3 left-0 right-0 z-[99] flex items-center justify-center">
22+
<section className="pointer-events-none absolute bottom-[22px] left-0 right-0 z-[99] hidden items-center justify-center md:flex">
2323
<div className="rounded bg-secondary px-2 font-mono text-sm text-foreground">
2424
<span>
2525
{stats.lines} Lines, {stats.words} Words, {stats.characters}{" "}

src/components/editor/terminal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export default function Terminal() {
4848
return (
4949
<pre
5050
ref={outputRef}
51-
className="h-full w-full overflow-x-auto bg-background p-4"
51+
className="h-full w-full overflow-x-auto bg-background px-4 py-1"
5252
>
5353
<code
5454
className={`w-full font-mono text-sm ${error ? "text-red-500" : "text-foreground"}`}

src/components/loader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default function Loader({ text }: { text: string }) {
44
return (
55
<div className="flex items-center gap-1 text-foreground">
66
<LoaderCircleIcon className="h-5 w-5 animate-spin" />
7-
<p>{text}</p>
7+
<p className="font-bold">{text}</p>
88
</div>
99
);
1010
}

src/components/magicui/ripple.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, { CSSProperties } from "react";
2+
3+
interface RippleProps {
4+
mainCircleSize?: number;
5+
mainCircleOpacity?: number;
6+
numCircles?: number;
7+
}
8+
9+
const Ripple = React.memo(function Ripple({
10+
mainCircleSize = 210,
11+
mainCircleOpacity = 0.24,
12+
numCircles = 8
13+
}: RippleProps) {
14+
return (
15+
<div className="absolute inset-0 flex items-center justify-center bg-white/5 [mask-image:linear-gradient(to_bottom,white,transparent)]">
16+
{Array.from({ length: numCircles }, (_, i) => {
17+
const size = mainCircleSize + i * 70;
18+
const opacity = mainCircleOpacity - i * 0.03;
19+
const animationDelay = `${i * 0.06}s`;
20+
const borderStyle = i === numCircles - 1 ? "dashed" : "solid";
21+
const borderOpacity = 5 + i * 5;
22+
23+
return (
24+
<div
25+
key={i}
26+
className={`absolute animate-ripple rounded-full border bg-foreground/25 shadow-xl [--i:${i}]`}
27+
style={
28+
{
29+
width: `${size}px`,
30+
height: `${size}px`,
31+
opacity,
32+
animationDelay,
33+
borderStyle,
34+
borderWidth: "1px",
35+
borderColor: `hsl(var(--foreground), ${borderOpacity / 100})`,
36+
top: "50%",
37+
left: "50%",
38+
transform: "translate(-50%, -50%) scale(1)"
39+
} as CSSProperties
40+
}
41+
/>
42+
);
43+
})}
44+
</div>
45+
);
46+
});
47+
48+
Ripple.displayName = "Ripple";
49+
50+
export default Ripple;

src/components/nav-buttons.tsx

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useStore } from "@/store/useStore";
44
import { Button } from "./ui/button";
55
import Settings from "./settings";
66
import ModeToggle from "./theme/mode-toggle";
7-
import { Separator } from "./ui/separator";
87

98
import {
109
ReplaceIcon,
@@ -38,46 +37,43 @@ export default function ButtonsNav() {
3837
}, [runCode, code]);
3938

4039
return (
41-
<>
42-
<section className="flex justify-between gap-2 bg-background p-2">
43-
<div className="flex grow items-center justify-center gap-1">
44-
<Button
45-
disabled={isCodeExecuting}
46-
title="Execute the code"
47-
onClick={handleRunCode}
48-
variant="secondary"
49-
>
50-
{isCodeExecuting ? (
51-
<LoaderCircleIcon className="h-5 w-5 animate-spin" />
52-
) : (
53-
<PlayIcon className="h-5 w-5" />
54-
)}
55-
<span className={`ml-2 ${isCodeExecuting ? "opacity-80" : ""}`}>
56-
Run
57-
</span>
58-
</Button>
59-
<Button
60-
disabled={isCodeExecuting}
61-
title="Clear the terminal"
62-
onClick={handleTerminalClear}
63-
variant="secondary"
64-
>
65-
<TrashIcon className="h-5 w-5" />
66-
<span className="ml-2 hidden md:inline">Clear Terminal</span>
67-
</Button>
68-
<Button
69-
title="Change direction"
70-
variant="secondary"
71-
onClick={handleDirectionChange}
72-
>
73-
<ReplaceIcon className="h-5 w-5" />
74-
<span className="ml-2 hidden md:inline">Direction</span>
75-
</Button>
76-
<Settings />
77-
<ModeToggle />
78-
</div>
79-
</section>
80-
<Separator />
81-
</>
40+
<section className="flex justify-between gap-2 bg-background p-2">
41+
<div className="flex grow items-center justify-center gap-1">
42+
<Button
43+
disabled={isCodeExecuting}
44+
title="Execute the code"
45+
onClick={handleRunCode}
46+
variant="secondary"
47+
>
48+
{isCodeExecuting ? (
49+
<LoaderCircleIcon className="h-5 w-5 animate-spin" />
50+
) : (
51+
<PlayIcon className="h-5 w-5" />
52+
)}
53+
<span className={`ml-2 ${isCodeExecuting ? "opacity-80" : ""}`}>
54+
Run
55+
</span>
56+
</Button>
57+
<Button
58+
disabled={isCodeExecuting}
59+
title="Clear the terminal"
60+
onClick={handleTerminalClear}
61+
variant="secondary"
62+
>
63+
<TrashIcon className="h-5 w-5" />
64+
<span className="ml-2 hidden md:inline">Clear Terminal</span>
65+
</Button>
66+
<Button
67+
title="Change direction"
68+
variant="secondary"
69+
onClick={handleDirectionChange}
70+
>
71+
<ReplaceIcon className="h-5 w-5" />
72+
<span className="ml-2 hidden md:inline">Direction</span>
73+
</Button>
74+
<Settings />
75+
<ModeToggle />
76+
</div>
77+
</section>
8278
);
8379
}

src/globals.css

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,57 @@
55
@layer base {
66
:root {
77
--background: 0 0% 100%;
8-
--foreground: 0 0% 3.9%;
8+
--foreground: 20 14.3% 4.1%;
99
--card: 0 0% 100%;
10-
--card-foreground: 0 0% 3.9%;
10+
--card-foreground: 20 14.3% 4.1%;
1111
--popover: 0 0% 100%;
12-
--popover-foreground: 0 0% 3.9%;
13-
--primary: 0 0% 9%;
14-
--primary-foreground: 0 0% 98%;
15-
--secondary: 0 0% 96.1%;
16-
--secondary-foreground: 0 0% 9%;
17-
--muted: 0 0% 96.1%;
18-
--muted-foreground: 0 0% 45.1%;
19-
--accent: 0 0% 96.1%;
20-
--accent-foreground: 0 0% 9%;
12+
--popover-foreground: 20 14.3% 4.1%;
13+
--primary: 24 9.8% 10%;
14+
--primary-foreground: 60 9.1% 97.8%;
15+
--secondary: 60 4.8% 95.9%;
16+
--secondary-foreground: 24 9.8% 10%;
17+
--muted: 60 4.8% 95.9%;
18+
--muted-foreground: 25 5.3% 44.7%;
19+
--accent: 60 4.8% 95.9%;
20+
--accent-foreground: 24 9.8% 10%;
2121
--destructive: 0 84.2% 60.2%;
22-
--destructive-foreground: 0 0% 98%;
23-
--border: 0 0% 89.8%;
24-
--input: 0 0% 89.8%;
25-
--ring: 0 0% 3.9%;
26-
--radius: 0.3rem;
22+
--destructive-foreground: 60 9.1% 97.8%;
23+
--border: 20 5.9% 90%;
24+
--input: 20 5.9% 90%;
25+
--ring: 20 14.3% 4.1%;
26+
--radius: 0.5rem;
27+
--chart-1: 12 76% 61%;
28+
--chart-2: 173 58% 39%;
29+
--chart-3: 197 37% 24%;
30+
--chart-4: 43 74% 66%;
31+
--chart-5: 27 87% 67%;
2732
}
2833

2934
.dark {
30-
--background: 0 0% 3.9%;
31-
--foreground: 0 0% 98%;
32-
--card: 0 0% 3.9%;
33-
--card-foreground: 0 0% 98%;
34-
--popover: 0 0% 3.9%;
35-
--popover-foreground: 0 0% 98%;
36-
--primary: 0 0% 98%;
37-
--primary-foreground: 0 0% 9%;
38-
--secondary: 0 0% 14.9%;
39-
--secondary-foreground: 0 0% 98%;
40-
--muted: 0 0% 14.9%;
41-
--muted-foreground: 0 0% 63.9%;
42-
--accent: 0 0% 14.9%;
43-
--accent-foreground: 0 0% 98%;
35+
--background: 20 14.3% 4.1%;
36+
--foreground: 60 9.1% 97.8%;
37+
--card: 20 14.3% 4.1%;
38+
--card-foreground: 60 9.1% 97.8%;
39+
--popover: 20 14.3% 4.1%;
40+
--popover-foreground: 60 9.1% 97.8%;
41+
--primary: 60 9.1% 97.8%;
42+
--primary-foreground: 24 9.8% 10%;
43+
--secondary: 12 6.5% 15.1%;
44+
--secondary-foreground: 60 9.1% 97.8%;
45+
--muted: 12 6.5% 15.1%;
46+
--muted-foreground: 24 5.4% 63.9%;
47+
--accent: 12 6.5% 15.1%;
48+
--accent-foreground: 60 9.1% 97.8%;
4449
--destructive: 0 62.8% 30.6%;
45-
--destructive-foreground: 0 0% 98%;
46-
--border: 0 0% 14.9%;
47-
--input: 0 0% 14.9%;
48-
--ring: 0 0% 83.1%;
50+
--destructive-foreground: 60 9.1% 97.8%;
51+
--border: 12 6.5% 15.1%;
52+
--input: 12 6.5% 15.1%;
53+
--ring: 24 5.7% 82.9%;
54+
--chart-1: 220 70% 50%;
55+
--chart-2: 160 60% 45%;
56+
--chart-3: 30 80% 55%;
57+
--chart-4: 280 65% 60%;
58+
--chart-5: 340 75% 55%;
4959
}
5060
}
5161

0 commit comments

Comments
 (0)