From 2e2a1a2c9d0a1e5011165f97553fd413de07172c Mon Sep 17 00:00:00 2001 From: Gigi Date: Wed, 15 Oct 2025 10:32:16 +0200 Subject: [PATCH] feat: add colored borders to blog post and highlight cards based on relationship - Add level-based colored borders to blog post cards (mine/friends/nostrverse) - Updated BlogPostCard to accept and apply level prop - Modified Explore.tsx to classify blog posts by relationship level - Added CSS styling using settings colors for visual distinction - Highlights already had this feature, now writings have it too --- src/components/BlogPostCard.tsx | 5 ++-- src/components/Explore.tsx | 43 ++++++++++++++++++++------------- src/styles/components/cards.css | 3 +++ 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/components/BlogPostCard.tsx b/src/components/BlogPostCard.tsx index 330220c2..549dddbe 100644 --- a/src/components/BlogPostCard.tsx +++ b/src/components/BlogPostCard.tsx @@ -10,9 +10,10 @@ import { Models } from 'applesauce-core' interface BlogPostCardProps { post: BlogPostPreview href: string + level?: 'mine' | 'friends' | 'nostrverse' } -const BlogPostCard: React.FC = ({ post, href }) => { +const BlogPostCard: React.FC = ({ post, href, level }) => { const profile = useEventModel(Models.ProfileModel, [post.author]) const displayName = profile?.name || profile?.display_name || `${post.author.slice(0, 8)}...${post.author.slice(-4)}` @@ -25,7 +26,7 @@ const BlogPostCard: React.FC = ({ post, href }) => { return (
diff --git a/src/components/Explore.tsx b/src/components/Explore.tsx index ab7559fc..dc2aecd8 100644 --- a/src/components/Explore.tsx +++ b/src/components/Explore.tsx @@ -278,25 +278,33 @@ const Explore: React.FC = ({ relayPool, eventStore, settings, acti }) }, [highlights, activeAccount?.pubkey, followedPubkeys, visibility]) - // Filter blog posts by future dates and visibility + // Filter blog posts by future dates and visibility, and add level classification const filteredBlogPosts = useMemo(() => { const maxFutureTime = Date.now() / 1000 + (24 * 60 * 60) // 1 day from now - return blogPosts.filter(post => { - // Filter out future dates - const publishedTime = post.published || post.event.created_at - if (publishedTime > maxFutureTime) return false - - // Apply visibility filters - const isMine = activeAccount && post.author === activeAccount.pubkey - const isFriend = followedPubkeys.has(post.author) - const isNostrverse = !isMine && !isFriend - - if (isMine && !visibility.mine) return false - if (isFriend && !visibility.friends) return false - if (isNostrverse && !visibility.nostrverse) return false - - return true - }) + return blogPosts + .filter(post => { + // Filter out future dates + const publishedTime = post.published || post.event.created_at + if (publishedTime > maxFutureTime) return false + + // Apply visibility filters + const isMine = activeAccount && post.author === activeAccount.pubkey + const isFriend = followedPubkeys.has(post.author) + const isNostrverse = !isMine && !isFriend + + if (isMine && !visibility.mine) return false + if (isFriend && !visibility.friends) return false + if (isNostrverse && !visibility.nostrverse) return false + + return true + }) + .map(post => { + // Add level classification + const isMine = activeAccount && post.author === activeAccount.pubkey + const isFriend = followedPubkeys.has(post.author) + const level: 'mine' | 'friends' | 'nostrverse' = isMine ? 'mine' : isFriend ? 'friends' : 'nostrverse' + return { ...post, level } + }) }, [blogPosts, activeAccount, followedPubkeys, visibility]) const renderTabContent = () => { @@ -322,6 +330,7 @@ const Explore: React.FC = ({ relayPool, eventStore, settings, acti key={`${post.author}:${post.event.tags.find(t => t[0] === 'd')?.[1]}`} post={post} href={getPostUrl(post)} + level={post.level} /> ))}
diff --git a/src/styles/components/cards.css b/src/styles/components/cards.css index b561a40e..58c4a8e3 100644 --- a/src/styles/components/cards.css +++ b/src/styles/components/cards.css @@ -81,6 +81,9 @@ .explore-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 2rem; margin-top: 2rem; } .blog-post-card { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 12px; overflow: hidden; transition: all 0.3s ease; cursor: pointer; display: flex; flex-direction: column; height: 100%; } .blog-post-card:hover { border-color: var(--color-primary); transform: translateY(-4px); box-shadow: 0 8px 24px rgba(99, 102, 241, 0.15); } +.blog-post-card.level-mine { border-color: color-mix(in srgb, var(--highlight-color-mine, #fde047) 60%, #333); box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight-color-mine, #fde047) 25%, transparent); } +.blog-post-card.level-friends { border-color: color-mix(in srgb, var(--highlight-color-friends, #f97316) 60%, #333); box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight-color-friends, #f97316) 25%, transparent); } +.blog-post-card.level-nostrverse { border-color: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 60%, #333); box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 25%, transparent); } .blog-post-card-image { width: 100%; height: 200px; overflow: hidden; background: var(--color-bg-subtle); display: flex; align-items: center; justify-content: center; } .blog-post-card-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s ease; } .blog-post-card:hover .blog-post-card-image img { transform: scale(1.05); }