feat(site): professional card system and tidy landing layout
Refine the public UI for a cleaner, more professional and scannable landing experience without leaving the classic Habbo style: - SurfaceCard: softer layered shadow, gradient accent hairline on the top edge and a bolder header title across all public cards. - Home: gradient hotel-name in the hero headline, shine effect on the primary CTA, hairline on the top bar. - Login/register: consistent avatar tiles with rounded corners, subtle borders and a gentle hover lift; uniform username sizing. - Add reusable theme-aware .card-hairline and .gradient-text utilities.
This commit is contained in:
1 parent
d755ab7ce1
commit
29b9a4b0dc
5 files changed
+73
-22
No files matched your search
@@ -122,24 +122,26 @@ export default async function LoginPage() {
|
||||
bodyClassName="p-4"
|
||||
className="card-glow"
|
||||
>
|
||||
<div className="grid grid-cols-4 gap-1.5">
|
||||
<div className="grid grid-cols-4 gap-1.5 sm:gap-2">
|
||||
{recentUsers.map((u) => (
|
||||
<div
|
||||
key={u.username}
|
||||
className="flex flex-col items-center gap-0.5 p-1.5 rounded-lg"
|
||||
className="flex flex-col items-center gap-1.5 rounded-xl border px-1 py-2 transition-all duration-200 hover:-translate-y-0.5"
|
||||
style={{
|
||||
background:
|
||||
"color-mix(in srgb, var(--color-primary) 4%, transparent)",
|
||||
borderColor:
|
||||
"color-mix(in srgb, var(--color-primary) 10%, transparent)",
|
||||
}}
|
||||
>
|
||||
<UserAvatarThumbnail
|
||||
figure={u.look}
|
||||
alt=""
|
||||
options={{ direction: 2 }}
|
||||
className="rounded-md"
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span
|
||||
className="text-[8px] font-bold truncate w-full text-center leading-tight"
|
||||
className="w-full truncate text-center text-[9px] font-bold leading-tight"
|
||||
style={{ color: "var(--color-text-readable)" }}
|
||||
>
|
||||
{u.username}
|
||||
@@ -157,24 +159,26 @@ export default async function LoginPage() {
|
||||
bodyClassName="p-4"
|
||||
className="card-glow"
|
||||
>
|
||||
<div className="grid grid-cols-4 gap-1.5">
|
||||
<div className="grid grid-cols-4 gap-1.5 sm:gap-2">
|
||||
{latestUsers.map((u) => (
|
||||
<div
|
||||
key={u.username}
|
||||
className="flex flex-col items-center gap-0.5 p-1.5 rounded-lg"
|
||||
className="flex flex-col items-center gap-1.5 rounded-xl border px-1 py-2 transition-all duration-200 hover:-translate-y-0.5"
|
||||
style={{
|
||||
background:
|
||||
"color-mix(in srgb, var(--color-primary) 4%, transparent)",
|
||||
borderColor:
|
||||
"color-mix(in srgb, var(--color-primary) 10%, transparent)",
|
||||
}}
|
||||
>
|
||||
<UserAvatarThumbnail
|
||||
figure={u.look}
|
||||
alt=""
|
||||
options={{ direction: 2 }}
|
||||
className="rounded-md"
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span
|
||||
className="text-[8px] font-bold truncate w-full text-center leading-tight"
|
||||
className="w-full truncate text-center text-[9px] font-bold leading-tight"
|
||||
style={{ color: "var(--color-text-readable)" }}
|
||||
>
|
||||
{u.username}
|
||||
|
||||
@@ -143,7 +143,7 @@ export default async function Home() {
|
||||
{/* ── Top Bar ── */}
|
||||
<Reveal>
|
||||
<div
|
||||
className="relative flex items-center justify-between rounded-xl border px-3 py-2.5 sm:px-5 sm:py-3"
|
||||
className="relative flex items-center justify-between rounded-xl border px-3 py-2.5 sm:px-5 sm:py-3 card-hairline"
|
||||
style={{
|
||||
background:
|
||||
"color-mix(in srgb, var(--color-surface) 60%, transparent)",
|
||||
@@ -269,11 +269,15 @@ export default async function Home() {
|
||||
<h1
|
||||
className="text-2xl font-black leading-[1.05] tracking-tight mb-2 sm:text-3xl md:text-5xl lg:text-6xl"
|
||||
style={{
|
||||
color: "var(--color-text-readable)",
|
||||
fontFamily: "var(--font-nunito)",
|
||||
}}
|
||||
>
|
||||
<TypewriterText text={tp("welcome", { hotelName })} />
|
||||
<span style={{ color: "var(--color-text-readable)" }}>
|
||||
{tp("welcome", { hotelName: "" })}
|
||||
</span>{" "}
|
||||
<span className="gradient-text">
|
||||
<TypewriterText text={hotelName} />
|
||||
</span>
|
||||
</h1>
|
||||
<p
|
||||
className="text-sm leading-relaxed max-w-2xl mb-5 sm:text-base md:text-lg md:mb-8"
|
||||
@@ -284,7 +288,7 @@ export default async function Home() {
|
||||
<div className="flex flex-wrap gap-2.5 sm:gap-3 justify-center">
|
||||
<Link
|
||||
href="/register"
|
||||
className="inline-flex items-center gap-2 sm:gap-2.5 font-extrabold text-xs sm:text-sm px-5 sm:px-8 py-3 sm:py-4 rounded-xl transition-all duration-200 hover:scale-[1.03] active:scale-95 shadow-lg"
|
||||
className="btn-shine inline-flex items-center gap-2 sm:gap-2.5 font-extrabold text-xs sm:text-sm px-5 sm:px-8 py-3 sm:py-4 rounded-xl transition-all duration-200 hover:scale-[1.03] active:scale-95 shadow-lg"
|
||||
style={{
|
||||
background: "var(--color-primary)",
|
||||
color: "var(--color-primary-foreground)",
|
||||
|
||||
@@ -135,20 +135,22 @@ export default async function RegisterPage() {
|
||||
{recentUsers.map((u) => (
|
||||
<div
|
||||
key={u.username}
|
||||
className="flex flex-col items-center gap-0.5 p-1.5 rounded-lg"
|
||||
className="flex flex-col items-center gap-1.5 rounded-xl border px-1 py-2 transition-all duration-200 hover:-translate-y-0.5"
|
||||
style={{
|
||||
background:
|
||||
"color-mix(in srgb, var(--color-primary) 4%, transparent)",
|
||||
borderColor:
|
||||
"color-mix(in srgb, var(--color-primary) 10%, transparent)",
|
||||
}}
|
||||
>
|
||||
<UserAvatarThumbnail
|
||||
figure={u.look}
|
||||
alt=""
|
||||
options={{ direction: 2 }}
|
||||
className="rounded-md"
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span
|
||||
className="text-[8px] font-bold truncate w-full text-center leading-tight"
|
||||
className="w-full truncate text-center text-[9px] font-bold leading-tight"
|
||||
style={{ color: "var(--color-text-readable)" }}
|
||||
>
|
||||
{u.username}
|
||||
@@ -170,20 +172,22 @@ export default async function RegisterPage() {
|
||||
{latestUsers.map((u) => (
|
||||
<div
|
||||
key={u.username}
|
||||
className="flex flex-col items-center gap-0.5 p-1.5 rounded-lg"
|
||||
className="flex flex-col items-center gap-1.5 rounded-xl border px-1 py-2 transition-all duration-200 hover:-translate-y-0.5"
|
||||
style={{
|
||||
background:
|
||||
"color-mix(in srgb, var(--color-primary) 4%, transparent)",
|
||||
borderColor:
|
||||
"color-mix(in srgb, var(--color-primary) 10%, transparent)",
|
||||
}}
|
||||
>
|
||||
<UserAvatarThumbnail
|
||||
figure={u.look}
|
||||
alt=""
|
||||
options={{ direction: 2 }}
|
||||
className="rounded-md"
|
||||
className="rounded-lg"
|
||||
/>
|
||||
<span
|
||||
className="text-[10px] font-bold truncate w-full text-center leading-tight"
|
||||
className="w-full truncate text-center text-[9px] font-bold leading-tight"
|
||||
style={{ color: "var(--color-text-readable)" }}
|
||||
>
|
||||
{u.username}
|
||||
|
||||
@@ -2018,3 +2018,40 @@ details[open] > summary .details-open\:rotate-180 {
|
||||
0 12px 32px -10px color-mix(in srgb, var(--color-primary) 32%, transparent),
|
||||
0 0 0 1px color-mix(in srgb, var(--color-primary) 22%, transparent);
|
||||
}
|
||||
|
||||
/* Gradient accent hairline drawn on the top edge of a relative card. */
|
||||
.card-hairline {
|
||||
position: relative;
|
||||
}
|
||||
.card-hairline::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset-inline: 2%;
|
||||
top: 0;
|
||||
height: 2px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
color-mix(in srgb, var(--color-primary) 75%, transparent) 30%,
|
||||
var(--color-primary) 50%,
|
||||
color-mix(in srgb, var(--color-accent) 70%, transparent) 70%,
|
||||
transparent
|
||||
);
|
||||
opacity: 0.55;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Brand gradient text (primary → accent). */
|
||||
.gradient-text {
|
||||
background: linear-gradient(
|
||||
115deg,
|
||||
var(--color-primary) 10%,
|
||||
color-mix(in srgb, var(--color-primary) 55%, var(--color-accent)) 48%,
|
||||
color-mix(in srgb, var(--color-accent) 92%, var(--color-primary)) 92%
|
||||
);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
@@ -43,13 +43,15 @@ export function SurfaceCard({
|
||||
}: SurfaceCardProps) {
|
||||
const hasHeader = Boolean(title || icon || (actionHref && actionLabel));
|
||||
|
||||
const CARD_SHADOW =
|
||||
"0 1px 2px rgba(0,0,0,0.05), 0 8px 24px -10px color-mix(in srgb, var(--color-text-muted) 22%, transparent), 0 0 0 0.5px color-mix(in srgb, var(--color-text-muted) 6%, transparent)";
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`surface-card overflow-hidden rounded-2xl border bg-[var(--color-surface)] ${className}`}
|
||||
className={`surface-card card-hairline overflow-hidden rounded-2xl border bg-[var(--color-surface)] ${className}`}
|
||||
style={{
|
||||
borderColor: CARD_BORDER,
|
||||
boxShadow:
|
||||
"0 1px 2px rgba(0,0,0,0.04), 0 2px 8px rgba(0,0,0,0.03), 0 0 0 0.5px color-mix(in srgb, var(--color-text-muted) 6%, transparent)",
|
||||
boxShadow: CARD_SHADOW,
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
@@ -81,7 +83,7 @@ export function SurfaceCard({
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
className="text-sm font-bold tracking-tight"
|
||||
className="text-sm font-extrabold tracking-wide"
|
||||
style={{
|
||||
fontFamily: "var(--font-nunito)",
|
||||
color: "var(--color-text-readable)",
|
||||
|
||||
Reference in new issue
Block a user