Skip to content

Commit

Permalink
#140 Add '/tag/{string}' page (#142)
Browse files Browse the repository at this point in the history
* add [tag].astro boilerplate page

* create BlogPostEntry.vue

* add BlogPostEntry.vue to pages

* remove console.log

* gotta be /tag instead of /tags
  • Loading branch information
SebinSong authored Aug 6, 2024
1 parent b0f3462 commit 4c58d24
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 15 deletions.
88 changes: 88 additions & 0 deletions src/components/BlogPostEntry.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<article class="c-article">
<a class="c-link-wrapper" :href="postUrl">
<img class="c-article-image has-deep-box-shadow" :src="imgSrc" />
<h2 class="c-blog-title">{{ title }}</h2>
<p class="c-blog-desc">{{ description }}</p>
<div class="c-info">{{ author }}<time v-if="createdDate">{{ createdDate }}</time></div>
</a>
</article>
</template>

<script setup>
import { resolvePath } from '@/utils/helpers.js'
const props = defineProps({
postFrontmatter: {
type: Object,
required: true
}
})
const {
permalink,
title,
description,
author = 'Greg Slepak',
date: createdDate,
image
} = props.postFrontmatter
const postUrl = resolvePath(permalink)
const imgSrc = resolvePath(image) || resolvePath('/images/' + permalink + '.jpeg')
</script>

<style lang="scss" scoped>
@import "../styles/_variables";
.c-article {
border-bottom: 1px solid #D0DEEA;
margin-bottom: 5rem;
img {
margin: 2rem auto;
}
.c-blog-title {
font-size: 2rem;
font-weight: 600;
margin: 1rem 0 1rem 0;
}
.c-blog-desc {
margin-bottom: 1.5rem;
}
&-image {
background-color: #D0DEEA;
border-radius: .5rem;
width: 100%;
aspect-ratio: 2 / 1;
object-fit: cover;
transition: transform 250ms ease-out;
}
.c-info {
font-weight: .5rem;
margin: 1rem 0 3rem 0;
color: #939393;
time::before {
content: '';
}
}
}
.c-link-wrapper {
&:hover,
&:focus {
.c-blog-title {
text-decoration: underline;
}
.c-article-image {
transform: scale(1.02);
}
}
}
</style>
2 changes: 1 addition & 1 deletion src/pages/[...blog].astro
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ function prepFootnotes () {

section {
@include until($desktop) {
padding: 0 2rem;
padding: 0 1rem;
}
}

Expand Down
19 changes: 5 additions & 14 deletions src/pages/blog/[...page].astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
import Layout from '@/layouts/DefaultLayout.astro';
import BlogPostEntry from '@/components/BlogPostEntry.vue'
import { resolvePath } from '@/utils/helpers.js'
export async function getStaticPaths({ paginate }) {
const posts = (await Astro.glob('../../posts/*.{md,mdx}')).sort(
Expand All @@ -19,19 +20,9 @@ const { data, lastPage, url } = page
</section>

<section class="blog-wrapper" v-if="posts">
{data.map((article: any) => {
const imgSrc = resolvePath(article.frontmatter.image) || resolvePath('/images/' + article.frontmatter.permalink + '.jpeg')
return (
<article class="c-article">
<a href={resolvePath(article.frontmatter.permalink)}>
<img class="c-article-image has-deep-box-shadow" src={imgSrc}/>
<h2 class="c-blog-title">{article.frontmatter.title}</h2>
<p>{article.frontmatter.description || 'TODO'}</p>
<div class="c-info">{article.frontmatter.author || "Greg Slepak"}<time v-if="article.frontmatter.date">{ article.frontmatter.date }</time></div>
</a>
</article>
)
})}
{
data.map((article: any) => <BlogPostEntry client:only="vue" postFrontmatter={article.frontmatter} />)
}
<div class="pagination">
<a class={ url.prev ? '' : 'inactive' } href={url.prev ? '/groupincome.org' + url.prev : null}>
<i class="icon-chevron-left"></i>
Expand Down Expand Up @@ -169,7 +160,7 @@ const { data, lastPage, url } = page

section {
@include until($desktop) {
padding: 0 2rem;
padding: 0 1rem;
}
}

Expand Down
76 changes: 76 additions & 0 deletions src/pages/tag/[tag].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
import Layout from '@/layouts/DefaultLayout.astro'
import BlogPostEntry from '@/components/BlogPostEntry.vue'
import { resolvePath, uniq } from '@/utils/helpers.js'
import { sortedPosts } from '@/utils/sort'
export async function getStaticPaths () {
const allPosts = sortedPosts(await Astro.glob('../../posts/*.{md,mdx}'))
const uniqueTags = uniq(
allPosts.map((post: any) => post.frontmatter?.tags || []).flat()
)
return uniqueTags.map((tag: string) => {
const filteredPosts = allPosts.filter(
(post: any) => Array.isArray(post.frontmatter.tags) && post.frontmatter.tags.includes(tag)
)
return {
params: { tag },
props: { posts: filteredPosts }
}
})
}
const { tag } = Astro.params
const { posts } = Astro.props
---

<Layout>
<div class="c-wrapper">
<header class="c-header">
<h1 class="is-title-3 page-title">Posts Tagged: <span class="c-tag-name">'{tag}'</span></h1>
</header>

<div class="c-post-list">
{
Boolean(posts.length) &&
posts.map((post: any) => <BlogPostEntry client:only="vue" postFrontmatter={post.frontmatter} />)
}
</div>
</div>
</Layout>

<style lang="scss" scoped>
@import "../../styles/_variables";

.c-wrapper {
@include page-wrapper-common;
}

.c-header {
display: flex;
width: 100%;
margin-bottom: 4rem;

@include tablet {
justify-content: center;
margin-bottom: 6rem;
}
}

.page-title {
font-weight: 600;
}

.c-post-list {
position: relative;
max-width: 45rem;
margin: 0 auto;
}

.c-tag-name {
display: inline-block;
margin-left: 0.5rem;
}
</style>
18 changes: 18 additions & 0 deletions src/styles/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@
}
}

@mixin page-wrapper-common {
position: relative;
display: block;
width: 100%;
max-width: $maxDesktop;
margin: 0 auto;

padding: 2rem 1rem;

@include tablet {
padding: 4rem 1rem;
}

@include desktop {
padding: 6rem 1rem;
}
}

%unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
Expand Down
4 changes: 4 additions & 0 deletions src/utils/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ export function resolvePath (relPath = '') {
relPath = relPath.startsWith('/') ? relPath.slice(1) : relPath
return `${import.meta.env.BASE_URL}${relPath}`
}

export function uniq (array) {
return Array.from(new Set(array))
}

0 comments on commit 4c58d24

Please sign in to comment.