feat(site): redesign home, login and register with premium dark gaming theme
CI / check (push) Failing after 1m5s
CI / deploy (push) Skipped
CI / publish-container (push) Skipped

Replaced the classic Habbo landing style on the home, login and register pages with a modern premium dark-gaming look: always-dark hero canvas with brand glows, grid overlay and ambient orbs, glass panels, gradient text and floating art. Adds shared LandingTopBar, AuthShell and BrandFrank components plus reusable premium CSS utilities. Build, typecheck and lint pass.
This commit is contained in:
openhands committed 2026-09-12 15:40:54 +02:00
1 parent 4d720ee03c
commit 741f01e897
8 files changed
+694 -657

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
import type { ReactNode } from "react";
import { AmbientOrbs } from "@/components/ambient-orbs";
import { LandingTopBar } from "@/components/landing-top-bar";
/**
* Premium dark-gaming shell shared by the login and register pages.
* Renders an always-dark hero canvas (brand glows + grid overlay) with a
* hotel header on top, a brand/side column on the left and the auth form
* (rendered by the page) on the right in a frosted glass panel.
*/
export function AuthShell({
hotelName,
logo,
side,
footer,
children,
}: {
hotelName: string;
logo?: string | null;
side: ReactNode;
footer?: ReactNode;
children: ReactNode;
}) {
return (
<section className="landing-hero w-full overflow-hidden rounded-2xl border border-white/10 sm:rounded-3xl">
{/* Ambient glows */}
<AmbientOrbs />
{/* Header */}
<LandingTopBar hotelName={hotelName} logo={logo} />
{/* Body */}
<div className="relative z-10 grid gap-8 px-4 pb-8 pt-6 sm:px-7 sm:pb-10 sm:pt-8 lg:grid-cols-[1fr_1.05fr] lg:gap-12">
<div className="flex flex-col">{side}</div>
<div className="glass-panel relative h-fit w-full rounded-2xl p-5 sm:p-7 lg:sticky lg:top-6">
{children}
</div>
</div>
{footer ? (
<div className="relative z-10 border-t border-white/10 px-4 py-4 text-center sm:px-7">
{footer}
</div>
) : null}
</section>
);
}
+32
View File
@@ -0,0 +1,32 @@
import Image from "next/image";
/**
* Floating brand art for the premium auth pages: the welcome character
* hovers over a pulsing primary halo with a faint slow-orbiting ring.
*/
export function BrandFrank({ size = 150 }: { size?: number }) {
return (
<div className="relative flex items-center justify-center">
<style>{`@keyframes spin-slow { to { transform: rotate(360deg); } }`}</style>
<span className="hero-halo h-40 w-40 sm:h-48 sm:w-48" />
<span
className="absolute h-52 w-52 rounded-full border border-dashed sm:h-64 sm:w-64"
style={{
borderColor: "color-mix(in srgb, #ffffff 16%, transparent)",
animation: "spin-slow 28s linear infinite",
}}
/>
<div className="animate-float relative z-10 drop-shadow-[0_20px_30px_rgba(0,0,0,0.45)]">
<Image
src="/assets/images/FrankwithBag.gif"
alt=""
width={size}
height={Math.round(size * 1.29)}
className="object-contain"
unoptimized
priority
/>
</div>
</div>
);
}
+25 -53
View File
@@ -113,52 +113,30 @@ export function RegisterForm({
/>
) : null}
{/* Header Banner */}
<div
className="relative overflow-hidden bg-center bg-cover rounded-t-xl"
style={{
backgroundImage: "url(/assets/images/mybobba_banner.png)",
height: "160px",
}}
>
<div
className="absolute inset-0 z-10"
style={{
background:
"linear-gradient(180deg, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.55) 100%)",
}}
/>
<div className="relative flex items-center justify-center w-full h-full z-20">
<div
className="relative animate-float"
style={{ width: "140px", height: "140px" }}
<div className="mb-7 flex items-center gap-4">
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl border border-white/10 bg-white/5">
<Image
src="/assets/images/icons/navigation/me.png"
alt=""
width={22}
height={22}
unoptimized
className="opacity-90"
/>
</div>
<div className="min-w-0">
<p
className="text-[11px] font-extrabold uppercase tracking-widest"
style={{ color: "var(--color-primary)" }}
>
<div
className="absolute inset-0 rounded-full overflow-hidden"
style={{ zIndex: -1 }}
>
<div
className="w-full h-full"
style={{
background: "black",
filter: "blur(8px)",
transform: "scale(1.2)",
opacity: 0.6,
}}
/>
</div>
<Image
src="/assets/images/FrankwithBag.gif"
alt=""
fill
className="!static"
style={{
objectFit: "contain",
objectPosition: "center",
width: "100%",
height: "100%",
}}
/>
</div>
{t("accountDetails")}
</p>
<h2 className="m-0 text-2xl font-black tracking-tight text-white">
{t("title")}
</h2>
<p className="mt-0.5 truncate text-sm text-white/55">
{t("subtitle")}
</p>
</div>
</div>
@@ -171,12 +149,7 @@ export function RegisterForm({
};
formAction(fd);
}}
className="p-6 flex flex-col gap-6"
style={{
backgroundColor:
"color-mix(in srgb, var(--color-background) 50%, var(--color-surface))",
borderRadius: "0 0 12px 12px",
}}
className="flex flex-col gap-6"
>
{(error || state.error) && (
<div
@@ -383,8 +356,7 @@ export function RegisterForm({
termsError ? "animate-shake" : ""
}`}
style={{
backgroundColor:
"color-mix(in srgb, var(--color-background) 50%, var(--color-surface))",
backgroundColor: "var(--color-background)",
border: `1px solid ${
termsError
? "var(--color-danger)"
+53
View File
@@ -0,0 +1,53 @@
import Image from "next/image";
import { Clock } from "@/components/clock";
import { LanguageSwitcher } from "@/components/language-switcher";
import { ThemeSwitcher } from "@/components/theme-switcher";
/**
* Frosted top bar shared by the home hero and the premium auth pages.
* Dark-styled to sit on the "always-dark" landing canvas.
*/
export function LandingTopBar({
hotelName,
logo,
}: {
hotelName: string;
logo?: string | null;
}) {
return (
<div className="relative z-10 flex items-center justify-between gap-3 border-b border-white/10 px-4 py-3 sm:px-7 sm:py-4">
<div className="flex min-w-0 items-center gap-2.5 sm:gap-3">
{logo ? (
<Image
src={logo}
alt={hotelName}
width={110}
height={30}
className="shrink-0 object-contain"
unoptimized
style={{ maxHeight: 30, width: "auto", height: "auto" }}
/>
) : (
<Image
src="/assets/images/icons/lighthouse.png"
alt={hotelName}
width={30}
height={30}
className="shrink-0"
unoptimized
/>
)}
<span className="hidden truncate text-sm font-extrabold uppercase tracking-widest text-white/85 sm:inline">
{hotelName}
</span>
</div>
<div className="flex shrink-0 items-center gap-1 rounded-xl border border-white/10 bg-white/5 px-1.5 py-1 sm:px-2">
<LanguageSwitcher />
<div className="hidden h-5 w-px bg-white/15 sm:block" />
<Clock />
<div className="h-5 w-px bg-white/15" />
<ThemeSwitcher />
</div>
</div>
);
}