From f1021784f31d6457681a7322dc69522b5def8a0c Mon Sep 17 00:00:00 2001 From: highperfocused Date: Mon, 25 May 2026 16:50:58 +0200 Subject: [PATCH] Build modern homepage --- src/components/ArticlePreview.tsx | 70 +++++--- src/components/Header.tsx | 13 +- src/components/LatestArticles.tsx | 28 +-- src/components/LatestInHashtag.tsx | 21 ++- src/components/Layout.tsx | 10 +- src/components/TrendingTags.tsx | 14 +- src/index.css | 26 +-- src/pages/HomePage.tsx | 277 +++++++++++++++++++++++++---- 8 files changed, 353 insertions(+), 106 deletions(-) diff --git a/src/components/ArticlePreview.tsx b/src/components/ArticlePreview.tsx index 957d585..be09992 100644 --- a/src/components/ArticlePreview.tsx +++ b/src/components/ArticlePreview.tsx @@ -16,6 +16,38 @@ interface ArticlePreviewProps { featured?: boolean; } +function ArticleVisual({ image, title, featured }: { image?: string; title: string; featured?: boolean }) { + const baseClass = featured ? 'aspect-[16/10] md:aspect-auto md:h-full md:min-h-[320px]' : 'aspect-[16/10]'; + + if (image) { + return ( +
+ {title} +
+ ); + } + + return ( +
+
+
+
+
+

Nostr Article

+

+ {title} +

+
+ +
+
+ ); +} + export function ArticlePreview({ post, variant = 'default', showAuthor = true, featured = false }: ArticlePreviewProps) { const { data: author } = useAuthor(post.pubkey); const metadata = author?.metadata; @@ -64,24 +96,16 @@ export function ArticlePreview({ post, variant = 'default', showAuthor = true, f if (featured) { return ( - +
- {image && ( -
- {title} -
- )} -
+ +
-

+

{title}

{summary && ( -

+

{summary}

)} @@ -109,7 +133,7 @@ export function ArticlePreview({ post, variant = 'default', showAuthor = true, f {hashtags.length > 0 && (
{hashtags.map((tag: string) => ( - + #{tag} ))} @@ -126,22 +150,14 @@ export function ArticlePreview({ post, variant = 'default', showAuthor = true, f // Default layout - vertical card return ( - - {image && ( -
- {title} -
- )} + + -

+

{title}

{summary && ( -

+

{summary}

)} @@ -169,7 +185,7 @@ export function ArticlePreview({ post, variant = 'default', showAuthor = true, f {hashtags.length > 0 && (
{hashtags.map((tag: string) => ( - + #{tag} ))} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 9ae06d5..14452bf 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -9,19 +9,22 @@ export function Header() { const { user } = useCurrentUser(); return ( -
+
{/* Logo / Brand */}
- + + + + zelo.news {/* Desktop Navigation */} {user && ( -
diff --git a/src/components/LatestArticles.tsx b/src/components/LatestArticles.tsx index a9e1444..6ba6ce5 100644 --- a/src/components/LatestArticles.tsx +++ b/src/components/LatestArticles.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { Card, CardHeader } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; -import { Newspaper } from 'lucide-react'; +import { ArrowRight, Newspaper } from 'lucide-react'; import { useLongFormContentNotes } from '@/hooks/useLongFormContentNotes'; import { ArticlePreview } from '@/components/ArticlePreview'; @@ -16,8 +16,10 @@ export function LatestArticles() { if (isLoading) { return (
-
- +
+
+ +
@@ -55,14 +57,20 @@ export function LatestArticles() { return (
{/* Section Header */} -
- -
-

Latest Articles

-

- Discover the most recent stories from the community -

+
+
+
+ +
+
+

Fresh from the network

+

Latest Articles

+

+ Discover the most recent stories from the community +

+
+
{/* Featured Post - Full Width */} diff --git a/src/components/LatestInHashtag.tsx b/src/components/LatestInHashtag.tsx index 2859d00..c389b81 100644 --- a/src/components/LatestInHashtag.tsx +++ b/src/components/LatestInHashtag.tsx @@ -82,8 +82,12 @@ export function LatestInHashtag({ hashtags, icon, title }: LatestInHashtagProps) if (isLoading) { return (
-
- {icon || } +
+ {icon || ( + + + + )}
@@ -117,10 +121,15 @@ export function LatestInHashtag({ hashtags, icon, title }: LatestInHashtagProps) return (
{/* Section Header */} -
- {icon || } +
+ {icon || ( + + + + )}
-

+

Topic stream

+

{title || (hashtagArray.length === 1 ? `Latest in #${hashtagArray[0]}` : `Latest in ${hashtagArray.map(h => `#${h}`).join(', ')}` @@ -135,7 +144,7 @@ export function LatestInHashtag({ hashtags, icon, title }: LatestInHashtagProps) onClick={() => navigate(`/tag/${encodeURIComponent(hashtagArray[0])}`)} variant="outline" size="default" - className="gap-1" + className="gap-1 border-zinc-950/15 bg-white/70 backdrop-blur hover:bg-white dark:border-white/15 dark:bg-white/10 dark:hover:bg-white/15" > View All diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 123627a..e0e7eec 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -18,10 +18,18 @@ export function Layout({ children }: LayoutProps) { {/* Mobile-only bottom navigation */} {/* Add extra bottom padding on mobile so footer content can scroll above the BottomNav overlay */} -