Next and previous buttons for posts and projects

Sort connections by date published
Move some styling to SCSS files
This commit is contained in:
Michał 2024-05-24 14:35:56 +01:00
parent c843050c8f
commit e9d1191ec1
11 changed files with 134 additions and 96 deletions

View file

@ -3,7 +3,7 @@ interface Props {
post: any, post: any,
} }
const { post } = Astro.props; const { post, prev, next, base } = Astro.props;
const { Content } = await post.render(); const { Content } = await post.render();
--- ---
@ -12,7 +12,7 @@ const { Content } = await post.render();
<h1>{post.data.title}</h1> <h1>{post.data.title}</h1>
<p>{post.data.description}</p> <p>{post.data.description}</p>
<ul id="tags"> <ul id="tags" class="pill-list">
{post.data.tags.map((item: string) => ( <li class="pill">#{item}</li> ))} {post.data.tags.map((item: string) => ( <li class="pill">#{item}</li> ))}
</ul> </ul>
@ -25,29 +25,16 @@ const { Content } = await post.render();
<hr> <hr>
<ul id="controls"> <ul id="controls">
<li><a class="button" href="/">Prev</a></li> <li>{prev && <a class="button" href=`${base}/${prev.slug}` id="prev">{prev.data.title}</a>}</li>
<li><a class="button" href="/">Next</a></li> <li>{next && <a class="button" href=`${base}/${next.slug}` id="next">{next?.data.title}</a>}</li>
</ul> </ul>
<style is:global lang="scss"> <style is:global lang="scss">
@import "../styles/vars"; @import "../styles/vars";
#home { #home { margin-bottom: 32px; }
margin-bottom: 32px; #tags { padding-top: 16px; }
} #markdown { flex-grow: 1; }
#tags {
padding-top: 16px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 8px;
}
#markdown {
flex-grow: 1;
}
#controls { #controls {
display: flex; display: flex;

View file

@ -1,6 +1,5 @@
--- ---
import { getCollection } from 'astro:content'; import { getPosts} from "../utils";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import Card from "../components/Card.astro"; import Card from "../components/Card.astro";
import Music from "../components/Music.astro"; import Music from "../components/Music.astro";
@ -8,8 +7,8 @@ import Music from "../components/Music.astro";
const tools = ["Proxmox", "JetBrain IDEs", "Docker", "Linux", "SQLite", "Postgres", "MySQL"]; const tools = ["Proxmox", "JetBrain IDEs", "Docker", "Linux", "SQLite", "Postgres", "MySQL"];
const languages = ["Go", "Python", "HTML", "CSS", "Sass", "TypeScript", "JavaScript", "Scratch", "PHP", "SQL", "Bash"]; const languages = ["Go", "Python", "HTML", "CSS", "Sass", "TypeScript", "JavaScript", "Scratch", "PHP", "SQL", "Bash"];
const frameworks = ["Gin", "Echo", "Flask", "Svelte", "Astro", "raylib"]; const frameworks = ["Gin", "Echo", "Flask", "Svelte", "Astro", "raylib"];
const projects = await getCollection('projects'); const projects = await getPosts("projects");
const posts = await getCollection('posts'); const posts = await getPosts("posts");
--- ---
<Layout title="Leggy Land" src="/banner-alt.webp" alt="Temporary Banner"> <Layout title="Leggy Land" src="/banner-alt.webp" alt="Temporary Banner">
@ -67,7 +66,7 @@ const posts = await getCollection('posts');
<section> <section>
<h2>Projects</h2> <h2>Projects</h2>
<ul class="project-list"> <ul class="project-list">
{projects.map(project => ( {projects.slice(0, 2).map(project => (
<Card <Card
href=`/projects/${project.slug}` href=`/projects/${project.slug}`
title={project.data.title} title={project.data.title}
@ -75,13 +74,13 @@ const posts = await getCollection('posts');
/> />
))} ))}
</ul> </ul>
<a class="button" id="see-all-projects" href="/projects">See Projects</a> <a class="button" id="see-all-projects" href="/projects">All Projects</a>
</section> </section>
<section> <section>
<h2>Recent Posts</h2> <h2>Recent Posts</h2>
<ul class="project-list"> <ul class="project-list">
{posts.map(project => ( {posts.slice(0, 2).map(project => (
<Card <Card
href=`/posts/${project.slug}` href=`/posts/${project.slug}`
title={project.data.title} title={project.data.title}
@ -89,31 +88,13 @@ const posts = await getCollection('posts');
/> />
))} ))}
</ul> </ul>
<a class="button" id="see-all-posts" href="/posts">See Posts</a> <a class="button" id="see-all-posts" href="/posts">All Posts</a>
</section> </section>
</Layout> </Layout>
<style lang="scss"> <style lang="scss">
@import "../styles/vars.scss"; @import "../styles/vars.scss";
.pill-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 8px;
> li {
list-style: none;
}
}
.project-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr));
gap: 16px;
padding: 0;
}
#see-all-projects, #see-all-projects,
#see-all-posts { #see-all-posts {
margin-top: 16px; margin-top: 16px;

View file

@ -14,7 +14,5 @@ import Layout from "../layouts/Layout.astro";
</Layout> </Layout>
<style lang="scss"> <style lang="scss">
#home { #home { margin-bottom: 32px; }
margin-bottom: 32px; </style>
}
</style>

View file

