Update login page styling and sidebar collapse logo

This commit is contained in:
2026-06-26 16:22:28 +02:00
parent 33a4f9dfa9
commit ec8207fca7
7 changed files with 139 additions and 51 deletions
+25
View File
File diff suppressed because one or more lines are too long
+65 -7
View File
@@ -1,4 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Bangers&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Bangers&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@800&display=swap');
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@@ -29,15 +30,16 @@
--border: 214.3 31.8% 91.4%; --border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%; --ring: 221.2 83.2% 53.3%;
--sidebar: 222.2 84% 4.9%; --sidebar: 216 12% 92%;
--sidebar-foreground: 210 40% 98%; --sidebar-foreground: 0 0% 20%;
--sidebar-primary: 217.2 91.2% 59.8%; --sidebar-primary: 0 91.2% 59.8%;
--sidebar-primary-foreground: 0 0% 100%; --sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 217.2 32.6% 17.5%; --sidebar-accent: 218 16% 87%;
--sidebar-accent-foreground: 210 40% 98%; --sidebar-accent-foreground: 0 0% 20%;
--sidebar-border: 217.2 32.6% 17.5%; --sidebar-border: 220 11% 84%;
--sidebar-ring: 224.3 76.3% 48%; --sidebar-ring: 0 76.3% 48%;
--radius: 0.5rem; --radius: 0.5rem;
--theme-primary: hsl(var(--primary));
} }
.dark { .dark {
@@ -574,6 +576,62 @@
--sidebar-ring: 351 85% 52%; --sidebar-ring: 351 85% 52%;
} }
.bc-logo {
font-family: 'Raleway', sans-serif;
font-weight: 800;
font-size: 18px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: hsl(var(--sidebar-foreground));
padding: 8px 16px;
position: relative;
display: inline-block;
}
.bc-logo .accent {
color: var(--theme-primary, #3b91f7);
}
.bc-logo::before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 1.5px solid var(--theme-primary, #3b91f7);
border-left: 1.5px solid var(--theme-primary, #3b91f7);
width: 0;
height: 0;
animation: drawTL 3s ease-in-out infinite;
}
.bc-logo::after {
content: '';
position: absolute;
bottom: 0;
right: 0;
border-bottom: 1.5px solid var(--theme-primary, #3b91f7);
border-right: 1.5px solid var(--theme-primary, #3b91f7);
width: 0;
height: 0;
animation: drawBR 3s ease-in-out infinite;
}
@keyframes drawTL {
0%, 5% { width: 0; height: 0; }
30% { width: 100%; height: 0; }
55% { width: 100%; height: 100%; }
85% { width: 100%; height: 100%; }
100% { width: 0; height: 0; }
}
@keyframes drawBR {
0%, 5% { width: 0; height: 0; }
30% { width: 100%; height: 0; }
55% { width: 100%; height: 100%; }
85% { width: 100%; height: 100%; }
100% { width: 0; height: 0; }
}
@layer base { @layer base {
* { * {
@apply border-border; @apply border-border;
+5 -11
View File
@@ -2,7 +2,6 @@
import { useState, useEffect, useRef } from "react" import { useState, useEffect, useRef } from "react"
import { useSearchParams } from "next/navigation" import { useSearchParams } from "next/navigation"
import { COMPANY_NAME } from "@/lib/constants"
import { Eye, EyeOff, Loader2 } from "lucide-react" import { Eye, EyeOff, Loader2 } from "lucide-react"
const waves = [ const waves = [
@@ -29,11 +28,11 @@ export default function LoginPage() {
const testimonials = [ const testimonials = [
{ {
text: "This CRM transformed how we manage our sales pipeline. We've seen a 40% increase in lead conversion.", text: "This CRM transformed how we manage our sales pipeline. We've seen a 40% increase in lead conversion.",
author: "Marcus Johnson, Sales Lead at Coast IT", author: "Marcus Johnson, Sales Lead at Black Cipher",
}, },
{ {
text: "When you're not sure, flip a coin, because when the coin is in the air, you realize which option you're actually hoping for.", text: "When you're not sure, flip a coin, because when the coin is in the air, you realize which option you're actually hoping for.",
author: "Dillen van der Merwe, Madman of Coast IT", author: "Dillen van der Merwe, Madman of Black Cipher",
}, },
] ]
@@ -231,16 +230,11 @@ export default function LoginPage() {
return ( return (
<div className="flex min-h-screen bg-[#0a0a0f]"> <div className="flex min-h-screen bg-[#0a0a0f]">
<div className="left-panel flex flex-1 flex-col p-12"> <div className="left-panel flex flex-1 flex-col p-12">
<div className="relative z-10">
<img
src="/logo/CompanyLogo.png"
alt={COMPANY_NAME}
className="h-44 w-auto object-contain"
/>
</div>
<div className="relative z-10 flex-1 flex items-center justify-center"> <div className="relative z-10 flex-1 flex items-center justify-center">
<div className="text-center"> <div className="text-center">
<div className="bc-logo mb-8" style={{"--theme-primary":"#1BB0CE"}}>
Black <span className="accent">Cipher</span>
</div>
<h1 className="text-[34px] font-extrabold text-[#e8e8ef] leading-tight tracking-[-0.6px]"> <h1 className="text-[34px] font-extrabold text-[#e8e8ef] leading-tight tracking-[-0.6px]">
Your Agency&apos;s{" "} Your Agency&apos;s{" "}
<span className="growth-word">Growth</span>{" "} <span className="growth-word">Growth</span>{" "}
-2
View File
@@ -5,7 +5,6 @@ import { usePathname } from "next/navigation"
import { motion, AnimatePresence } from "framer-motion" import { motion, AnimatePresence } from "framer-motion"
import { Sidebar } from "./sidebar" import { Sidebar } from "./sidebar"
import { Topbar } from "./topbar" import { Topbar } from "./topbar"
import { SystemMonitor } from "./system-monitor"
interface AppShellProps { interface AppShellProps {
children: React.ReactNode children: React.ReactNode
@@ -80,7 +79,6 @@ export function AppShell({ children }: AppShellProps) {
</svg> </svg>
</div> </div>
<SystemMonitor />
<Sidebar <Sidebar
collapsed={sidebarCollapsed} collapsed={sidebarCollapsed}
onToggle={toggleSidebar} onToggle={toggleSidebar}
+10 -20
View File
@@ -5,6 +5,7 @@ import Link from "next/link"
import { usePathname } from "next/navigation" import { usePathname } from "next/navigation"
import { motion, AnimatePresence } from "framer-motion" import { motion, AnimatePresence } from "framer-motion"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { SystemMonitor } from "./system-monitor"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar" import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
@@ -20,7 +21,7 @@ import {
Bot, Bot,
Facebook, Facebook,
} from "lucide-react" } from "lucide-react"
import { COMPANY_NAME } from "@/lib/constants"
import { useUser } from "@/providers/user-provider" import { useUser } from "@/providers/user-provider"
import { useNotifications } from "@/providers/notification-provider" import { useNotifications } from "@/providers/notification-provider"
import { FacebookAccountsDialog } from "@/components/settings/facebook-accounts-dialog" import { FacebookAccountsDialog } from "@/components/settings/facebook-accounts-dialog"
@@ -60,24 +61,11 @@ export function Sidebar({ collapsed, onToggle, mobileOpen, onMobileClose }: Side
{/* Logo */} {/* Logo */}
<div className={cn("flex h-16 items-center border-b border-sidebar-border px-4", collapsed ? "justify-center" : "justify-between")}> <div className={cn("flex h-16 items-center border-b border-sidebar-border px-4", collapsed ? "justify-center" : "justify-between")}>
<Link href="/" className="flex items-center gap-3 overflow-hidden"> <Link href="/" className="flex items-center gap-3 overflow-hidden">
<img {collapsed ? (
src="/logo/CompanyLogo.png" <div className="bc-logo" style={{padding: "8px 3px", fontSize: "16px"}}>B<span className="accent">C</span></div>
alt={COMPANY_NAME} ) : (
className="h-8 w-8 shrink-0 rounded-lg object-contain" <div className="bc-logo">Black<span className="accent">Cipher</span></div>
/>
<AnimatePresence mode="wait">
{!collapsed && (
<motion.span
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -10 }}
transition={{ duration: 0.15 }}
className="text-sm font-semibold whitespace-nowrap"
>
{COMPANY_NAME}
</motion.span>
)} )}
</AnimatePresence>
</Link> </Link>
{!collapsed && ( {!collapsed && (
<Button <Button
@@ -196,6 +184,8 @@ export function Sidebar({ collapsed, onToggle, mobileOpen, onMobileClose }: Side
</div> </div>
)} )}
<SystemMonitor collapsed={collapsed} />
{/* User info */} {/* User info */}
<div className={cn("border-t border-sidebar-border p-3", collapsed && "flex justify-center")}> <div className={cn("border-t border-sidebar-border p-3", collapsed && "flex justify-center")}>
{collapsed ? ( {collapsed ? (
@@ -222,7 +212,7 @@ export function Sidebar({ collapsed, onToggle, mobileOpen, onMobileClose }: Side
return ( return (
<> <>
{/* Desktop sidebar */} {/* Desktop sidebar */}
<aside className="hidden lg:fixed lg:inset-y-0 lg:z-30 lg:flex"> <aside className="hidden lg:fixed lg:inset-y-0 lg:z-30 lg:flex border-r border-sidebar-border">
{sidebarContent} {sidebarContent}
</aside> </aside>
@@ -244,7 +234,7 @@ export function Sidebar({ collapsed, onToggle, mobileOpen, onMobileClose }: Side
animate={{ x: 0 }} animate={{ x: 0 }}
exit={{ x: -300 }} exit={{ x: -300 }}
transition={{ type: "spring", damping: 30, stiffness: 300 }} transition={{ type: "spring", damping: 30, stiffness: 300 }}
className="fixed inset-y-0 left-0 z-50 lg:hidden" className="fixed inset-y-0 left-0 z-50 lg:hidden border-r border-sidebar-border"
> >
{sidebarContent} {sidebarContent}
</motion.aside> </motion.aside>
+30 -7
View File
@@ -3,9 +3,13 @@
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
const RAM_LIMIT_MB = 8192 const RAM_LIMIT_MB = 8192
const CPU_LIMIT_PCT = 400 // 4 cores * 100% const CPU_LIMIT_PCT = 400
export function SystemMonitor() { interface SystemMonitorProps {
collapsed: boolean
}
export function SystemMonitor({ collapsed }: SystemMonitorProps) {
const [rssMB, setRssMB] = useState(0) const [rssMB, setRssMB] = useState(0)
const [cpuPct, setCpuPct] = useState(0) const [cpuPct, setCpuPct] = useState(0)
@@ -30,14 +34,33 @@ export function SystemMonitor() {
const ramOver = rssMB > RAM_LIMIT_MB const ramOver = rssMB > RAM_LIMIT_MB
const cpuOver = cpuPct > CPU_LIMIT_PCT const cpuOver = cpuPct > CPU_LIMIT_PCT
if (collapsed) {
return ( return (
<div className="fixed top-0 left-0 z-[9999] flex items-center gap-3 px-3 py-1 text-[11px] font-mono bg-black/80 rounded-br-lg select-none"> <div className="border-t border-sidebar-border px-3 py-2 flex justify-center gap-1.5">
<span className={ramOver ? "text-red-400" : "text-green-400"}> <span className={ramOver ? "text-red-400" : "text-[var(--theme-primary,#3b91f7)]"}>
RAM: {rssMB}MB / 8192MB {rssMB}
</span> </span>
<span className={cpuOver ? "text-red-400" : "text-green-400"}> <span className={cpuOver ? "text-red-400" : "text-[var(--theme-primary,#3b91f7)]"}>
CPU: {cpuPct}% {cpuPct}%
</span> </span>
</div> </div>
) )
} }
return (
<div className="border-t border-sidebar-border px-3 py-2.5">
<div className="flex items-center justify-between text-[11px] font-mono">
<span className="text-sidebar-foreground/50">RAM</span>
<span className={ramOver ? "text-red-400 font-semibold" : "text-sidebar-foreground/80"}>
{rssMB}MB / {RAM_LIMIT_MB}MB
</span>
</div>
<div className="flex items-center justify-between text-[11px] font-mono mt-1">
<span className="text-sidebar-foreground/50">CPU</span>
<span className={cpuOver ? "text-red-400 font-semibold" : "text-sidebar-foreground/80"}>
{cpuPct}%
</span>
</div>
</div>
)
}
+1 -1
View File
@@ -19,4 +19,4 @@ export const LEAD_SOURCES = [
export const ITEMS_PER_PAGE = 10 export const ITEMS_PER_PAGE = 10
export const COMPANY_NAME = "Coast IT" export const COMPANY_NAME = "Black Cipher"