Skip to content

Commit 2f600f0

Browse files
committed
feat: improve code comparison component
1 parent ca67908 commit 2f600f0

File tree

2 files changed

+45
-62
lines changed

2 files changed

+45
-62
lines changed

app/page.tsx

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {ChevronRight} from "lucide-react";
1+
import {ChevronRight, Github, GithubIcon} from "lucide-react";
22
import {buttonVariants} from "@/components/ui/button";
33
import Link from "next/link";
44
import {cn} from "@/lib/utils";
@@ -45,31 +45,36 @@ public class MyPlugin extends PluginBase {
4545
}
4646
return true;
4747
}
48-
48+
4949
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = false)
5050
public void onServerCommand(ServerCommandEvent event) {
5151
this.getLogger().info("ServerCommandEvent is called!");
5252
}
5353
}`;
5454

55-
const afterCode = `from endstone import ColorFormat
55+
const afterCode = `from typing import override
56+
5657
from endstone.command import Command, CommandSender
57-
from endstone.event import EventPriority, ServerCommandEvent, event_handler
58+
from endstone.event import event_handler, EventPriority, ServerCommandEvent
5859
from endstone.plugin import Plugin
60+
from endstone import ColorFormat
5961
6062
6163
class MyPlugin(Plugin):
62-
64+
@override
6365
def on_load(self) -> None:
6466
self.logger.info(ColorFormat.GREEN + "on_load is called!")
6567
68+
@override
6669
def on_enable(self) -> None:
6770
self.logger.info(ColorFormat.DARK_GREEN + "on_enable is called!")
6871
self.register_events(self)
69-
72+
73+
@override
7074
def on_disable(self) -> None:
7175
self.logger.info(ColorFormat.DARK_RED + "on_disable is called!")
72-
76+
77+
@override
7378
def on_command(self, sender: CommandSender, command: Command, args: list[str]) -> bool:
7479
match command.name:
7580
case "example":
@@ -78,18 +83,17 @@ class MyPlugin(Plugin):
7883
7984
return True
8085
81-
@event_handler(priority=EventPriority.NORMAL, ignore_cancelled = False)
86+
@event_handler(priority=EventPriority.NORMAL, ignore_cancelled=False)
8287
def on_server_command(self, event: ServerCommandEvent):
8388
self.logger.info("ServerCommandEvent is called!")
8489
85-
};`;
90+
`;
8691
return (
8792
<div>
8893
<section>
8994
<div className="relative h-full overflow-hidden py-5 md:py-14">
9095
<AnimatedGridPattern maxOpacity={0.1}
9196
duration={3}
92-
repeatDelay={1}
9397
className={cn(
9498
"[mask-image:radial-gradient(500px_circle_at_center,white,transparent)]",
9599
"inset-x-0 inset-y-[-30%] h-[200%] skew-y-12",
@@ -120,7 +124,8 @@ class MyPlugin(Plugin):
120124
"text-5xl sm:text-7xl md:text-7xl lg:text-7xl"
121125
)}
122126
>
123-
The <AnimatedGradientText className="font-semibold tracking-tight">next generation</AnimatedGradientText> of
127+
The <AnimatedGradientText className="font-semibold tracking-tight">next
128+
generation</AnimatedGradientText> of
124129
Nukkit is here.
125130
</h1>
126131
</div>
@@ -133,13 +138,12 @@ class MyPlugin(Plugin):
133138
</p>
134139

135140
<div className="mx-0 flex w-full max-w-full flex-col gap-4 py-1 sm:max-w-lg sm:flex-row md:mx-auto">
136-
<div className="flex w-full flex-col gap-2 sm:flex-row sm:gap-4 md:justify-center
137-
">
138-
<RainbowButton className="
139-
rounded-xl h-11 px-8" asChild>
140-
<Link href="https://github.com/EndstoneMC/endstone">Visit Endstone on Github
141+
<div className="flex w-full flex-col gap-2 sm:flex-row sm:gap-4 md:justify-center">
142+
<RainbowButton className="rounded-xl h-11 px-8 gap-1" asChild>
143+
<Link href="https://github.com/EndstoneMC/endstone">
144+
Visit Endstone on GitHub
141145
<ChevronRight
142-
className="ml-1 size-4 shrink-0 transition-all duration-300 ease-out group-hover:translate-x-1"/>
146+
className="size-4 shrink-0 transition-all duration-300 ease-out group-hover:translate-x-1"/>
143147
</Link>
144148
</RainbowButton>
145149
</div>
@@ -166,8 +170,8 @@ class MyPlugin(Plugin):
166170
afterLanguage="python"
167171
beforeFilename="Plugin.java"
168172
afterFilename="plugin.py"
169-
lightTheme="github-light"
170-
darkTheme="github-dark"
173+
beforeDescription="Nukkit"
174+
afterDescription="Endstone"
171175
highlightColor="rgba(101, 117, 133, 0.16)"
172176
/>
173177
</div>

components/magicui/code-comparison.tsx

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
} from "@shikijs/transformers";
88
import {FileIcon} from "lucide-react";
99
import {useTheme} from "next-themes";
10-
import {useEffect, useState, useMemo} from "react";
10+
import React, {useEffect, useState, useMemo} from "react";
11+
import {Badge} from "@/components/ui/badge";
1112

1213
interface CodeComparisonProps {
1314
beforeCode: string;
@@ -16,8 +17,10 @@ interface CodeComparisonProps {
1617
afterLanguage: string;
1718
beforeFilename: string;
1819
afterFilename: string;
19-
lightTheme: string;
20-
darkTheme: string;
20+
beforeDescription?: string;
21+
afterDescription?: string;
22+
lightTheme?: string;
23+
darkTheme?: string;
2124
highlightColor?: string;
2225
}
2326

@@ -28,28 +31,21 @@ export function CodeComparison({
2831
afterLanguage,
2932
beforeFilename,
3033
afterFilename,
31-
lightTheme,
32-
darkTheme,
34+
beforeDescription = "before",
35+
afterDescription = "after",
36+
lightTheme = "github-light",
37+
darkTheme = "github-dark",
3338
highlightColor = "#ff3333",
3439
}: CodeComparisonProps) {
3540
const {theme, systemTheme} = useTheme();
3641
const [highlightedBefore, setHighlightedBefore] = useState("");
3742
const [highlightedAfter, setHighlightedAfter] = useState("");
38-
const [hasLeftFocus, setHasLeftFocus] = useState(false);
39-
const [hasRightFocus, setHasRightFocus] = useState(false);
4043

4144
const selectedTheme = useMemo(() => {
4245
const currentTheme = theme === "system" ? systemTheme : theme;
4346
return currentTheme === "dark" ? darkTheme : lightTheme;
4447
}, [theme, systemTheme, darkTheme, lightTheme]);
4548

46-
useEffect(() => {
47-
if (highlightedBefore || highlightedAfter) {
48-
setHasLeftFocus(highlightedBefore.includes('class="line focused"'));
49-
setHasRightFocus(highlightedAfter.includes('class="line focused"'));
50-
}
51-
}, [highlightedBefore, highlightedAfter]);
52-
5349
useEffect(() => {
5450
async function highlightCode() {
5551
try {
@@ -95,15 +91,11 @@ export function CodeComparison({
9591
style={{"--highlight-color": highlightColor} as React.CSSProperties}
9692
className={cn(
9793
"h-full w-full overflow-auto bg-background font-mono text-xs",
98-
"[&>pre]:h-full [&>pre]:!w-screen [&>pre]:py-2",
99-
"[&>pre>code]:!inline-block [&>pre>code]:!w-full",
100-
"[&>pre>code>span]:!inline-block [&>pre>code>span]:w-full [&>pre>code>span]:px-4 [&>pre>code>span]:py-0.5",
94+
"[&>pre]:h-full [&>pre]:py-2",
95+
"[&>pre>code]:!inline-block [&>pre>code]:!flex-col",
96+
"[&>pre>code>span]:inline-block [&>pre>code>span]:px-3 [&>pre>code>span]:py-0.5",
10197
"[&>pre>code>.highlighted]:inline-block [&>pre>code>.highlighted]:w-full [&>pre>code>.highlighted]:!bg-[var(--highlight-color)]",
102-
"group-hover/left:[&>pre>code>:not(.focused)]:!opacity-100 group-hover/left:[&>pre>code>:not(.focused)]:!blur-none",
103-
"group-hover/right:[&>pre>code>:not(.focused)]:!opacity-100 group-hover/right:[&>pre>code>:not(.focused)]:!blur-none",
10498
"[&>pre>code>.add]:bg-[rgba(16,185,129,.16)] [&>pre>code>.remove]:bg-[rgba(244,63,94,.16)]",
105-
"group-hover/left:[&>pre>code>:not(.focused)]:transition-all group-hover/left:[&>pre>code>:not(.focused)]:duration-300",
106-
"group-hover/right:[&>pre>code>:not(.focused)]:transition-all group-hover/right:[&>pre>code>:not(.focused)]:duration-300",
10799
)}
108100
dangerouslySetInnerHTML={{__html: highlighted}}
109101
/>
@@ -119,35 +111,22 @@ export function CodeComparison({
119111

120112
return (
121113
<div className="mx-auto w-full max-w-5xl">
122-
<div className="group relative w-full overflow-hidden rounded-md border border-border">
123-
<div className="relative grid md:grid-cols-2">
124-
<div
125-
className={cn(
126-
"leftside group/left border-primary/20 md:border-r",
127-
hasLeftFocus &&
128-
"[&>div>pre>code>:not(.focused)]:!opacity-50 [&>div>pre>code>:not(.focused)]:!blur-[0.095rem]",
129-
"[&>div>pre>code>:not(.focused)]:transition-all [&>div>pre>code>:not(.focused)]:duration-300",
130-
)}
131-
>
132-
<div className="flex items-center border-b border-primary/20 bg-accent p-2 text-sm text-foreground">
114+
<div className="relative w-full overflow-hidden rounded-md border border-border border-primary/20">
115+
<div className="grid grid-cols-1 md:grid-cols-2">
116+
<div className="border-primary/20 md:border-r flex flex-col">
117+
<div className="w-full flex items-center border-b border-primary/20 bg-accent p-2 text-sm text-foreground">
133118
<FileIcon className="mr-2 h-4 w-4"/>
134119
{beforeFilename}
135-
<span className="ml-auto hidden md:block">before</span>
120+
<Badge className="ml-auto rounded-full">{beforeDescription}</Badge>
136121
</div>
137122
{renderCode(beforeCode, highlightedBefore)}
138123
</div>
139-
<div
140-
className={cn(
141-
"rightside group/right border-t border-primary/20 md:border-t-0",
142-
hasRightFocus &&
143-
"[&>div>pre>code>:not(.focused)]:!opacity-50 [&>div>pre>code>:not(.focused)]:!blur-[0.095rem]",
144-
"[&>div>pre>code>:not(.focused)]:transition-all [&>div>pre>code>:not(.focused)]:duration-300",
145-
)}
146-
>
147-
<div className="flex items-center border-b border-primary/20 bg-accent p-2 text-sm text-foreground">
124+
125+
<div className="border-primary/20 border-t md:border-t-0 flex flex-col">
126+
<div className="w-full flex items-center border-b border-primary/20 bg-accent p-2 text-sm text-foreground">
148127
<FileIcon className="mr-2 h-4 w-4"/>
149128
{afterFilename}
150-
<span className="ml-auto hidden md:block">after</span>
129+
<Badge className="ml-auto rounded-full">{afterDescription}</Badge>
151130
</div>
152131
{renderCode(afterCode, highlightedAfter)}
153132
</div>

0 commit comments

Comments
 (0)