From ac16df98c3054d42292db59ce727f7cbe99b0191 Mon Sep 17 00:00:00 2001 From: openhands Date: Thu, 23 Jul 2026 16:36:32 +0200 Subject: [PATCH] Replace PNG icons with Habbo-style SVG pixel art icons across index, nav, and mobile nav - Create 20 Habbo-style pixel-art SVG icon components (home, user, catalog, star, community, games, enter, news, online, camera, chat, clock, heart, arrow, cog, furni, diamond, credits, duckets, rank) - Update index page: replace all PNG icon references, add pixel font headings, add Habbo-style gradient section headers - Update navigation: replace all PNG nav icons with Habbo SVG icons - Update NavDropdown: accept ReactNode icon instead of string path - Update mobile-nav: replace PNG brand icon with HabboHome SVG --- src/app/(site)/page.tsx | 385 ++++++++++++++------------ src/components/mobile-nav.tsx | 10 +- src/components/nav-dropdown.tsx | 12 +- src/components/navigation.tsx | 171 +++--------- src/components/shared/habbo-icons.tsx | 310 +++++++++++++++++++++ 5 files changed, 575 insertions(+), 313 deletions(-) create mode 100644 src/components/shared/habbo-icons.tsx diff --git a/src/app/(site)/page.tsx b/src/app/(site)/page.tsx index afc4aadb..a4032ef5 100644 --- a/src/app/(site)/page.tsx +++ b/src/app/(site)/page.tsx @@ -11,6 +11,18 @@ import { siteSettings } from "@/lib/services/site-settings"; import { auth } from "@/lib/auth"; import { ThemeSwitcher } from "@/components/theme-switcher"; import { LanguageSwitcher } from "@/components/language-switcher"; +import { + HabboHome, + HabboUser, + HabboCatalog, + HabboStar, + HabboCommunity, + HabboGames, + HabboEnter, + HabboNews, + HabboOnline, + HabboCamera, +} from "@/components/shared/habbo-icons"; export const revalidate = 120; @@ -85,24 +97,15 @@ export default async function Home() { } = await getHotelData(); return ( -
- +
{/* ── Toolbar ── */}
+ {/* ── 1. Hero ── */}
-
-
-
+
+

{tp("welcome", { hotelName })}

@@ -179,7 +177,7 @@ export default async function Home() { boxShadow: "0 4px 24px color-mix(in srgb, var(--color-primary) 35%, transparent)", }} > - + {tp("register")} {[ - { value: online.toLocaleString(), label: tp("statsOnline"), icon: "/assets/images/icons/navigation/home.png" }, - { value: users.toLocaleString(), label: tp("statsCitizens"), icon: "/assets/images/icons/navigation/me.png" }, - { value: rooms.toLocaleString(), label: tp("statsRooms"), icon: "/assets/images/icons/catalog.png" }, - ].map((s) => ( + { value: online.toLocaleString(), label: tp("statsOnline"), icon: HabboHome }, + { value: users.toLocaleString(), label: tp("statsCitizens"), icon: HabboUser }, + { value: rooms.toLocaleString(), label: tp("statsRooms"), icon: HabboCatalog }, + ].map(({ value, label, icon: Icon }) => (
+ className="w-10 h-10 rounded-xl flex items-center justify-center mx-auto mb-2" + style={{ background: "color-mix(in srgb, var(--color-primary) 15%, transparent)" }} + > + +
-
- {s.value} + {value}
- {s.label} + {label}
@@ -250,14 +249,14 @@ export default async function Home() { {/* ── 3. Features ── */}
{[ - { img: "/assets/images/icons/star.gif", title: tp("featuresAvatar"), desc: tp("featuresAvatarDesc") }, - { img: "/assets/images/icons/catalog.png", title: tp("featuresFurniture"), desc: tp("featuresFurnitureDesc") }, - { img: "/assets/images/icons/navigation/community.png", title: tp("featuresCommunity"), desc: tp("featuresCommunityDesc") }, - { img: "/assets/images/icons/navigation/bb.png", title: tp("featuresGames"), desc: tp("featuresGamesDesc") }, - ].map((f) => ( + { icon: HabboStar, title: tp("featuresAvatar"), desc: tp("featuresAvatarDesc") }, + { icon: HabboCatalog, title: tp("featuresFurniture"), desc: tp("featuresFurnitureDesc") }, + { icon: HabboCommunity, title: tp("featuresCommunity"), desc: tp("featuresCommunityDesc") }, + { icon: HabboGames, title: tp("featuresGames"), desc: tp("featuresGamesDesc") }, + ].map(({ icon: Icon, title, desc }) => (
- +

- {f.title} + {title}

- {f.desc} + {desc}

))} @@ -283,130 +282,163 @@ export default async function Home() { {/* ── 4. Newest citizens ── */} {latestUsers.length > 0 && ( -
-

- {tp("latestUsers", { count: users.toLocaleString() })} -

-
- {latestUsers.map((u) => ( -
-
-
- {u.username} +
+
+ +

+ {tp("latestUsers", { count: users.toLocaleString() })} +

+
+
+
+ {latestUsers.map((u) => ( +
+
+ {u.username} +
+ + {u.username} +
- - {u.username} - -
- ))} + ))} +
)} {/* ── 5. News ── */} -
-
-

- {tp("latestNews")} -

- +
+
+
+ +

+ {tp("latestNews")} +

+
+ {tp("allNews")}
- {articles.length > 0 ? ( -
- {articles.slice(0, 4).map((a) => ( - -
- {a.image ? ( - - ) : ( -
- )} -
-
-

- {a.title} -

-

- {formatDate(a.createdAt, "date", "")} -

-
- - ))} -
- ) : ( -

{tp("noArticles")}

- )} +
+ {articles.length > 0 ? ( +
+ {articles.slice(0, 4).map((a) => ( + +
+ {a.image ? ( + + ) : ( +
+ )} +
+
+

+ {a.title} +

+

+ {formatDate(a.createdAt, "date", "")} +

+
+ + ))} +
+ ) : ( +

{tp("noArticles")}

+ )} +
{/* ── 6. Online users row ── */} {recentUsers.length > 0 && ( -
-

- - {tp("recentUsers")} -

-
- {recentUsers.slice(0, 10).map((u) => ( -
- {u.username} - - {u.username} - -
- ))} +
+
+ +

+ {tp("recentUsers")} +

+
+
+
+ {recentUsers.slice(0, 12).map((u) => ( +
+ {u.username} + + {u.username} + +
+ ))} +
)} {/* ── 7. Bottom CTA ── */}
-

+

{tp("joinNow", { hotelName })}

@@ -421,30 +453,43 @@ export default async function Home() { boxShadow: "0 4px 24px color-mix(in srgb, var(--color-primary) 35%, transparent)", }} > - + {tp("register")}

{/* ── 8. Recent photos (compact) ── */} {recentPhotos.length > 0 && ( -
-

- {tp("recentPhotos")} -

-
- {recentPhotos.slice(0, 4).map((p) => ( - - - - ))} +
+
+ +

+ {tp("recentPhotos")} +

+
+
+
+ {recentPhotos.slice(0, 4).map((p) => ( + + + + ))} +
)} diff --git a/src/components/mobile-nav.tsx b/src/components/mobile-nav.tsx index de76d8e1..dd6a2fe9 100644 --- a/src/components/mobile-nav.tsx +++ b/src/components/mobile-nav.tsx @@ -1,10 +1,10 @@ "use client"; import { AnimatePresence, motion } from "framer-motion"; -import Image from "next/image"; import { type ReactNode, useRef, useState } from "react"; import { FALLBACK_HOTEL_NAME } from "@/lib/brand"; import { mobileMenuVariants } from "@/lib/motion"; +import { HabboHome } from "@/components/shared/habbo-icons"; interface MobileNavProps { children: ReactNode; @@ -88,13 +88,7 @@ export function MobileNav({ "color-mix(in srgb, var(--color-primary) 12%, transparent)", }} > - + {icon ? ( - + {icon} ) : null} {label} - - {t("home")} + + {t("home")}
@@ -68,7 +72,7 @@ export async function Navigation({ session }: { session: Session | null }) {
} > {t("articles")} @@ -95,7 +99,7 @@ export async function Navigation({ session }: { session: Session | null }) { } > {t("shop")} @@ -109,30 +113,18 @@ export async function Navigation({ session }: { session: Session | null }) { - - {t("leaderboards")} + + {t("leaderboards")} - - {t("radio")} + + {t("radio")} } > {t("helpCenter")} @@ -157,51 +149,27 @@ export async function Navigation({ session }: { session: Session | null }) { {session?.user ? ( <> - - {t("friends")} + + {t("friends")} - - {t("messages")} + + {t("messages")} ) : null} {showMod ? ( - - {t("mod")} + + {t("mod")} ) : null} {showAdmin ? ( - - {t("admin")} + + {t("admin")} ) : null}
@@ -213,19 +181,13 @@ export async function Navigation({ session }: { session: Session | null }) { brandLabel={brandLabel} > - - {t("home")} + + {t("home")} } > {t("articles")} @@ -252,7 +214,7 @@ export async function Navigation({ session }: { session: Session | null }) { } > {t("shop")} @@ -266,30 +228,18 @@ export async function Navigation({ session }: { session: Session | null }) { - - {t("leaderboards")} + + {t("leaderboards")} - - {t("radio")} + + {t("radio")} } > {t("helpCenter")} @@ -314,51 +264,27 @@ export async function Navigation({ session }: { session: Session | null }) { {session?.user ? ( <> - - {t("friends")} + + {t("friends")} - - {t("messages")} + + {t("messages")} ) : null} {showMod ? ( - - {t("mod")} + + {t("mod")} ) : null} {showAdmin ? ( - - {t("admin")} + + {t("admin")} ) : null} @@ -381,12 +307,7 @@ export async function Navigation({ session }: { session: Session | null }) { className="ml-auto flex md:hidden items-center gap-2 shrink-0" aria-label="Home" > - + & { size?: number }; + +function IconSvg({ + children, + size = 24, + viewBox = "0 0 24 24", + ...props +}: IconProps & { viewBox?: string }) { + return ( + + {children} + + ); +} + +export function HabboHome({ size, ...props }: IconProps) { + return ( + + + + + + + + + ); +} + +export function HabboUser({ size, ...props }: IconProps) { + return ( + + + + + + + ); +} + +export function HabboCatalog({ size, ...props }: IconProps) { + return ( + + + + + + + + ); +} + +export function HabboStar({ size, ...props }: IconProps) { + return ( + + + + + + + + + + + + ); +} + +export function HabboCommunity({ size, ...props }: IconProps) { + return ( + + + + + + + + + ); +} + +export function HabboGames({ size, ...props }: IconProps) { + return ( + + + + + + + + + + ); +} + +export function HabboEnter({ size, ...props }: IconProps) { + return ( + + + + + + + ); +} + +export function HabboNews({ size, ...props }: IconProps) { + return ( + + + + + + + + + + ); +} + +export function HabboOnline({ size, ...props }: IconProps) { + return ( + + + + + + + + + ); +} + +export function HabboCamera({ size, ...props }: IconProps) { + return ( + + + + + + + + + ); +} + +export function HabboChat({ size, ...props }: IconProps) { + return ( + + + + + + + + + ); +} + +export function HabboClock({ size, ...props }: IconProps) { + return ( + + + + + + + + ); +} + +export function HabboHeart({ size, ...props }: IconProps) { + return ( + + + + + + + + + + + ); +} + +export function HabboArrowRight({ size, ...props }: IconProps) { + return ( + + + + + ); +} + +export function HabboCog({ size, ...props }: IconProps) { + return ( + + + + + + + + + + + + + ); +} + +export function HabboFurni({ size, ...props }: IconProps) { + return ( + + + + + + + + + + ); +} + +export function HabboDiamond({ size, ...props }: IconProps) { + return ( + + + + + + + + ); +} + +export function HabboCredits({ size, ...props }: IconProps) { + return ( + + + + + + + ); +} + +export function HabboDuckets({ size, ...props }: IconProps) { + return ( + + + + + + + + ); +} + +export function HabboRank({ size, ...props }: IconProps) { + return ( + + + + + + + + ); +} + +const iconMap = { + home: HabboHome, + user: HabboUser, + catalog: HabboCatalog, + star: HabboStar, + community: HabboCommunity, + games: HabboGames, + enter: HabboEnter, + news: HabboNews, + online: HabboOnline, + camera: HabboCamera, + chat: HabboChat, + clock: HabboClock, + heart: HabboHeart, + arrowRight: HabboArrowRight, + cog: HabboCog, + furni: HabboFurni, + diamond: HabboDiamond, + credits: HabboCredits, + duckets: HabboDuckets, + rank: HabboRank, +}; + +export type HabboIconName = keyof typeof iconMap; + +export function HabboIcon({ name, size, ...props }: IconProps & { name: HabboIconName }) { + const Icon = iconMap[name]; + return ; +}