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:
@@ -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: {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1288,6 +1288,11 @@
|
||||
"from": "с"
|
||||
},
|
||||
"auth": {
|
||||
"tagline": "SSH ТЕРМИНАЛ МЕНЕДЖЕР",
|
||||
"description": "Безопасное, мощное и интуитивное управление SSH-соединениями",
|
||||
"welcomeBack": "Добро пожаловать обратно в TERMIX",
|
||||
"createAccount": "Создайте вашу учетную запись TERMIX",
|
||||
"continueExternal": "Продолжить с внешним провайдером",
|
||||
"loginTitle": "Вход в Termix",
|
||||
"registerTitle": "Создать учетную запись",
|
||||
"loginButton": "Войти",
|
||||
|
||||
@@ -1272,6 +1272,11 @@
|
||||
"from": "来自"
|
||||
},
|
||||
"auth": {
|
||||
"tagline": "SSH 终端管理器",
|
||||
"description": "安全、强大、直观的 SSH 连接管理",
|
||||
"welcomeBack": "欢迎回到 TERMIX",
|
||||
"createAccount": "创建您的 TERMIX 账户",
|
||||
"continueExternal": "使用外部提供商继续",
|
||||
"loginTitle": "登录 Termix",
|
||||
"registerTitle": "创建账户",
|
||||
"loginButton": "登录",
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user