@ -1,22 +1,24 @@
--- ---
import { getCollection } from "astro:content"; import { getPosts } from "../../utils";
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import Markdown from "../../layouts/Markdown.astro"; import Markdown from "../../layouts/Markdown.astro";
export async function getStaticPaths() { export async function getStaticPaths() {
const collection = await getCollection('posts') const collection = await getPosts("posts");
return collection.map(post => {
return { return collection.map((post, i) => ({
params: { slug: post.slug }, params: { slug: post.slug },
props: { post: post }, props: {
}; post: post,
}); prev: i > 0 ? collection[i - 1] : undefined,
next: i < collection.length - 1 ? collection[i + 1] : undefined
}
}));
} }
const { post } = Astro.props; const { post, prev, next } = Astro.props;
--- ---
<Layout title="Leggy Land" src={post.data.image.url} alt={post.data.image.alt}> <Layout title="Leggy Land" src={post.data.image.url} alt={post.data.image.alt}>
<Markdown post={post} /> <Markdown {post} {prev} {next} base="/posts" />
</Layout> </Layout>

View file

@ -11,10 +11,15 @@ const posts = await getCollection('posts');
<a class="button" id="home" href="/">Home</a> <a class="button" id="home" href="/">Home</a>
<h1>All Posts</h1> <h1>All Posts</h1>
<p>Some regrettable, some not so bad...</p> <p>Egg Book</p>
<hr> <hr>
<!--<div class="search-box">-->
<!-- <label for="search">Search</label>-->
<!-- <input type="text" id="search" name="search" />-->
<!--</div>-->
<ul role="list" class="project-list"> <ul role="list" class="project-list">
{posts.map(project => ( {posts.map(project => (
<Card <Card
@ -29,14 +34,57 @@ const posts = await getCollection('posts');
<style lang="scss"> <style lang="scss">
@import "../../styles/vars.scss"; @import "../../styles/vars.scss";
.project-list { .search-box {
display: grid; padding: 8px 0 32px;
grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr));
gap: 16px; width: 100%;
padding: 0;
position: relative;
> label {
padding: 0 8px;
position: absolute;
top: -4px;
left: 20px;
background: $dark;
pointer-events: none;
z-index: +1;
}
> input {
padding: 0 16px;
width: 100%;
height: 35px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 8px;
text-decoration: none;
border-radius: 9999px;
border: 2px solid $gray;
background-color: $dark;
color: $light;
overflow: hidden;
&:hover {
border: 2px solid lighten($gray, 1%);
}
&:focus-visible {
outline: 0 solid transparent;
border: 2px solid $light;
}
}
} }
#home { #home { margin-bottom: 32px; }
margin-bottom: 32px;
}
</style> </style>

View file

@ -1,23 +1,24 @@
--- ---
import { getCollection } from 'astro:content'; import { getPosts } from "../../utils";
import Layout from "../../layouts/Layout.astro"; import Layout from "../../layouts/Layout.astro";
import Markdown from "../../layouts/Markdown.astro"; import Markdown from "../../layouts/Markdown.astro";
export async function getStaticPaths() { export async function getStaticPaths() {
const collection = await getCollection('projects') const collection = await getPosts("projects");
return collection.map(project => {
return { return collection.map((post, i) => ({
params: { slug: project.slug }, params: { slug: post.slug },
props: { project: project }, props: {
}; post: post,
}); prev: i > 0 ? collection[i - 1] : undefined,
next: i < collection.length - 1 ? collection[i + 1] : undefined
}
}));
} }
const { project } = Astro.props; const { post, prev, next } = Astro.props;
--- ---
<Layout title="Leggy Land" src={project.data.image.url} alt={project.data.image.alt}> <Layout title="Leggy Land" src={post.data.image.url} alt={post.data.image.alt}>
<Markdown post={project} /> <Markdown {post} {prev} {next} base="/projects" />
</Layout> </Layout>

View file

@ -10,7 +10,7 @@ const projects = await getCollection('projects');
<Layout title="Leggy Land" src="/banner-alt.webp" alt="Temporary Banner"> <Layout title="Leggy Land" src="/banner-alt.webp" alt="Temporary Banner">
<a class="button" id="home" href="/">Home</a> <a class="button" id="home" href="/">Home</a>
<h1>All Projects</h1> <h1>All Projects</h1>
<p>Too many, so many</p> <p>Come back next week for 4 new projects!</p>
<hr> <hr>
@ -26,16 +26,5 @@ const projects = await getCollection('projects');
</Layout> </Layout>
<style lang="scss"> <style lang="scss">
@import "../../styles/vars.scss"; #home { margin-bottom: 32px; }
.project-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr));
gap: 16px;
padding: 0;
}
#home {
margin-bottom: 32px;
}
</style> </style>

View file

@ -0,0 +1,11 @@
.pill-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 8px;
// if the anchor tag has the pill class
> li {
list-style: none;
}
}

View file

@ -0,0 +1,8 @@
.project-list {
padding: 0;
display: flex;
flex-direction: column;
gap: 16px;
}

View file

@ -3,4 +3,6 @@
@import "button"; @import "button";
@import "pill"; @import "pill";
@import "pill_list";
@import "project_list";
@import "main"; @import "main";

11
src/utils.ts Normal file
View file

@ -0,0 +1,11 @@
import { type ContentEntryMap, getCollection } from "astro:content";
// https://github.com/hellotham/hello-astro/blob/e05706cf488bcec6e4c5494a622eedfc4e47d763/src/config.ts#L55C1-L62C2
export async function getPosts(collection: keyof ContentEntryMap) {
const posts = await getCollection(collection, ({ data }) => {
return data.draft !== true
})
return posts.sort((a, b) =>
a.data.pubDate && b.data.pubDate ? +b.data.pubDate - +a.data.pubDate : 0
)
}