mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
feat: enhance accessibility and improve component styles across the application
This commit is contained in:
parent
2302a50484
commit
b456cad3d5
@ -47,8 +47,8 @@ export function NetworkChartClient({
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">{error.message}</p>
|
||||
<p className="text-sm font-medium opacity-40">{t("chart_fetch_error_message")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{error.message}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("chart_fetch_error_message")}</p>
|
||||
</div>
|
||||
<NetworkChartLoading />
|
||||
</>
|
||||
@ -123,12 +123,12 @@ export const NetworkChart = React.memo(function NetworkChart({
|
||||
key={key}
|
||||
data-active={activeChart === key}
|
||||
className={
|
||||
"relative z-30 flex cursor-pointer grow basis-0 flex-col justify-center gap-1 border-b border-neutral-200 dark:border-neutral-800 px-6 py-4 text-left data-[active=true]:bg-muted/50 sm:border-l sm:border-t-0 sm:px-6"
|
||||
"relative z-30 flex grow basis-0 cursor-pointer flex-col justify-center gap-1 border-neutral-200 border-b px-6 py-4 text-left data-[active=true]:bg-muted/50 sm:border-t-0 sm:border-l sm:px-6 dark:border-neutral-800"
|
||||
}
|
||||
onClick={() => handleButtonClick(key)}
|
||||
>
|
||||
<span className="whitespace-nowrap text-xs text-muted-foreground">{key}</span>
|
||||
<span className="text-md font-bold leading-none sm:text-lg">
|
||||
<span className="whitespace-nowrap text-muted-foreground text-xs">{key}</span>
|
||||
<span className="font-bold text-md leading-none sm:text-lg">
|
||||
{chartData[key][chartData[key].length - 1].avg_delay.toFixed(2)}ms
|
||||
</span>
|
||||
</button>
|
||||
@ -269,16 +269,16 @@ export const NetworkChart = React.memo(function NetworkChart({
|
||||
<CardDescription className="text-xs">
|
||||
{chartDataKey.length} {t("ServerMonitorCount")}
|
||||
</CardDescription>
|
||||
<div className="flex items-center mt-0.5 space-x-2">
|
||||
<div className="mt-0.5 flex items-center space-x-2">
|
||||
<Switch id="Peak" checked={isPeakEnabled} onCheckedChange={setIsPeakEnabled} />
|
||||
<Label className="text-xs" htmlFor="Peak">
|
||||
Peak cut
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap w-full">{chartButtons}</div>
|
||||
<div className="flex w-full flex-wrap">{chartButtons}</div>
|
||||
</CardHeader>
|
||||
<CardContent className="pr-2 pl-0 py-4 sm:pt-6 sm:pb-6 sm:pr-6 sm:pl-2">
|
||||
<CardContent className="py-4 pr-2 pl-0 sm:pt-6 sm:pr-6 sm:pb-6 sm:pl-2">
|
||||
<ChartContainer config={chartConfig} className="aspect-auto h-[250px] w-full">
|
||||
<LineChart accessibilityLayer data={processedData} margin={{ left: 12, right: 12 }}>
|
||||
<CartesianGrid vertical={false} />
|
||||
|
@ -64,8 +64,8 @@ export default function ServerDetailChartClient({
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">{error.message}</p>
|
||||
<p className="text-sm font-medium opacity-40">{t("chart_fetch_error_message")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{error.message}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("chart_fetch_error_message")}</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
@ -73,7 +73,7 @@ export default function ServerDetailChartClient({
|
||||
if (!data) return <ServerDetailChartLoading />
|
||||
|
||||
return (
|
||||
<section className="grid md:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-3">
|
||||
<section className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
|
||||
<CpuChart data={data} history={history} />
|
||||
<ProcessChart data={data} history={history} />
|
||||
<DiskChart data={data} history={history} />
|
||||
@ -150,9 +150,9 @@ function CpuChart({
|
||||
<CardContent className="px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-md font-medium">CPU</p>
|
||||
<p className="font-medium text-md">CPU</p>
|
||||
<section className="flex items-center gap-2">
|
||||
<p className="text-xs text-end w-10 font-medium">{cpu.toFixed(0)}%</p>
|
||||
<p className="w-10 text-end font-medium text-xs">{cpu.toFixed(0)}%</p>
|
||||
<AnimatedCircularProgressBar
|
||||
className="size-3 text-[0px]"
|
||||
max={100}
|
||||
@ -273,9 +273,9 @@ function ProcessChart({
|
||||
<CardContent className="px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-md font-medium">{t("Process")}</p>
|
||||
<p className="font-medium text-md">{t("Process")}</p>
|
||||
<section className="flex items-center gap-2">
|
||||
<p className="text-xs text-end w-10 font-medium">{process}</p>
|
||||
<p className="w-10 text-end font-medium text-xs">{process}</p>
|
||||
</section>
|
||||
</div>
|
||||
<ChartContainer config={chartConfig} className="aspect-auto h-[130px] w-full">
|
||||
@ -388,7 +388,7 @@ function MemChart({
|
||||
<div className="flex items-center justify-between">
|
||||
<section className="flex items-center gap-4">
|
||||
<div className="flex flex-col">
|
||||
<p className=" text-xs text-muted-foreground">{t("Mem")}</p>
|
||||
<p className=" text-muted-foreground text-xs">{t("Mem")}</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<AnimatedCircularProgressBar
|
||||
className="size-3 text-[0px]"
|
||||
@ -397,11 +397,11 @@ function MemChart({
|
||||
value={mem}
|
||||
primaryColor="hsl(var(--chart-8))"
|
||||
/>
|
||||
<p className="text-xs font-medium">{mem.toFixed(0)}%</p>
|
||||
<p className="font-medium text-xs">{mem.toFixed(0)}%</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<p className=" text-xs text-muted-foreground">{t("Swap")}</p>
|
||||
<p className=" text-muted-foreground text-xs">{t("Swap")}</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<AnimatedCircularProgressBar
|
||||
className="size-3 text-[0px]"
|
||||
@ -410,15 +410,15 @@ function MemChart({
|
||||
value={swap}
|
||||
primaryColor="hsl(var(--chart-10))"
|
||||
/>
|
||||
<p className="text-xs font-medium">{swap.toFixed(0)}%</p>
|
||||
<p className="font-medium text-xs">{swap.toFixed(0)}%</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="flex flex-col items-end gap-0.5">
|
||||
<div className="flex text-[11px] font-medium items-center gap-2">
|
||||
<div className="flex items-center gap-2 font-medium text-[11px]">
|
||||
{formatBytes(data.status.MemUsed)} / {formatBytes(data.host.MemTotal)}
|
||||
</div>
|
||||
<div className="flex text-[11px] font-medium items-center gap-2">
|
||||
<div className="flex items-center gap-2 font-medium text-[11px]">
|
||||
swap: {formatBytes(data.status.SwapUsed)}
|
||||
</div>
|
||||
</section>
|
||||
@ -542,10 +542,10 @@ function DiskChart({
|
||||
<CardContent className="px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-md font-medium">{t("Disk")}</p>
|
||||
<p className="font-medium text-md">{t("Disk")}</p>
|
||||
<section className="flex flex-col items-end gap-0.5">
|
||||
<section className="flex items-center gap-2">
|
||||
<p className="text-xs text-end w-10 font-medium">{disk.toFixed(0)}%</p>
|
||||
<p className="w-10 text-end font-medium text-xs">{disk.toFixed(0)}%</p>
|
||||
<AnimatedCircularProgressBar
|
||||
className="size-3 text-[0px]"
|
||||
max={100}
|
||||
@ -554,7 +554,7 @@ function DiskChart({
|
||||
primaryColor="hsl(var(--chart-5))"
|
||||
/>
|
||||
</section>
|
||||
<div className="flex text-[11px] font-medium items-center gap-2">
|
||||
<div className="flex items-center gap-2 font-medium text-[11px]">
|
||||
{formatBytes(data.status.DiskUsed)} / {formatBytes(data.host.DiskTotal)}
|
||||
</div>
|
||||
</section>
|
||||
@ -681,18 +681,18 @@ function NetworkChart({
|
||||
<section className="flex flex-col gap-1">
|
||||
<div className="flex items-center">
|
||||
<section className="flex items-center gap-4">
|
||||
<div className="flex flex-col w-20">
|
||||
<p className="text-xs text-muted-foreground">{t("Upload")}</p>
|
||||
<div className="flex w-20 flex-col">
|
||||
<p className="text-muted-foreground text-xs">{t("Upload")}</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-1))]" />
|
||||
<p className="text-xs font-medium">{up.toFixed(2)} M/s</p>
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-1))]" />
|
||||
<p className="font-medium text-xs">{up.toFixed(2)} M/s</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-20">
|
||||
<p className=" text-xs text-muted-foreground">{t("Download")}</p>
|
||||
<div className="flex w-20 flex-col">
|
||||
<p className=" text-muted-foreground text-xs">{t("Download")}</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-4))]" />
|
||||
<p className="text-xs font-medium">{down.toFixed(2)} M/s</p>
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-4))]" />
|
||||
<p className="font-medium text-xs">{down.toFixed(2)} M/s</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -823,18 +823,18 @@ function ConnectChart({
|
||||
<section className="flex flex-col gap-1">
|
||||
<div className="flex items-center">
|
||||
<section className="flex items-center gap-4">
|
||||
<div className="flex flex-col w-12">
|
||||
<p className="text-xs text-muted-foreground">TCP</p>
|
||||
<div className="flex w-12 flex-col">
|
||||
<p className="text-muted-foreground text-xs">TCP</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-1))]" />
|
||||
<p className="text-xs font-medium">{tcp}</p>
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-1))]" />
|
||||
<p className="font-medium text-xs">{tcp}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-12">
|
||||
<p className=" text-xs text-muted-foreground">UDP</p>
|
||||
<div className="flex w-12 flex-col">
|
||||
<p className=" text-muted-foreground text-xs">UDP</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-4))]" />
|
||||
<p className="text-xs font-medium">{udp}</p>
|
||||
<span className="relative inline-flex size-1.5 rounded-full bg-[hsl(var(--chart-4))]" />
|
||||
<p className="font-medium text-xs">{udp}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -55,8 +55,8 @@ export default function ServerDetailClient({
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">{error.message}</p>
|
||||
<p className="text-sm font-medium opacity-40">{t("detail_fetch_error_message")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{error.message}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("detail_fetch_error_message")}</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
@ -89,19 +89,19 @@ export default function ServerDetailClient({
|
||||
<div>
|
||||
<div
|
||||
onClick={linkClick}
|
||||
className="flex flex-none cursor-pointer font-semibold leading-none items-center break-all tracking-tight gap-0.5 text-xl hover:opacity-50 transition-opacity duration-300"
|
||||
className="flex flex-none cursor-pointer items-center gap-0.5 break-all font-semibold text-xl leading-none tracking-tight transition-opacity duration-300 hover:opacity-50"
|
||||
>
|
||||
<BackIcon />
|
||||
{name}
|
||||
</div>
|
||||
<section className="flex flex-wrap gap-2 mt-3">
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<section className="mt-3 flex flex-wrap gap-2">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("status")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("status")}</p>
|
||||
<Badge
|
||||
className={cn(
|
||||
"text-[9px] rounded-[6px] w-fit px-1 py-0 -mt-[0.3px] dark:text-white",
|
||||
"-mt-[0.3px] w-fit rounded-[6px] px-1 py-0 text-[9px] dark:text-white",
|
||||
{
|
||||
" bg-green-800": online,
|
||||
" bg-red-600": !online,
|
||||
@ -113,10 +113,10 @@ export default function ServerDetailClient({
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Uptime")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Uptime")}</p>
|
||||
<div className="text-xs">
|
||||
{" "}
|
||||
{uptime / 86400 >= 1
|
||||
@ -127,62 +127,62 @@ export default function ServerDetailClient({
|
||||
</CardContent>
|
||||
</Card>
|
||||
{version && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Version")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Version")}</p>
|
||||
<div className="text-xs">{version} </div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{arch && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Arch")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Arch")}</p>
|
||||
<div className="text-xs">{arch} </div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Mem")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Mem")}</p>
|
||||
<div className="text-xs">{formatBytes(mem_total)}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Disk")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Disk")}</p>
|
||||
<div className="text-xs">{formatBytes(disk_total)}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{country_code && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Region")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Region")}</p>
|
||||
<section className="flex items-start gap-1">
|
||||
<div className="text-xs text-start">{countries.getName(country_code, "en")}</div>
|
||||
<ServerFlag className="text-[11px] -mt-[1px]" country_code={country_code} />
|
||||
<div className="text-start text-xs">{countries.getName(country_code, "en")}</div>
|
||||
<ServerFlag className="-mt-[1px] text-[11px]" country_code={country_code} />
|
||||
</section>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</section>
|
||||
<section className="flex flex-wrap gap-2 mt-1">
|
||||
<section className="mt-1 flex flex-wrap gap-2">
|
||||
{platform && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("System")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("System")}</p>
|
||||
|
||||
<div className="text-xs">
|
||||
{" "}
|
||||
@ -193,10 +193,10 @@ export default function ServerDetailClient({
|
||||
</Card>
|
||||
)}
|
||||
{cpu_info && cpu_info.length > 0 && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("CPU")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("CPU")}</p>
|
||||
|
||||
<div className="text-xs"> {cpu_info.join(", ")}</div>
|
||||
</section>
|
||||
@ -204,31 +204,31 @@ export default function ServerDetailClient({
|
||||
</Card>
|
||||
)}
|
||||
{gpu_info && gpu_info.length > 0 && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{"GPU"}</p>
|
||||
<p className="text-muted-foreground text-xs">{"GPU"}</p>
|
||||
<div className="text-xs"> {gpu_info.join(", ")}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</section>
|
||||
<section className="flex flex-wrap gap-2 mt-1">
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<section className="mt-1 flex flex-wrap gap-2">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Load")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Load")}</p>
|
||||
<div className="text-xs">
|
||||
{load_1 || "0.00"} / {load_5 || "0.00"} / {load_15 || "0.00"}
|
||||
</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Upload")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Upload")}</p>
|
||||
{net_out_transfer ? (
|
||||
<div className="text-xs"> {formatBytes(net_out_transfer)} </div>
|
||||
) : (
|
||||
@ -237,10 +237,10 @@ export default function ServerDetailClient({
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("Download")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("Download")}</p>
|
||||
{net_in_transfer ? (
|
||||
<div className="text-xs"> {formatBytes(net_in_transfer)} </div>
|
||||
) : (
|
||||
@ -250,11 +250,11 @@ export default function ServerDetailClient({
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
<section className="flex flex-wrap gap-2 mt-1">
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<section className="mt-1 flex flex-wrap gap-2">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("LastActive")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("LastActive")}</p>
|
||||
<div className="text-xs">
|
||||
{last_active_time_string ? last_active_time_string : "N/A"}
|
||||
</div>
|
||||
|
@ -22,92 +22,92 @@ export default function ServerIPInfo({ server_id }: { server_id: number }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="flex flex-wrap gap-2 mb-4">
|
||||
<section className="mb-4 flex flex-wrap gap-2">
|
||||
{data.asn?.autonomous_system_organization && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{"ASN"}</p>
|
||||
<p className="text-muted-foreground text-xs">{"ASN"}</p>
|
||||
<div className="text-xs">{data.asn.autonomous_system_organization}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.asn?.autonomous_system_number && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("asn_number")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("asn_number")}</p>
|
||||
<div className="text-xs">AS{data.asn.autonomous_system_number}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.registered_country?.names.en && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("registered_country")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("registered_country")}</p>
|
||||
<div className="text-xs">{data.city.registered_country?.names.en}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.country?.iso_code && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{"ISO"}</p>
|
||||
<p className="text-muted-foreground text-xs">{"ISO"}</p>
|
||||
<div className="text-xs">{data.city.country?.iso_code}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.city?.names.en && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("city")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("city")}</p>
|
||||
<div className="text-xs">{data.city.city?.names.en}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.location?.longitude && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("longitude")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("longitude")}</p>
|
||||
<div className="text-xs">{data.city.location?.longitude}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.location?.latitude && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("latitude")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("latitude")}</p>
|
||||
<div className="text-xs">{data.city.location?.latitude}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.location?.time_zone && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("time_zone")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("time_zone")}</p>
|
||||
<div className="text-xs">{data.city.location?.time_zone}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{data.city?.postal && (
|
||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||
<Card className="rounded-[10px] border-none bg-transparent shadow-none">
|
||||
<CardContent className="px-1.5 py-1">
|
||||
<section className="flex flex-col items-start gap-0.5">
|
||||
<p className="text-xs text-muted-foreground">{t("postal_code")}</p>
|
||||
<p className="text-muted-foreground text-xs">{t("postal_code")}</p>
|
||||
<div className="text-xs">{data.city.postal?.code}</div>
|
||||
</section>
|
||||
</CardContent>
|
||||
|
@ -13,7 +13,7 @@ export default function ServerGlobal() {
|
||||
if (error)
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">{error.message}</p>
|
||||
<p className="font-medium text-sm opacity-40">{error.message}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -43,7 +43,7 @@ export default function ServerGlobal() {
|
||||
)
|
||||
|
||||
return (
|
||||
<section className="flex flex-col gap-4 mt-[3.2px]">
|
||||
<section className="mt-[3.2px] flex flex-col gap-4">
|
||||
<GlobalInfo countries={countryList} />
|
||||
<div className="w-full overflow-x-auto">
|
||||
<TooltipProvider>
|
||||
|
@ -10,7 +10,7 @@ export default function GlobalInfo({ countries }: GlobalInfoProps) {
|
||||
const t = useTranslations("Global")
|
||||
return (
|
||||
<section className="flex items-center justify-between">
|
||||
<p className="text-sm font-medium opacity-40">
|
||||
<p className="font-medium text-sm opacity-40">
|
||||
{t("Distributions")} {countries.length} {t("Regions")}
|
||||
</p>
|
||||
</section>
|
||||
|
@ -32,13 +32,13 @@ export function InteractiveMap({
|
||||
const path = geoPath().projection(projection)
|
||||
|
||||
return (
|
||||
<div className="relative w-full aspect-[2/1]" onMouseLeave={() => setTooltipData(null)}>
|
||||
<div className="relative aspect-[2/1] w-full" onMouseLeave={() => setTooltipData(null)}>
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox={`0 0 ${width} ${height}`}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-full h-auto"
|
||||
className="h-auto w-full"
|
||||
>
|
||||
<title>Interactive Map</title>
|
||||
<defs>
|
||||
@ -67,8 +67,8 @@ export function InteractiveMap({
|
||||
d={path(feature) || ""}
|
||||
className={
|
||||
isHighlighted
|
||||
? "fill-green-700 hover:fill-green-600 dark:fill-green-900 dark:hover:fill-green-700 transition-all cursor-pointer"
|
||||
: "fill-neutral-200/50 dark:fill-neutral-800 stroke-neutral-300/40 dark:stroke-neutral-700 stroke-[0.5]"
|
||||
? "cursor-pointer fill-green-700 transition-all hover:fill-green-600 dark:fill-green-900 dark:hover:fill-green-700"
|
||||
: "fill-neutral-200/50 stroke-[0.5] stroke-neutral-300/40 dark:fill-neutral-800 dark:stroke-neutral-700"
|
||||
}
|
||||
onMouseEnter={() => {
|
||||
if (!isHighlighted) {
|
||||
@ -140,7 +140,7 @@ export function InteractiveMap({
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={4}
|
||||
className="fill-sky-700 stroke-white hover:fill-sky-600 dark:fill-sky-900 dark:hover:fill-sky-700 transition-all"
|
||||
className="fill-sky-700 stroke-white transition-all hover:fill-sky-600 dark:fill-sky-900 dark:hover:fill-sky-700"
|
||||
/>
|
||||
</g>
|
||||
)
|
||||
|
@ -21,7 +21,7 @@ const MapTooltip = memo(function MapTooltip() {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute hidden lg:block bg-white dark:bg-neutral-800 px-2 py-1 rounded shadow-lg text-sm dark:border dark:border-neutral-700 z-50 tooltip-animate"
|
||||
className="tooltip-animate absolute z-50 hidden rounded bg-white px-2 py-1 text-sm shadow-lg lg:block dark:border dark:border-neutral-700 dark:bg-neutral-800"
|
||||
key={tooltipData.country}
|
||||
style={{
|
||||
left: tooltipData.centroid[0],
|
||||
@ -36,12 +36,12 @@ const MapTooltip = memo(function MapTooltip() {
|
||||
<p className="font-medium">
|
||||
{tooltipData.country === "China" ? "Mainland China" : tooltipData.country}
|
||||
</p>
|
||||
<p className="text-neutral-600 dark:text-neutral-400 font-light text-xs mb-1">
|
||||
<p className="mb-1 font-light text-neutral-600 text-xs dark:text-neutral-400">
|
||||
{tooltipData.count} {t("Servers")}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="border-t dark:border-neutral-700 pt-1"
|
||||
className="border-t pt-1 dark:border-neutral-700"
|
||||
style={{
|
||||
maxHeight: "200px",
|
||||
overflowY: "auto",
|
||||
@ -52,10 +52,10 @@ const MapTooltip = memo(function MapTooltip() {
|
||||
onClick={saveSession}
|
||||
href={`/server/${server.id}`}
|
||||
key={server.name}
|
||||
className="flex items-center gap-1.5 py-0.5 transition-colors text-neutral-500 dark:text-neutral-400 hover:text-black dark:hover:text-white"
|
||||
className="flex items-center gap-1.5 py-0.5 text-neutral-500 transition-colors hover:text-black dark:text-neutral-400 dark:hover:text-white"
|
||||
>
|
||||
<span
|
||||
className={`w-1.5 h-1.5 shrink-0 rounded-full ${
|
||||
className={`h-1.5 w-1.5 shrink-0 rounded-full ${
|
||||
server.status ? "bg-green-500" : "bg-red-500"
|
||||
}`}
|
||||
/>
|
||||
|
@ -56,8 +56,8 @@ const getTagCounts = (servers: any[]) => {
|
||||
}
|
||||
|
||||
const LoadingState = ({ t }: { t: any }) => (
|
||||
<div className="flex flex-col items-center min-h-96 justify-center ">
|
||||
<div className="font-semibold flex items-center gap-2 text-sm">
|
||||
<div className="flex min-h-96 flex-col items-center justify-center ">
|
||||
<div className="flex items-center gap-2 font-semibold text-sm">
|
||||
<Loader visible={true} />
|
||||
{t("connecting")}...
|
||||
</div>
|
||||
@ -66,8 +66,8 @@ const LoadingState = ({ t }: { t: any }) => (
|
||||
|
||||
const ErrorState = ({ error, t }: { error: Error; t: any }) => (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">{error.message}</p>
|
||||
<p className="text-sm font-medium opacity-40">{t("error_message")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{error.message}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("error_message")}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -80,7 +80,7 @@ const ServerList = ({
|
||||
return (
|
||||
<section
|
||||
ref={containerRef}
|
||||
className="flex flex-col gap-2 overflow-x-scroll scrollbar-hidden"
|
||||
className="scrollbar-hidden flex flex-col gap-2 overflow-x-scroll"
|
||||
>
|
||||
{servers.map((serverInfo) => (
|
||||
<ServerCardInline key={serverInfo.id} serverInfo={serverInfo} />
|
||||
@ -171,7 +171,7 @@ export default function ServerListClient() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="flex items-center gap-2 w-full overflow-hidden">
|
||||
<section className="flex w-full items-center gap-2 overflow-hidden">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
@ -180,7 +180,7 @@ export default function ServerListClient() {
|
||||
localStorage.setItem("showMap", String(newShowMap))
|
||||
}}
|
||||
className={cn(
|
||||
"rounded-[50px] flex flex-col items-center gap-0 cursor-pointer bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-100 p-[10px] transition-all inset-shadow-2xs inset-shadow-white/20 ",
|
||||
"inset-shadow-2xs inset-shadow-white/20 flex cursor-pointer flex-col items-center gap-0 rounded-[50px] bg-blue-100 p-[10px] text-blue-600 transition-all dark:bg-blue-900 dark:text-blue-100 ",
|
||||
{
|
||||
"inset-shadow-black/20 bg-blue-600 text-white dark:bg-blue-100 dark:text-blue-600":
|
||||
showMap,
|
||||
@ -197,7 +197,7 @@ export default function ServerListClient() {
|
||||
localStorage.setItem("inline", newInline)
|
||||
}}
|
||||
className={cn(
|
||||
"rounded-[50px] flex flex-col items-center gap-0 cursor-pointer bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-100 p-[10px] transition-all inset-shadow-2xs inset-shadow-white/20 ",
|
||||
"inset-shadow-2xs inset-shadow-white/20 flex cursor-pointer flex-col items-center gap-0 rounded-[50px] bg-blue-100 p-[10px] text-blue-600 transition-all dark:bg-blue-900 dark:text-blue-100 ",
|
||||
{
|
||||
"inset-shadow-black/20 bg-blue-600 text-white dark:bg-blue-100 dark:text-blue-600":
|
||||
inline === "1",
|
||||
|
@ -24,10 +24,10 @@ export default function ServerOverviewClient() {
|
||||
const errorInfo = error as any
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">
|
||||
<p className="font-medium text-sm opacity-40">
|
||||
Error status:{errorInfo?.status} {errorInfo.info?.cause ?? errorInfo?.message}
|
||||
</p>
|
||||
<p className="text-sm font-medium opacity-40">{t("error_message")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("error_message")}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -40,17 +40,17 @@ export default function ServerOverviewClient() {
|
||||
setFilter(false)
|
||||
setStatus("all")
|
||||
}}
|
||||
className={cn("cursor-pointer hover:border-blue-500 transition-all group")}
|
||||
className={cn("group cursor-pointer transition-all hover:border-blue-500")}
|
||||
>
|
||||
<CardContent className="flex h-full items-center px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
<p className="text-sm font-medium md:text-base">{t("p_816-881_Totalservers")}</p>
|
||||
<div className="flex items-center gap-2 min-h-[28px]">
|
||||
<p className="font-medium text-sm md:text-base">{t("p_816-881_Totalservers")}</p>
|
||||
<div className="flex min-h-[28px] items-center gap-2">
|
||||
<span className="relative flex h-2 w-2">
|
||||
<span className="relative inline-flex h-2 w-2 rounded-full bg-blue-500" />
|
||||
</span>
|
||||
{data?.result ? (
|
||||
<div className="text-lg font-semibold">
|
||||
<div className="font-semibold text-lg">
|
||||
<AnimateCountClient count={data?.result.length} />
|
||||
</div>
|
||||
) : (
|
||||
@ -68,22 +68,22 @@ export default function ServerOverviewClient() {
|
||||
setStatus("online")
|
||||
}}
|
||||
className={cn(
|
||||
"cursor-pointer hover:ring-green-500 ring-1 ring-transparent transition-all",
|
||||
"cursor-pointer ring-1 ring-transparent transition-all hover:ring-green-500",
|
||||
{
|
||||
"ring-green-500 ring-2 border-transparent": status === "online",
|
||||
"border-transparent ring-2 ring-green-500": status === "online",
|
||||
},
|
||||
)}
|
||||
>
|
||||
<CardContent className="flex h-full items-center px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
<p className="text-sm font-medium md:text-base">{t("p_1610-1676_Onlineservers")}</p>
|
||||
<div className="flex items-center gap-2 min-h-[28px]">
|
||||
<p className="font-medium text-sm md:text-base">{t("p_1610-1676_Onlineservers")}</p>
|
||||
<div className="flex min-h-[28px] items-center gap-2">
|
||||
<span className="relative flex h-2 w-2">
|
||||
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-500 opacity-75" />
|
||||
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-500" />
|
||||
</span>
|
||||
{data?.result ? (
|
||||
<div className="text-lg font-semibold">
|
||||
<div className="font-semibold text-lg">
|
||||
<AnimateCountClient count={data?.live_servers} />
|
||||
</div>
|
||||
) : (
|
||||
@ -101,22 +101,22 @@ export default function ServerOverviewClient() {
|
||||
setStatus("offline")
|
||||
}}
|
||||
className={cn(
|
||||
"cursor-pointer hover:ring-red-500 ring-1 ring-transparent transition-all",
|
||||
"cursor-pointer ring-1 ring-transparent transition-all hover:ring-red-500",
|
||||
{
|
||||
"ring-red-500 ring-2 border-transparent": status === "offline",
|
||||
"border-transparent ring-2 ring-red-500": status === "offline",
|
||||
},
|
||||
)}
|
||||
>
|
||||
<CardContent className="flex h-full items-center px-6 py-3">
|
||||
<section className="flex flex-col gap-1">
|
||||
<p className="text-sm font-medium md:text-base">{t("p_2532-2599_Offlineservers")}</p>
|
||||
<div className="flex items-center gap-2 min-h-[28px]">
|
||||
<p className="font-medium text-sm md:text-base">{t("p_2532-2599_Offlineservers")}</p>
|
||||
<div className="flex min-h-[28px] items-center gap-2">
|
||||
<span className="relative flex h-2 w-2">
|
||||
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-red-500 opacity-75" />
|
||||
<span className="relative inline-flex h-2 w-2 rounded-full bg-red-500" />
|
||||
</span>
|
||||
{data?.result ? (
|
||||
<div className="text-lg font-semibold">
|
||||
<div className="font-semibold text-lg">
|
||||
<AnimateCountClient count={data?.offline_servers} />
|
||||
</div>
|
||||
) : (
|
||||
@ -134,34 +134,34 @@ export default function ServerOverviewClient() {
|
||||
setFilter(true)
|
||||
}}
|
||||
className={cn(
|
||||
"cursor-pointer hover:ring-purple-500 ring-1 ring-transparent transition-all group",
|
||||
"group cursor-pointer ring-1 ring-transparent transition-all hover:ring-purple-500",
|
||||
{
|
||||
"ring-purple-500 ring-2 border-transparent": filter === true,
|
||||
"border-transparent ring-2 ring-purple-500": filter === true,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<CardContent className="flex h-full items-center relative px-6 py-3">
|
||||
<section className="flex flex-col gap-1 w-full">
|
||||
<div className="flex items-center w-full justify-between">
|
||||
<p className="text-sm font-medium md:text-base">{t("network")}</p>
|
||||
<CardContent className="relative flex h-full items-center px-6 py-3">
|
||||
<section className="flex w-full flex-col gap-1">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<p className="font-medium text-sm md:text-base">{t("network")}</p>
|
||||
</div>
|
||||
{data?.result ? (
|
||||
<>
|
||||
<section className="flex flex-row flex-wrap items-start pr-0 gap-1">
|
||||
<p className="text-[12px] text-blue-800 dark:text-blue-400 text-nowrap font-medium">
|
||||
<section className="flex flex-row flex-wrap items-start gap-1 pr-0">
|
||||
<p className="text-nowrap font-medium text-[12px] text-blue-800 dark:text-blue-400">
|
||||
↑{formatBytes(data?.total_out_bandwidth)}
|
||||
</p>
|
||||
<p className="text-[12px] text-purple-800 dark:text-purple-400 text-nowrap font-medium">
|
||||
<p className="text-nowrap font-medium text-[12px] text-purple-800 dark:text-purple-400">
|
||||
↓{formatBytes(data?.total_in_bandwidth)}
|
||||
</p>
|
||||
</section>
|
||||
<section className="flex flex-row flex-wrap -mr-1 sm:items-center items-start gap-1">
|
||||
<p className="text-[11px] flex items-center text-nowrap font-semibold">
|
||||
<ArrowUpCircleIcon className="size-3 mr-0.5 sm:mb-[1px]" />
|
||||
<section className="-mr-1 flex flex-row flex-wrap items-start gap-1 sm:items-center">
|
||||
<p className="flex items-center text-nowrap font-semibold text-[11px]">
|
||||
<ArrowUpCircleIcon className="mr-0.5 size-3 sm:mb-[1px]" />
|
||||
{formatBytes(data?.total_out_speed)}/s
|
||||
</p>
|
||||
<p className="text-[11px] flex items-center text-nowrap font-semibold">
|
||||
<ArrowDownCircleIcon className="size-3 mr-0.5" />
|
||||
<p className="flex items-center text-nowrap font-semibold text-[11px]">
|
||||
<ArrowDownCircleIcon className="mr-0.5 size-3" />
|
||||
{formatBytes(data?.total_in_speed)}/s
|
||||
</p>
|
||||
</section>
|
||||
@ -174,7 +174,7 @@ export default function ServerOverviewClient() {
|
||||
</section>
|
||||
{!disableCartoon && (
|
||||
<Image
|
||||
className="absolute right-3 top-[-85px] z-50 w-20 scale-90 group-hover:opacity-50 md:scale-100 transition-all"
|
||||
className="absolute top-[-85px] right-3 z-50 w-20 scale-90 transition-all group-hover:opacity-50 md:scale-100"
|
||||
alt={"Hamster1963"}
|
||||
src={blogMan}
|
||||
priority
|
||||
@ -186,7 +186,7 @@ export default function ServerOverviewClient() {
|
||||
</section>
|
||||
{data?.result === undefined && !isLoading && (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-medium opacity-40">{t("error_message")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("error_message")}</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
@ -15,7 +15,7 @@ const FooterLink = ({ href, children }: LinkProps) => (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
className="cursor-pointer font-normal underline decoration-yellow-500 hover:decoration-yellow-600 transition-colors decoration-2 underline-offset-2 dark:decoration-yellow-500/60 dark:hover:decoration-yellow-500/80"
|
||||
className="cursor-pointer font-normal underline decoration-2 decoration-yellow-500 underline-offset-2 transition-colors hover:decoration-yellow-600 dark:decoration-yellow-500/60 dark:hover:decoration-yellow-500/80"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{children}
|
||||
@ -36,7 +36,7 @@ export default function Footer() {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<footer className="mx-auto w-full max-w-5xl flex items-center justify-between">
|
||||
<footer className="mx-auto flex w-full max-w-5xl items-center justify-between">
|
||||
<section className="flex flex-col">
|
||||
<p className={`mt-3 flex gap-1 ${baseTextStyles}`}>
|
||||
{t("p_146-598_Findthecodeon")}{" "}
|
||||
@ -49,7 +49,7 @@ export default function Footer() {
|
||||
</section>
|
||||
</section>
|
||||
<p className={`mt-1 ${baseTextStyles}`}>
|
||||
<kbd className="pointer-events-none mx-1 inline-flex h-4 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
|
||||
<kbd className="pointer-events-none mx-1 inline-flex h-4 select-none items-center gap-1 rounded border bg-muted px-1.5 font-medium font-mono text-[10px] text-muted-foreground opacity-100">
|
||||
{isMac ? <span className="text-xs">⌘</span> : "Ctrl "}K
|
||||
</kbd>
|
||||
</p>
|
||||
|
@ -59,7 +59,7 @@ const Links = memo(function Links() {
|
||||
href={link.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-1 text-sm font-medium opacity-50 transition-opacity hover:opacity-100"
|
||||
className="flex items-center gap-1 font-medium text-sm opacity-50 transition-opacity hover:opacity-100"
|
||||
>
|
||||
{link.name}
|
||||
</a>
|
||||
@ -74,15 +74,15 @@ const Overview = memo(function Overview() {
|
||||
|
||||
return (
|
||||
<section className={"mt-10 flex flex-col md:mt-16"}>
|
||||
<p className="text-base font-semibold">{t("p_2277-2331_Overview")}</p>
|
||||
<p className="font-semibold text-base">{t("p_2277-2331_Overview")}</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<p className="text-sm font-medium opacity-50">{t("p_2390-2457_wherethetimeis")}</p>
|
||||
<div className="flex items-center text-sm font-medium">
|
||||
<p className="font-medium text-sm opacity-50">{t("p_2390-2457_wherethetimeis")}</p>
|
||||
<div className="flex items-center font-medium text-sm">
|
||||
<AnimateCountClient count={time.hh} minDigits={2} />
|
||||
<span className="text-sm mb-[1px] font-medium opacity-50">:</span>
|
||||
<span className="mb-[1px] font-medium text-sm opacity-50">:</span>
|
||||
<AnimateCountClient count={time.mm} minDigits={2} />
|
||||
<span className="text-sm mb-[1px] font-medium opacity-50">:</span>
|
||||
<span className="text-sm font-medium">{time.ss.toString().padStart(2, "0")}</span>
|
||||
<span className="mb-[1px] font-medium text-sm opacity-50">:</span>
|
||||
<span className="font-medium text-sm">{time.ss.toString().padStart(2, "0")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -107,7 +107,7 @@ function Header() {
|
||||
<section className="flex items-center justify-between">
|
||||
<section
|
||||
onClick={handleLogoClick}
|
||||
className="flex cursor-pointer items-center text-base font-medium hover:opacity-50 transition-opacity duration-300"
|
||||
className="flex cursor-pointer items-center font-medium text-base transition-opacity duration-300 hover:opacity-50"
|
||||
>
|
||||
<div className="mr-1 flex flex-row items-center justify-start">
|
||||
<img
|
||||
@ -115,19 +115,19 @@ function Header() {
|
||||
height={40}
|
||||
alt="apple-touch-icon"
|
||||
src={customLogo ? customLogo : "/apple-touch-icon.png"}
|
||||
className="relative m-0! border-2 border-transparent h-6 w-6 object-cover object-top p-0! dark:hidden"
|
||||
className="relative m-0! h-6 w-6 border-2 border-transparent object-cover object-top p-0! dark:hidden"
|
||||
/>
|
||||
<img
|
||||
width={40}
|
||||
height={40}
|
||||
alt="apple-touch-icon"
|
||||
src={customLogo ? customLogo : "/apple-touch-icon-dark.png"}
|
||||
className="relative m-0! border-2 border-transparent h-6 w-6 object-cover object-top p-0! hidden dark:block"
|
||||
className="relative m-0! hidden h-6 w-6 border-2 border-transparent object-cover object-top p-0! dark:block"
|
||||
/>
|
||||
</div>
|
||||
{customTitle ? customTitle : "NezhaDash"}
|
||||
<Separator orientation="vertical" className="mx-2 hidden h-4 w-[1px] md:block" />
|
||||
<p className="hidden text-sm font-medium opacity-40 md:block">
|
||||
<p className="hidden font-medium text-sm opacity-40 md:block">
|
||||
{customDescription ? customDescription : t("p_1079-1199_Simpleandbeautifuldashbo")}
|
||||
</p>
|
||||
</section>
|
||||
@ -139,7 +139,7 @@ function Header() {
|
||||
<ModeToggle />
|
||||
</section>
|
||||
</section>
|
||||
<div className="w-full flex justify-end sm:hidden mt-1">
|
||||
<div className="mt-1 flex w-full justify-end sm:hidden">
|
||||
<Links />
|
||||
</div>
|
||||
<Overview />
|
||||
|
@ -35,9 +35,9 @@ export default function Page({ params }: PageProps) {
|
||||
<main className="mx-auto grid w-full max-w-5xl gap-2">
|
||||
<ServerDetailClient server_id={serverId} />
|
||||
|
||||
<nav className="flex items-center my-2 w-full">
|
||||
<nav className="my-2 flex w-full items-center">
|
||||
<Separator className="flex-1" />
|
||||
<div className="flex justify-center w-full max-w-[200px]">
|
||||
<div className="flex w-full max-w-[200px] justify-center">
|
||||
<TabSwitch
|
||||
tabs={tabs}
|
||||
currentTab={currentTab}
|
||||
|
@ -9,10 +9,10 @@ export default function NotFoundPage() {
|
||||
<div className="flex min-h-screen w-full flex-col">
|
||||
<main className="flex min-h-[calc(100vh-calc(var(--spacing)*16))] flex-1 flex-col gap-4 bg-background p-4 md:p-10 md:pt-8">
|
||||
<Header />
|
||||
<section className="flex flex-col items-center flex-1 justify-center gap-2">
|
||||
<p className="text-sm font-semibold">{t("h1_490-590_404NotFound")}</p>
|
||||
<section className="flex flex-1 flex-col items-center justify-center gap-2">
|
||||
<p className="font-semibold text-sm">{t("h1_490-590_404NotFound")}</p>
|
||||
<Link href="/" className="flex items-center gap-1">
|
||||
<p className="text-sm font-medium opacity-40">{t("h1_490-590_404NotFoundBack")}</p>
|
||||
<p className="font-medium text-sm opacity-40">{t("h1_490-590_404NotFoundBack")}</p>
|
||||
</Link>
|
||||
</section>
|
||||
<Footer />
|
||||
|
@ -17,6 +17,9 @@
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"nursery": {
|
||||
"useSortedClasses": "error"
|
||||
},
|
||||
"a11y": {
|
||||
"useKeyWithClickEvents": "off"
|
||||
},
|
||||
|
@ -65,7 +65,7 @@ export function AnimateCount({
|
||||
return (
|
||||
<div
|
||||
key={`${index}-${digit}`}
|
||||
className={cn("relative h-full flex items-center min-w-[0.6em] text-center", {
|
||||
className={cn("relative flex h-full min-w-[0.6em] items-center text-center", {
|
||||
"min-w-[0.2em]": digit === ".",
|
||||
})}
|
||||
>
|
||||
|
@ -103,9 +103,9 @@ export function DashCommand() {
|
||||
}}
|
||||
>
|
||||
{server.online_status ? (
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-green-500 self-center" />
|
||||
<span className="h-2 w-2 shrink-0 self-center rounded-full bg-green-500" />
|
||||
) : (
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-red-500 self-center" />
|
||||
<span className="h-2 w-2 shrink-0 self-center rounded-full bg-red-500" />
|
||||
)}
|
||||
<span>{server.name}</span>
|
||||
</CommandItem>
|
||||
|
@ -27,7 +27,7 @@ export function LanguageSwitcher() {
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-full px-[9px] bg-white dark:bg-black cursor-pointer hover:bg-accent/50 dark:hover:bg-accent/50"
|
||||
className="cursor-pointer rounded-full bg-white px-[9px] hover:bg-accent/50 dark:bg-black dark:hover:bg-accent/50"
|
||||
>
|
||||
<LanguageIcon className="size-4" />
|
||||
<span className="sr-only">Change language</span>
|
||||
@ -40,7 +40,7 @@ export function LanguageSwitcher() {
|
||||
onSelect={(e) => handleSelect(e, item.code)}
|
||||
className={cn(
|
||||
{
|
||||
"bg-muted gap-3 font-semibold": locale === item.code,
|
||||
"gap-3 bg-muted font-semibold": locale === item.code,
|
||||
},
|
||||
{
|
||||
"rounded-t-[5px]": index === localeItems.length - 1,
|
||||
|
@ -30,7 +30,7 @@ export default function ServerCard({
|
||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||
<Card
|
||||
className={cn(
|
||||
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 cursor-pointer hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md",
|
||||
"flex cursor-pointer flex-col items-center justify-start gap-3 p-3 hover:border-stone-300 hover:shadow-md md:px-5 dark:hover:border-stone-700",
|
||||
{
|
||||
"flex-col": fixedTopServerName,
|
||||
"lg:flex-row": !fixedTopServerName,
|
||||
@ -43,7 +43,7 @@ export default function ServerCard({
|
||||
})}
|
||||
style={{ gridTemplateColumns: "auto auto 1fr" }}
|
||||
>
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-green-500 self-center" />
|
||||
<span className="h-2 w-2 shrink-0 self-center rounded-full bg-green-500" />
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-center",
|
||||
@ -70,8 +70,8 @@ export default function ServerCard({
|
||||
})}
|
||||
>
|
||||
{fixedTopServerName && (
|
||||
<div className={"hidden col-span-1 items-center lg:flex lg:flex-row gap-2"}>
|
||||
<div className="text-xs font-semibold">
|
||||
<div className={"col-span-1 hidden items-center gap-2 lg:flex lg:flex-row"}>
|
||||
<div className="font-semibold text-xs">
|
||||
{host.Platform.includes("Windows") ? (
|
||||
<MageMicrosoftWindows className="size-[10px]" />
|
||||
) : (
|
||||
@ -79,37 +79,37 @@ export default function ServerCard({
|
||||
)}
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("System")}</p>
|
||||
<div className="flex items-center text-[10.5px] font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("System")}</p>
|
||||
<div className="flex items-center font-semibold text-[10.5px]">
|
||||
{host.Platform.includes("Windows") ? "Windows" : GetOsName(host.Platform)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("CPU")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">{cpu.toFixed(2)}%</div>
|
||||
<p className="text-muted-foreground text-xs">{t("CPU")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">{cpu.toFixed(2)}%</div>
|
||||
<ServerUsageBar value={cpu} />
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Mem")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">{mem.toFixed(2)}%</div>
|
||||
<p className="text-muted-foreground text-xs">{t("Mem")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">{mem.toFixed(2)}%</div>
|
||||
<ServerUsageBar value={mem} />
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("STG")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">{stg.toFixed(2)}%</div>
|
||||
<p className="text-muted-foreground text-xs">{t("STG")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">{stg.toFixed(2)}%</div>
|
||||
<ServerUsageBar value={stg} />
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Upload")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("Upload")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{up >= 1024 ? `${(up / 1024).toFixed(2)}G/s` : `${up.toFixed(2)}M/s`}
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Download")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("Download")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{down >= 1024 ? `${(down / 1024).toFixed(2)}G/s` : `${down.toFixed(2)}M/s`}
|
||||
</div>
|
||||
</div>
|
||||
@ -118,13 +118,13 @@ export default function ServerCard({
|
||||
<section className={"flex items-center justify-between gap-1"}>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="items-center flex-1 justify-center rounded-[8px] text-nowrap text-[11px] border-muted-50 shadow-md shadow-neutral-200/30 dark:shadow-none"
|
||||
className="flex-1 items-center justify-center text-nowrap rounded-[8px] border-muted-50 text-[11px] shadow-md shadow-neutral-200/30 dark:shadow-none"
|
||||
>
|
||||
{t("Upload")}:{formatBytes(serverInfo.status.NetOutTransfer)}
|
||||
</Badge>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="items-center flex-1 justify-center rounded-[8px] text-nowrap text-[11px] shadow-md shadow-neutral-200/30 dark:shadow-none"
|
||||
className="flex-1 items-center justify-center text-nowrap rounded-[8px] text-[11px] shadow-md shadow-neutral-200/30 dark:shadow-none"
|
||||
>
|
||||
{t("Download")}:{formatBytes(serverInfo.status.NetInTransfer)}
|
||||
</Badge>
|
||||
@ -137,8 +137,8 @@ export default function ServerCard({
|
||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||
<Card
|
||||
className={cn(
|
||||
"flex flex-col items-center justify-start gap-3 p-3 md:px-5 cursor-pointer hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md",
|
||||
showNetTransfer ? "lg:min-h-[91px] min-h-[123px]" : "lg:min-h-[61px] min-h-[93px]",
|
||||
"flex cursor-pointer flex-col items-center justify-start gap-3 p-3 hover:border-stone-300 hover:shadow-md md:px-5 dark:hover:border-stone-700",
|
||||
showNetTransfer ? "min-h-[123px] lg:min-h-[91px]" : "min-h-[93px] lg:min-h-[61px]",
|
||||
{
|
||||
"flex-col": fixedTopServerName,
|
||||
"lg:flex-row": !fixedTopServerName,
|
||||
@ -151,7 +151,7 @@ export default function ServerCard({
|
||||
})}
|
||||
style={{ gridTemplateColumns: "auto auto 1fr" }}
|
||||
>
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-red-500 self-center" />
|
||||
<span className="h-2 w-2 shrink-0 self-center rounded-full bg-red-500" />
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-center",
|
||||
|
@ -29,14 +29,14 @@ export default function ServerCardInline({
|
||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||
<Card
|
||||
className={cn(
|
||||
"flex items-center lg:flex-row justify-start gap-3 p-3 md:px-5 cursor-pointer hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md min-w-[900px] w-full",
|
||||
"flex w-full min-w-[900px] cursor-pointer items-center justify-start gap-3 p-3 hover:border-stone-300 hover:shadow-md md:px-5 lg:flex-row dark:hover:border-stone-700",
|
||||
)}
|
||||
>
|
||||
<section
|
||||
className={cn("grid items-center gap-2 lg:w-36")}
|
||||
style={{ gridTemplateColumns: "auto auto 1fr" }}
|
||||
>
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-green-500 self-center" />
|
||||
<span className="h-2 w-2 shrink-0 self-center rounded-full bg-green-500" />
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-center",
|
||||
@ -56,11 +56,11 @@ export default function ServerCardInline({
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<Separator orientation="vertical" className="h-8 mx-0 ml-2" />
|
||||
<Separator orientation="vertical" className="mx-0 ml-2 h-8" />
|
||||
<div className="flex flex-col gap-2">
|
||||
<section className={cn("grid grid-cols-9 items-center gap-3 flex-1")}>
|
||||
<div className={"items-center flex flex-row gap-2 whitespace-nowrap"}>
|
||||
<div className="text-xs font-semibold">
|
||||
<section className={cn("grid flex-1 grid-cols-9 items-center gap-3")}>
|
||||
<div className={"flex flex-row items-center gap-2 whitespace-nowrap"}>
|
||||
<div className="font-semibold text-xs">
|
||||
{host.Platform.includes("Windows") ? (
|
||||
<MageMicrosoftWindows className="size-[10px]" />
|
||||
) : (
|
||||
@ -68,54 +68,54 @@ export default function ServerCardInline({
|
||||
)}
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("System")}</p>
|
||||
<div className="flex items-center text-[10.5px] font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("System")}</p>
|
||||
<div className="flex items-center font-semibold text-[10.5px]">
|
||||
{host.Platform.includes("Windows") ? "Windows" : GetOsName(host.Platform)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex w-20 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Uptime")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("Uptime")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{(serverInfo?.status.Uptime / 86400).toFixed(0)} {"Days"}
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("CPU")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">{cpu.toFixed(2)}%</div>
|
||||
<p className="text-muted-foreground text-xs">{t("CPU")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">{cpu.toFixed(2)}%</div>
|
||||
<ServerUsageBar value={cpu} />
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Mem")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">{mem.toFixed(2)}%</div>
|
||||
<p className="text-muted-foreground text-xs">{t("Mem")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">{mem.toFixed(2)}%</div>
|
||||
<ServerUsageBar value={mem} />
|
||||
</div>
|
||||
<div className={"flex w-14 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("STG")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">{stg.toFixed(2)}%</div>
|
||||
<p className="text-muted-foreground text-xs">{t("STG")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">{stg.toFixed(2)}%</div>
|
||||
<ServerUsageBar value={stg} />
|
||||
</div>
|
||||
<div className={"flex w-16 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Upload")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("Upload")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{up >= 1024 ? `${(up / 1024).toFixed(2)}G/s` : `${up.toFixed(2)}M/s`}
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex w-16 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("Download")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("Download")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{down >= 1024 ? `${(down / 1024).toFixed(2)}G/s` : `${down.toFixed(2)}M/s`}
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex w-20 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("TotalUpload")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("TotalUpload")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{formatBytes(serverInfo.status.NetOutTransfer)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex w-20 flex-col"}>
|
||||
<p className="text-xs text-muted-foreground">{t("TotalDownload")}</p>
|
||||
<div className="flex items-center text-xs font-semibold">
|
||||
<p className="text-muted-foreground text-xs">{t("TotalDownload")}</p>
|
||||
<div className="flex items-center font-semibold text-xs">
|
||||
{formatBytes(serverInfo.status.NetInTransfer)}
|
||||
</div>
|
||||
</div>
|
||||
@ -127,14 +127,14 @@ export default function ServerCardInline({
|
||||
<Link onClick={saveSession} href={`/server/${id}`} prefetch={true}>
|
||||
<Card
|
||||
className={cn(
|
||||
"flex items-center justify-start gap-3 p-3 md:px-5 hover:border-stone-300 dark:hover:border-stone-700 hover:shadow-md min-h-[61px] min-w-[900px] flex-row",
|
||||
"flex min-h-[61px] min-w-[900px] flex-row items-center justify-start gap-3 p-3 hover:border-stone-300 hover:shadow-md md:px-5 dark:hover:border-stone-700",
|
||||
)}
|
||||
>
|
||||
<section
|
||||
className={cn("grid items-center gap-2 lg:w-40")}
|
||||
style={{ gridTemplateColumns: "auto auto 1fr" }}
|
||||
>
|
||||
<span className="h-2 w-2 shrink-0 rounded-full bg-red-500 self-center" />
|
||||
<span className="h-2 w-2 shrink-0 self-center rounded-full bg-red-500" />
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-center",
|
||||
|
@ -49,26 +49,26 @@ export function SignIn() {
|
||||
}
|
||||
return (
|
||||
<form
|
||||
className="flex flex-col flex-1 items-center justify-center gap-4 p-4 "
|
||||
className="flex flex-1 flex-col items-center justify-center gap-4 p-4 "
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||
<section className="flex flex-col items-start gap-2">
|
||||
<label className="flex flex-col items-start gap-1 ">
|
||||
{errorState && <p className="text-red-500 text-sm font-semibold">{t("ErrorMessage")}</p>}
|
||||
{errorState && <p className="font-semibold text-red-500 text-sm">{t("ErrorMessage")}</p>}
|
||||
{successState && (
|
||||
<p className="text-green-500 text-sm font-semibold">{t("SuccessMessage")}</p>
|
||||
<p className="font-semibold text-green-500 text-sm">{t("SuccessMessage")}</p>
|
||||
)}
|
||||
<p className="text-base font-semibold">{t("SignInMessage")}</p>
|
||||
<p className="font-semibold text-base">{t("SignInMessage")}</p>
|
||||
<input
|
||||
className="px-1 border-[1px] rounded-[5px] border-stone-300 dark:border-stone-800"
|
||||
className="rounded-[5px] border-[1px] border-stone-300 px-1 dark:border-stone-800"
|
||||
name="password"
|
||||
type="password"
|
||||
/>
|
||||
</label>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-1.5 py-0.5 w-fit flex items-center gap-1 text-sm font-semibold border-stone-300 dark:border-stone-800 rounded-[8px] border bg-card hover:brightness-95 transition-all text-card-foreground shadow-lg shadow-neutral-200/40 dark:shadow-none"
|
||||
className="flex w-fit items-center gap-1 rounded-[8px] border border-stone-300 bg-card px-1.5 py-0.5 font-semibold text-card-foreground text-sm shadow-lg shadow-neutral-200/40 transition-all hover:brightness-95 dark:border-stone-800 dark:shadow-none"
|
||||
disabled={loading}
|
||||
>
|
||||
{t("Submit")}
|
||||
|
@ -86,7 +86,7 @@ export default function Switch({
|
||||
<div className="relative flex items-center gap-1 rounded-[50px] bg-stone-100 p-[3px] dark:bg-stone-800">
|
||||
{indicator.w > 0 && (
|
||||
<div
|
||||
className="absolute top-[3px] left-0 z-10 h-[35px] bg-white shadow-lg shadow-black/5 dark:bg-stone-700 dark:shadow-white/5"
|
||||
className="absolute top-[3px] left-0 z-10 h-[35px] bg-white shadow-black/5 shadow-lg dark:bg-stone-700 dark:shadow-white/5"
|
||||
style={{
|
||||
borderRadius: 24,
|
||||
width: `${indicator.w}px`,
|
||||
@ -104,18 +104,18 @@ export default function Switch({
|
||||
sessionStorage.setItem("selectedTag", tag)
|
||||
}}
|
||||
className={cn(
|
||||
"relative cursor-pointer rounded-3xl px-2.5 py-[8px] text-[13px] font-[600]",
|
||||
"transition-all duration-500 ease-in-out text-stone-400 dark:text-stone-500 hover:text-stone-950 hover:dark:text-stone-50",
|
||||
"relative cursor-pointer rounded-3xl px-2.5 py-[8px] font-[600] text-[13px]",
|
||||
"text-stone-400 transition-all duration-500 ease-in-out hover:text-stone-950 dark:text-stone-500 hover:dark:text-stone-50",
|
||||
{
|
||||
"text-stone-950 dark:text-stone-50": nowTag === tag,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<div className="relative z-20 flex items-center gap-1">
|
||||
<div className="whitespace-nowrap flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 whitespace-nowrap">
|
||||
{tag === "defaultTag" ? t("defaultTag") : tag}{" "}
|
||||
{getEnv("NEXT_PUBLIC_ShowTagCount") === "true" && tag !== "defaultTag" && (
|
||||
<div className="w-fit px-1.5 rounded-full bg-muted">{tagCountMap[tag]}</div>
|
||||
<div className="w-fit rounded-full bg-muted px-1.5">{tagCountMap[tag]}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -40,7 +40,7 @@ export default function TabSwitch({
|
||||
<div className="relative flex items-center gap-1 rounded-[50px] bg-stone-100 p-[3px] dark:bg-stone-800">
|
||||
{indicator.w > 0 && (
|
||||
<div
|
||||
className="absolute top-[3px] left-0 z-10 h-[35px] bg-white shadow-lg shadow-black/5 dark:bg-stone-700 dark:shadow-white/5"
|
||||
className="absolute top-[3px] left-0 z-10 h-[35px] bg-white shadow-black/5 shadow-lg dark:bg-stone-700 dark:shadow-white/5"
|
||||
style={{
|
||||
borderRadius: 24,
|
||||
width: `${indicator.w}px`,
|
||||
@ -57,8 +57,8 @@ export default function TabSwitch({
|
||||
}}
|
||||
onClick={() => setCurrentTab(tab)}
|
||||
className={cn(
|
||||
"relative cursor-pointer rounded-3xl px-2.5 py-[8px] text-[13px] font-[600]",
|
||||
"transition-all duration-500 ease-in-out text-stone-400 dark:text-stone-500 hover:text-stone-950 hover:dark:text-stone-50",
|
||||
"relative cursor-pointer rounded-3xl px-2.5 py-[8px] font-[600] text-[13px]",
|
||||
"text-stone-400 transition-all duration-500 ease-in-out hover:text-stone-950 dark:text-stone-500 hover:dark:text-stone-50",
|
||||
{
|
||||
"text-stone-950 dark:text-stone-50": currentTab === tab,
|
||||
},
|
||||
|
@ -28,9 +28,9 @@ export function ModeToggle() {
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-full px-[9px] bg-white dark:bg-black cursor-pointer hover:bg-accent/50 dark:hover:bg-accent/50"
|
||||
className="cursor-pointer rounded-full bg-white px-[9px] hover:bg-accent/50 dark:bg-black dark:hover:bg-accent/50"
|
||||
>
|
||||
<Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Sun className="dark:-rotate-90 h-4 w-4 rotate-0 scale-100 transition-all dark:scale-0" />
|
||||
<Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
|
@ -6,7 +6,7 @@ import { useTranslations } from "next-intl"
|
||||
export default function GlobalLoading() {
|
||||
const t = useTranslations("Global")
|
||||
return (
|
||||
<section className="flex flex-col gap-4 mt-[3.2px]">
|
||||
<section className="mt-[3.2px] flex flex-col gap-4">
|
||||
<div className="flex min-h-40 flex-col items-center justify-center font-medium text-sm">
|
||||
{t("Loading")}
|
||||
<Loader visible={true} />
|
||||
|
@ -11,7 +11,7 @@ export default function NetworkChartLoading() {
|
||||
</CardTitle>
|
||||
<div className="mt-[2px] aspect-auto h-[14px] w-32 bg-muted" />
|
||||
</div>
|
||||
<div className="hidden pr-4 pt-4 sm:block">
|
||||
<div className="hidden pt-4 pr-4 sm:block">
|
||||
<Loader visible={true} />
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
@ -5,13 +5,13 @@ import { useRouter } from "next/navigation"
|
||||
export function ServerDetailChartLoading() {
|
||||
return (
|
||||
<div>
|
||||
<section className="grid md:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-3">
|
||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<section className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
|
||||
<Skeleton className="h-[182px] w-full animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
<Skeleton className="h-[182px] w-full animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
<Skeleton className="h-[182px] w-full animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
<Skeleton className="h-[182px] w-full animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
<Skeleton className="h-[182px] w-full animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
<Skeleton className="h-[182px] w-full animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
@ -26,12 +26,12 @@ export function ServerDetailLoading() {
|
||||
onClick={() => {
|
||||
router.push("/")
|
||||
}}
|
||||
className="flex flex-none cursor-pointer font-semibold leading-none items-center break-all tracking-tight gap-0.5 text-xl"
|
||||
className="flex flex-none cursor-pointer items-center gap-0.5 break-all font-semibold text-xl leading-none tracking-tight"
|
||||
>
|
||||
<BackIcon />
|
||||
<Skeleton className="h-[20px] w-24 rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="h-[20px] w-24 animate-none rounded-[5px] bg-muted-foreground/10" />
|
||||
</div>
|
||||
<Skeleton className="flex flex-wrap gap-2 h-[81px] w-1/2 mt-3 rounded-[5px] bg-muted-foreground/10 animate-none" />
|
||||
<Skeleton className="mt-3 flex h-[81px] w-1/2 animate-none flex-wrap gap-2 rounded-[5px] bg-muted-foreground/10" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ export default function AnimatedCircularProgressBar({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("relative size-40 text-2xl font-semibold", className)}
|
||||
className={cn("relative size-40 font-semibold text-2xl", className)}
|
||||
style={
|
||||
{
|
||||
"--circle-size": "100px",
|
||||
@ -48,7 +48,7 @@ export default function AnimatedCircularProgressBar({
|
||||
strokeDashoffset="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="opacity-100 stroke-muted"
|
||||
className="stroke-muted opacity-100"
|
||||
style={
|
||||
{
|
||||
"--stroke-percent": 90 - currentPercent,
|
||||
@ -71,7 +71,7 @@ export default function AnimatedCircularProgressBar({
|
||||
strokeDashoffset="0"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={cn("opacity-100 stroke-current", {
|
||||
className={cn("stroke-current opacity-100", {
|
||||
"stroke-[var(--stroke-primary-color)]": primaryColor,
|
||||
})}
|
||||
style={
|
||||
@ -92,7 +92,7 @@ export default function AnimatedCircularProgressBar({
|
||||
</svg>
|
||||
<span
|
||||
data-current-value={currentPercent}
|
||||
className="duration-[var(--transition-length)] delay-[var(--delay)] absolute inset-0 m-auto size-fit ease-linear animate-in fade-in"
|
||||
className="fade-in absolute inset-0 m-auto size-fit animate-in delay-[var(--delay)] duration-[var(--transition-length)] ease-linear"
|
||||
>
|
||||
{currentPercent}
|
||||
</span>
|
||||
|
@ -14,7 +14,7 @@ export const AnimatedTooltip = ({
|
||||
return (
|
||||
<>
|
||||
{items.map((item) => (
|
||||
<div className="group relative -mr-4" key={item.name}>
|
||||
<div className="group -mr-4 relative" key={item.name}>
|
||||
<Link href="https://buycoffee.top" target="_blank">
|
||||
<Image
|
||||
width={40}
|
||||
|
@ -26,7 +26,7 @@ const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HT
|
||||
({ className, ...props }, ref) => (
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn("text-2xl font-semibold leading-none tracking-tight", className)}
|
||||
className={cn("font-semibold text-2xl leading-none tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
@ -37,7 +37,7 @@ const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
||||
<p ref={ref} className={cn("text-muted-foreground text-sm", className)} {...props} />
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
|
@ -164,16 +164,16 @@ const ChartTooltipContent = React.forwardRef<
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"grid min-w-[8rem] items-start overflow-hidden gap-1.5 rounded-sm border border-border/50 bg-stone-100 dark:bg-stone-900 text-xs",
|
||||
"grid min-w-[8rem] items-start gap-1.5 overflow-hidden rounded-sm border border-border/50 bg-stone-100 text-xs dark:bg-stone-900",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{!nestLabel && (
|
||||
<div className="px-2.5 pt-1 mx-auto -mb-1">{!nestLabel ? tooltipLabel : null}</div>
|
||||
<div className="-mb-1 mx-auto px-2.5 pt-1">{!nestLabel ? tooltipLabel : null}</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={cn("grid gap-1.5 bg-white dark:bg-black px-2.5 py-1.5", {
|
||||
className={cn("grid gap-1.5 bg-white px-2.5 py-1.5 dark:bg-black", {
|
||||
"border-t-[1px]": !nestLabel,
|
||||
})}
|
||||
>
|
||||
@ -233,7 +233,7 @@ const ChartTooltipContent = React.forwardRef<
|
||||
{item.value && (
|
||||
<span
|
||||
className={cn(
|
||||
"ml-2 font-medium tabular-nums text-foreground",
|
||||
"ml-2 font-medium text-foreground tabular-nums",
|
||||
payload.length === 1 && "-ml-9",
|
||||
)}
|
||||
>
|
||||
|
@ -40,7 +40,7 @@ const CommandInput = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div className="flex items-center bg-stone-100 dark:bg-stone-900 px-3" cmdk-input-wrapper="">
|
||||
<div className="flex items-center bg-stone-100 px-3 dark:bg-stone-900" cmdk-input-wrapper="">
|
||||
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
<CommandPrimitive.Input
|
||||
ref={ref}
|
||||
@ -61,7 +61,7 @@ const CommandList = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.List
|
||||
ref={ref}
|
||||
className={cn("max-h-[300px] mb-1 overflow-y-auto overflow-x-hidden", className)}
|
||||
className={cn("mb-1 max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
@ -84,7 +84,7 @@ const CommandGroup = React.forwardRef<
|
||||
<CommandPrimitive.Group
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-xs",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -112,7 +112,7 @@ const CommandItem = React.forwardRef<
|
||||
<CommandPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default gap-2 select-none items-center rounded-[8px] px-2 py-1.5 text-xs outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-stone-100 dark:data-[selected='true']:bg-stone-900 data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"relative flex cursor-default select-none items-center gap-2 rounded-[8px] px-2 py-1.5 text-xs outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-stone-100 data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 dark:data-[selected='true']:bg-stone-900 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -124,7 +124,7 @@ CommandItem.displayName = CommandPrimitive.Item.displayName
|
||||
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
|
||||
className={cn("ml-auto text-muted-foreground text-xs tracking-widest", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80 data-[state=closed]:animate-out data-[state=open]:animate-in",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -38,13 +38,13 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:rounded-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<DialogPrimitive.Close className="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
@ -72,7 +72,7 @@ const DialogTitle = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
||||
className={cn("font-semibold text-lg leading-none tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
@ -84,7 +84,7 @@ const DialogDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
@ -45,7 +45,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -62,7 +62,7 @@ const DropdownMenuContent = React.forwardRef<
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-2xl dark:shadow-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-2xl data-[state=closed]:animate-out data-[state=open]:animate-in dark:shadow-none",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -80,7 +80,7 @@ const DropdownMenuItem = React.forwardRef<
|
||||
<DropdownMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-[10px] px-2 py-1.5 text-xs font-normal outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-[10px] px-2 py-1.5 font-normal text-xs outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
)}
|
||||
@ -96,7 +96,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
@ -119,7 +119,7 @@ const DropdownMenuRadioItem = React.forwardRef<
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -142,7 +142,7 @@ const DropdownMenuLabel = React.forwardRef<
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
||||
className={cn("px-2 py-1.5 font-semibold text-sm", inset && "pl-8", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
@ -62,7 +62,7 @@ const NavigationMenuContent = React.forwardRef<
|
||||
<NavigationMenuPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto",
|
||||
"data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out md:absolute md:w-auto",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -76,10 +76,10 @@ const NavigationMenuViewport = React.forwardRef<
|
||||
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div className={cn("absolute left-0 top-full flex justify-center")}>
|
||||
<div className={cn("absolute top-full left-0 flex justify-center")}>
|
||||
<NavigationMenuPrimitive.Viewport
|
||||
className={cn(
|
||||
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
||||
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full origin-top-center overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in md:w-[var(--radix-navigation-menu-viewport-width)]",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
@ -96,7 +96,7 @@ const NavigationMenuIndicator = React.forwardRef<
|
||||
<NavigationMenuPrimitive.Indicator
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
|
||||
"data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=visible]:animate-in",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
@ -18,7 +18,7 @@ const PopoverContent = React.forwardRef<
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
@ -20,7 +20,7 @@ const SheetOverlay = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80 data-[state=closed]:animate-out data-[state=open]:animate-in",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@ -60,7 +60,7 @@ const SheetContent = React.forwardRef<
|
||||
<SheetOverlay />
|
||||
<SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
|
||||
{children}
|
||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||
<SheetPrimitive.Close className="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
@ -88,7 +88,7 @@ const SheetTitle = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-lg font-semibold text-foreground", className)}
|
||||
className={cn("font-semibold text-foreground text-lg", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
@ -100,7 +100,7 @@ const SheetDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
@ -18,7 +18,7 @@ const TooltipContent = React.forwardRef<
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 overflow-hidden rounded-[10px] border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 animate-in overflow-hidden rounded-[10px] border bg-popover px-3 py-1.5 text-popover-foreground text-sm shadow-md data-[state=closed]:animate-out",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
Loading…
Reference in New Issue
Block a user