This commit is contained in:
2026-09-13 06:53:33 +01:00
parent 75670e4d5c
commit e7e63bc491
45 changed files with 2117 additions and 22 deletions
+40
View File
@@ -0,0 +1,40 @@
import type { ButtonHTMLAttributes } from "react";
import type { LucideIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
type Props = ButtonHTMLAttributes<HTMLButtonElement> & {
variant?: "primary" | "ghost";
Icon?: LucideIcon;
};
const baseClass =
"h-[30px] px-3 rounded-[5px] inline-flex items-center justify-center gap-2 " +
"text-[13px] font-medium cursor-pointer transition-colors whitespace-nowrap";
const variantClass = {
primary: "bg-primary text-white font-semibold hover:opacity-90",
ghost:
"text-foreground-light/70 dark:text-foreground-dark/70 " +
"hover:text-foreground-light dark:hover:text-foreground-dark " +
"border border-slate-200 dark:border-white/10 " +
"hover:border-secondary/60 dark:hover:border-secondary/60",
};
export default function AdminButton({
variant = "ghost",
Icon,
className,
children,
...props
}: Props) {
return (
<button
type="button"
{...props}
className={twMerge(baseClass, variantClass[variant], className)}
>
{Icon ? <Icon size={13} strokeWidth={2.25} /> : null}
{children}
</button>
);
}
+25
View File
@@ -0,0 +1,25 @@
import type { HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
type Props = HTMLAttributes<HTMLDivElement> & {
tier?: "default" | "secondary";
};
export default function AdminCard({
tier = "default",
className,
...props
}: Props) {
return (
<div
{...props}
className={twMerge(
"rounded-default border border-slate-200 dark:border-white/10",
tier == "secondary"
? "bg-background-light dark:bg-[#0e0e10]"
: "bg-background-light dark:bg-background-dark",
className,
)}
/>
);
}
+52
View File
@@ -0,0 +1,52 @@
import { twMerge } from "tailwind-merge";
export type WgStatus = "connected" | "idle" | "error";
type Props = {
status: WgStatus;
showLabel?: boolean;
};
const STATUS_META: Record<
WgStatus,
{ label: string; dot: string; text: string }
> = {
connected: {
label: "Connected",
dot: "bg-success",
text: "text-success dark:text-success",
},
idle: {
label: "Idle",
dot: "bg-warning",
text: "text-warning dark:text-warning",
},
error: {
label: "Error",
dot: "bg-error",
text: "text-error dark:text-error",
},
};
export default function StatusDot({ status, showLabel }: Props) {
const meta = STATUS_META[status];
return (
<span className="inline-flex items-center gap-1.5 shrink-0">
<span
className={twMerge("w-[6px] h-[6px] rounded-full", meta.dot)}
aria-hidden="true"
/>
{showLabel ? (
<span
className={twMerge(
"text-[12px] font-medium",
meta.text,
)}
>
{meta.label}
</span>
) : null}
</span>
);
}