feat: Update login page theme colors and add i18n support

- Changed login page gradient from blue to match dark theme colors
- Updated ripple effects to use theme primary color
- Added i18n translation keys for login page (auth.tagline, auth.description, auth.welcomeBack, auth.createAccount, auth.continueExternal)
- Updated all language files (en, zh, de, ru, pt-BR) with new translations
- Fixed TypeScript compilation issues by clearing build cache
This commit is contained in:
ZacharyZcR
2025-11-09 08:46:58 +08:00
parent 3a8e3a1607
commit fe9e392b2c
11 changed files with 57 additions and 22 deletions

View File

@@ -6,7 +6,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive active:scale-95",
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-100 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive active:scale-95",
{
variants: {
variant: {

View File

@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
type={type}
data-slot="input"
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] duration-200 outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className,

View File

@@ -40,7 +40,7 @@ function TabsTrigger({
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] duration-200 focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
@@ -55,7 +55,13 @@ function TabsContent({
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
className={cn(
"flex-1 outline-none",
"data-[state=active]:animate-in data-[state=inactive]:animate-out",
"data-[state=inactive]:fade-out-0 data-[state=active]:fade-in-0",
"duration-150",
className
)}
{...props}
/>
);

View File

@@ -1192,6 +1192,11 @@
"from": "von"
},
"auth": {
"tagline": "SSH TERMINAL MANAGER",
"description": "Sichere, leistungsstarke und intuitive SSH-Verbindungsverwaltung",
"welcomeBack": "Willkommen zurück bei TERMIX",
"createAccount": "Erstellen Sie Ihr TERMIX-Konto",
"continueExternal": "Mit externem Anbieter fortfahren",
"loginTitle": "Melden Sie sich bei Termix an",
"registerTitle": "Benutzerkonto erstellen",
"loginButton": "Anmelden",

View File

@@ -1301,6 +1301,11 @@
"from": "from"
},
"auth": {
"tagline": "SSH TERMINAL MANAGER",
"description": "Secure, powerful, and intuitive SSH connection management",
"welcomeBack": "Welcome back to TERMIX",
"createAccount": "Create your TERMIX account",
"continueExternal": "Continue with external provider",
"loginTitle": "Login to Termix",
"registerTitle": "Create Account",
"loginButton": "Login",

View File

@@ -1143,6 +1143,11 @@
"available": "Disponível"
},
"auth": {
"tagline": "GERENCIADOR DE TERMINAL SSH",
"description": "Gerenciamento de conexão SSH seguro, poderoso e intuitivo",
"welcomeBack": "Bem-vindo de volta ao TERMIX",
"createAccount": "Crie sua conta TERMIX",
"continueExternal": "Continuar com provedor externo",
"loginTitle": "Entrar no Termix",
"registerTitle": "Criar Conta",
"loginButton": "Entrar",

View File

@@ -1288,6 +1288,11 @@
"from": "с"
},
"auth": {
"tagline": "SSH ТЕРМИНАЛ МЕНЕДЖЕР",
"description": "Безопасное, мощное и интуитивное управление SSH-соединениями",
"welcomeBack": "Добро пожаловать обратно в TERMIX",
"createAccount": "Создайте вашу учетную запись TERMIX",
"continueExternal": "Продолжить с внешним провайдером",
"loginTitle": "Вход в Termix",
"registerTitle": "Создать учетную запись",
"loginButton": "Войти",

View File

@@ -1272,6 +1272,11 @@
"from": "来自"
},
"auth": {
"tagline": "SSH 终端管理器",
"description": "安全、强大、直观的 SSH 连接管理",
"welcomeBack": "欢迎回到 TERMIX",
"createAccount": "创建您的 TERMIX 账户",
"continueExternal": "使用外部提供商继续",
"loginTitle": "登录 Termix",
"registerTitle": "创建账户",
"loginButton": "登录",

View File

@@ -841,30 +841,34 @@ export function Auth({
<div className="w-full h-full flex flex-col md:flex-row">
{/* Left Side - Brand Showcase */}
<div className="hidden md:flex md:w-2/5 bg-gradient-to-br from-primary via-primary/90 to-primary/70 relative overflow-hidden items-center justify-center">
<div className="hidden md:flex md:w-2/5 relative overflow-hidden items-center justify-center"
style={{
background: 'linear-gradient(to bottom right, hsl(var(--background)), #0e0e10, #09090b)'
}}
>
{/* Animated Ripples Background */}
<div className="absolute inset-0 flex items-center justify-center">
<div className="absolute w-0 h-0 bg-white/10 rounded-full animate-[ripple_4s_ease-out_infinite]" />
<div className="absolute w-0 h-0 bg-white/8 rounded-full animate-[ripple_4s_ease-out_infinite_1s]" />
<div className="absolute w-0 h-0 bg-white/5 rounded-full animate-[ripple_4s_ease-out_infinite_2s]" />
<div className="absolute w-0 h-0 bg-primary/10 rounded-full animate-[ripple_4s_ease-out_infinite]" />
<div className="absolute w-0 h-0 bg-primary/7 rounded-full animate-[ripple_4s_ease-out_infinite_1s]" />
<div className="absolute w-0 h-0 bg-primary/5 rounded-full animate-[ripple_4s_ease-out_infinite_2s]" />
</div>
{/* Logo and Branding */}
<div className="relative z-10 text-center px-8">
<div
className="text-7xl font-bold tracking-wider text-white mb-4"
className="text-7xl font-bold tracking-wider mb-4 text-foreground"
style={{
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
textShadow: '0 0 30px rgba(255,255,255,0.3), 0 0 60px rgba(255,255,255,0.2)'
textShadow: '0 0 30px hsl(var(--primary) / 0.3), 0 0 60px hsl(var(--primary) / 0.2)'
}}
>
TERMIX
</div>
<div className="text-lg text-white/80 tracking-widest font-light">
SSH TERMINAL MANAGER
<div className="text-lg text-muted-foreground tracking-widest font-light">
{t("auth.tagline") || "SSH TERMINAL MANAGER"}
</div>
<div className="mt-8 text-sm text-white/60 max-w-md">
Secure, powerful, and intuitive SSH connection management for modern teams
<div className="mt-8 text-sm text-muted-foreground/80 max-w-md">
{t("auth.description") || "Secure, powerful, and intuitive SSH connection management"}
</div>
</div>
@@ -1067,7 +1071,7 @@ export function Auth({
{/* Page Title */}
<div className="mb-8 text-center">
<h2 className="text-2xl font-bold mb-2 bg-gradient-to-r from-foreground to-foreground/70 bg-clip-text text-transparent">
<h2 className="text-2xl font-bold mb-2">
{tab === "login"
? t("auth.loginTitle")
: tab === "signup"
@@ -1078,10 +1082,10 @@ export function Auth({
</h2>
<p className="text-sm text-muted-foreground">
{tab === "login"
? "Welcome back to TERMIX"
? t("auth.welcomeBack")
: tab === "signup"
? "Create your TERMIX account"
: "Continue with external provider"}
? t("auth.createAccount")
: t("auth.continueExternal")}
</p>
</div>

View File

@@ -137,10 +137,10 @@ export function SSHAuthDialog({
return (
<div
className="absolute inset-0 z-50 flex items-center justify-center bg-dark-bg"
className="absolute inset-0 z-50 flex items-center justify-center bg-dark-bg animate-in fade-in duration-200"
style={{ backgroundColor }}
>
<Card className="w-full max-w-2xl mx-4 border-2">
<Card className="w-full max-w-2xl mx-4 border-2 animate-in fade-in zoom-in-95 duration-200">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Shield className="w-5 h-5" />

View File

@@ -25,12 +25,12 @@ export function TOTPDialog({
if (!isOpen) return null;
return (
<div className="absolute inset-0 flex items-center justify-center z-50">
<div className="absolute inset-0 flex items-center justify-center z-50 animate-in fade-in duration-200">
<div
className="absolute inset-0 bg-dark-bg rounded-md"
style={{ backgroundColor: backgroundColor || undefined }}
/>
<div className="bg-dark-bg border-2 border-dark-border rounded-lg p-6 max-w-md w-full mx-4 relative z-10">
<div className="bg-dark-bg border-2 border-dark-border rounded-lg p-6 max-w-md w-full mx-4 relative z-10 animate-in fade-in zoom-in-95 duration-200">
<div className="mb-4 flex items-center gap-2">
<Shield className="w-5 h-5 text-primary" />
<h3 className="text-lg font-semibold">