diff --git a/package.json b/package.json index 53fc146..0d98c51 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "siteforge", "private": true, - "version": "2.9.2", + "version": "2.9.3", "type": "module", "scripts": { "dev": "vite", diff --git a/src/App.css b/src/App.css index 08d3d2c..5afc2bf 100644 --- a/src/App.css +++ b/src/App.css @@ -13126,15 +13126,28 @@ .study-status-badge.planned { background: rgba(255, 255, 255, 0.05); color: #9a9486; border: 1px solid rgba(255, 255, 255, 0.15); } .study-status-badge.complete { background: rgba(120, 170, 130, 0.16); color: #8fc79b; border: 1px solid rgba(120, 170, 130, 0.45); } -.highlight-group + .highlight-group { margin-top: 2.5rem; } -.highlight-group-title { - margin: 0 0 1rem; - font-size: 1.05rem; - letter-spacing: 0.04em; - color: #c9a84c; - border-bottom: 1px solid rgba(201, 168, 76, 0.22); - padding-bottom: 0.5rem; +.highlight-tabs { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.6rem; + margin: 0 0 1.75rem; } +.highlight-tab { + background: transparent; + color: #b9b09b; + border: 1px solid rgba(201, 168, 76, 0.3); + border-radius: 999px; + padding: 0.5rem 1.1rem; + font: inherit; + font-size: 0.9rem; + cursor: pointer; + transition: border-color 200ms, color 200ms, background 200ms; +} +.highlight-tab:hover { color: #f0ead8; border-color: rgba(201, 168, 76, 0.6); } +.highlight-tab--active { background: #c9a84c; border-color: #c9a84c; color: #0a0a08; } +.highlight-tab-count { opacity: 0.7; font-size: 0.8em; margin-left: 0.25rem; } +.highlight-more { display: flex; justify-content: center; margin-top: 1.5rem; } .admin-tabs--page { margin: 0 0 1.5rem; padding-bottom: 1rem; border-bottom: 1px solid #2a2518; } .admin-tabs--page .admin-tab { font-size: 0.8rem; padding: 0.45rem 0.9rem; } diff --git a/src/App.tsx b/src/App.tsx index 35822bb..e9b84b1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -743,20 +743,25 @@ function HighlightCard({ link }: { link: PodcastFeaturedLink }) { return {inner} } -// Highlights are grouped by the series they belong to, so each book being studied gets its own row. +const HIGHLIGHTS_PREVIEW_COUNT = 6 + +// Highlights are grouped by the series they belong to, one tab per series, so a long series +// never pushes the others down the page. Each tab previews the newest few with a "show all" option. function PodcastHighlightsSection({ content }: { content: SiteContent }) { + const [activeKey, setActiveKey] = useState('') + const [expanded, setExpanded] = useState>({}) const links = [...(content.podcastFeaturedLinks ?? [])].reverse() if (links.length === 0) return null const laneOf = (link: PodcastFeaturedLink) => (link.lane === 'second' ? 'second' : link.lane === 'general' ? 'general' : 'primary') - const secondTitle = content.secondSeries?.title?.trim() const groups = [ { key: 'primary', title: content.seriesTitle, links: links.filter(link => laneOf(link) === 'primary') }, - { key: 'second', title: secondTitle, links: links.filter(link => laneOf(link) === 'second') }, + { key: 'second', title: content.secondSeries?.title?.trim() || 'Second Series', links: links.filter(link => laneOf(link) === 'second') }, { key: 'general', title: 'More Highlights', links: links.filter(link => laneOf(link) === 'general') }, ].filter(group => group.links.length > 0) - // Only label the rows when there is more than one to tell apart - const showGroupTitles = groups.length > 1 + const active = groups.find(group => group.key === activeKey) ?? groups[0] + const isExpanded = expanded[active.key] === true + const shown = isExpanded ? active.links : active.links.slice(0, HIGHLIGHTS_PREVIEW_COUNT) return (
@@ -765,14 +770,32 @@ function PodcastHighlightsSection({ content }: { content: SiteContent }) { ✦ Podcast Highlights{' '} ✦ - {groups.map(group => ( -
- {showGroupTitles &&

{group.title}

} -
- {group.links.map(link => )} -
+ {groups.length > 1 && ( +
+ {groups.map(group => ( + + ))}
- ))} + )} +
+ {shown.map(link => )} +
+ {active.links.length > HIGHLIGHTS_PREVIEW_COUNT && ( +
+ +
+ )}
)