style(landing): add micro-interactions and polish public pages

This commit is contained in:
openhands committed 2026-10-06 22:59:03 +02:00
1 parent 57710a7fe3
commit 3265c149da
8 files changed
+235 -36

No files matched your search

+25 -1
View File
@@ -47,7 +47,31 @@ export default async function LoginPage() {
return (
<div className="mx-auto w-full max-w-6xl flex flex-col gap-8 pb-16">
<AuthTopBar hotelName={hotelName} logo={logo} />
<div className="relative">
<div
aria-hidden="true"
className="pointer-events-none absolute -inset-x-16 -top-24 overflow-hidden"
>
<div
className="aurora-blob -left-20 top-0 h-80 w-80"
style={{
background:
"color-mix(in srgb, var(--color-primary) 34%, transparent)",
opacity: 0.45,
}}
/>
<div
className="aurora-blob -right-20 top-6 h-72 w-72"
style={{
background:
"color-mix(in srgb, var(--color-accent) 30%, transparent)",
animationDelay: "-7s",
opacity: 0.4,
}}
/>
</div>
<AuthTopBar hotelName={hotelName} logo={logo} />
</div>
<Reveal>
<div className="flex flex-col gap-8 lg:flex-row lg:items-start">
+26 -17
View File
File diff suppressed because it is too large. Load diff
+25 -1
View File
@@ -57,7 +57,31 @@ export default async function RegisterPage() {
return (
<div className="mx-auto w-full max-w-6xl flex flex-col gap-8 pb-16">
<AuthTopBar hotelName={hotelName} logo={logo} />
<div className="relative">
<div
aria-hidden="true"
className="pointer-events-none absolute -inset-x-16 -top-24 overflow-hidden"
>
<div
className="aurora-blob -left-20 top-0 h-80 w-80"
style={{
background:
"color-mix(in srgb, var(--color-primary) 34%, transparent)",
opacity: 0.45,
}}
/>
<div
className="aurora-blob -right-20 top-6 h-72 w-72"
style={{
background:
"color-mix(in srgb, var(--color-accent) 30%, transparent)",
animationDelay: "-7s",
opacity: 0.4,
}}
/>
</div>
<AuthTopBar hotelName={hotelName} logo={logo} />
</div>
<Reveal>
<div className="flex flex-col gap-8 lg:flex-row lg:items-start">
+54
View File
@@ -2837,3 +2837,57 @@ html {
background: color-mix(in srgb, var(--color-text-muted) 20%, transparent);
}
}
/* Mouse-tracking spotlight glow for premium cards. The dot position comes
from CSS custom properties updated on pointermove (see SpotlightCard). */
.spotlight {
position: relative;
isolation: isolate;
}
.spotlight::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
opacity: 0;
transition: opacity 0.4s ease;
background: radial-gradient(
340px circle at var(--spot-x, 50%) var(--spot-y, 50%),
color-mix(in srgb, var(--color-primary) 20%, transparent),
transparent 70%
);
z-index: -1;
}
.spotlight:hover::before,
.spotlight:focus-within::before {
opacity: 1;
}
/* Section number mark (01 / 02 / …) used as a faint watermark in headers. */
.number-mark {
font-family: var(--font-nunito);
font-weight: 900;
letter-spacing: -0.02em;
line-height: 1;
background: linear-gradient(
120deg,
color-mix(in srgb, var(--color-primary) 65%, transparent),
color-mix(in srgb, var(--color-accent) 50%, transparent)
);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
opacity: 0.85;
}
@media (prefers-reduced-motion: reduce) {
.spotlight::before {
transition: none;
}
.animate-fade-in-up,
.animate-scale-in,
.animate-count {
animation: none;
}
}
+56 -9
View File
@@ -1,6 +1,6 @@
"use client";
import { Lock, Mail, UserRound } from "lucide-react";
import { KeyRound, Lock, Mail, ShieldCheck, UserRound } from "lucide-react";
import Script from "next/script";
import { signIn } from "next-auth/react";
import { useTranslations } from "next-intl";
@@ -183,7 +183,24 @@ export function RegisterForm({
{/* Username & Email */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2.5">
<span
aria-hidden="true"
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg"
style={{
background:
"color-mix(in srgb, var(--color-primary) 12%, transparent)",
boxShadow:
"inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 22%, transparent)",
}}
>
<UserRound
className="h-3.5 w-3.5"
style={{
color: "var(--color-primary-readable, var(--color-primary))",
}}
/>
</span>
<span
className="text-[11px] font-black uppercase tracking-widest"
style={{
@@ -199,6 +216,9 @@ export function RegisterForm({
"linear-gradient(90deg, color-mix(in srgb, var(--color-text-muted) 18%, transparent), transparent)",
}}
/>
<span aria-hidden="true" className="number-mark text-lg">
01
</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 stagger-children">
<div className="space-y-1.5">
@@ -247,7 +267,24 @@ export function RegisterForm({
{/* Password & Confirm */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<div className="flex items-center gap-2.5">
<span
aria-hidden="true"
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg"
style={{
background:
"color-mix(in srgb, var(--color-primary) 12%, transparent)",
boxShadow:
"inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 22%, transparent)",
}}
>
<KeyRound
className="h-3.5 w-3.5"
style={{
color: "var(--color-primary-readable, var(--color-primary))",
}}
/>
</span>
<span
className="text-[11px] font-black uppercase tracking-widest"
style={{
@@ -263,6 +300,9 @@ export function RegisterForm({
"linear-gradient(90deg, color-mix(in srgb, var(--color-text-muted) 18%, transparent), transparent)",
}}
/>
<span aria-hidden="true" className="number-mark text-lg">
02
</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 stagger-children">
<div className="space-y-1.5">
@@ -313,12 +353,19 @@ export function RegisterForm({
/>
))}
</div>
<p
className="text-[11px] font-extrabold uppercase tracking-wider"
style={{ color: strength.color }}
>
{strength.label}
</p>
<div className="flex items-center gap-1.5">
<ShieldCheck
aria-hidden="true"
className="h-3.5 w-3.5 shrink-0"
style={{ color: strength.color }}
/>
<p
className="text-[11px] font-extrabold uppercase tracking-wider"
style={{ color: strength.color }}
>
{strength.label}
</p>
</div>
</div>
)}
</div>
+39
View File
@@ -0,0 +1,39 @@
"use client";
import type { CSSProperties, MouseEvent, ReactNode } from "react";
interface SpotlightCardProps {
children: ReactNode;
className?: string;
style?: CSSProperties;
}
/**
* Wraps a card with a mouse-tracking radial glow. The pointer position is
* written to `--spot-x` / `--spot-y` and consumed by the `.spotlight::before`
* overlay in globals.css.
*/
export function SpotlightCard({
children,
className,
style,
}: SpotlightCardProps) {
const handlePointerMove = (event: MouseEvent<HTMLDivElement>) => {
const el = event.currentTarget;
const rect = el.getBoundingClientRect();
el.style.setProperty("--spot-x", `${event.clientX - rect.left}px`);
el.style.setProperty("--spot-y", `${event.clientY - rect.top}px`);
};
return (
<div
className={className}
style={
{ "--spot-x": "50%", "--spot-y": "50%", ...style } as CSSProperties
}
onPointerMove={handlePointerMove}
>
{children}
</div>
);
}