152 lines
3.2 KiB
Plaintext
152 lines
3.2 KiB
Plaintext
---
|
|
import { type CollectionEntry, getCollection } from 'astro:content';
|
|
|
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
|
|
|
import ContactCTA from '../../components/ContactCTA.astro';
|
|
import Hero from '../../components/Hero.astro';
|
|
import Icon from '../../components/Icon.astro';
|
|
import Pill from '../../components/Pill.astro';
|
|
|
|
interface Props {
|
|
entry: CollectionEntry<'work'>;
|
|
}
|
|
|
|
// This is a dynamic route that generates a page for every Markdown file in src/content/
|
|
// Read more about dynamic routes and this `getStaticPaths` function in the Astro docs:
|
|
// https://docs.astro.build/en/core-concepts/routing/#dynamic-routes
|
|
export async function getStaticPaths() {
|
|
const work = await getCollection('work');
|
|
return work.map((entry) => ({
|
|
params: { slug: entry.slug },
|
|
props: { entry },
|
|
}));
|
|
}
|
|
|
|
const { entry } = Astro.props;
|
|
const { Content } = await entry.render();
|
|
---
|
|
|
|
<BaseLayout title={entry.data.title} description={entry.data.description}>
|
|
<div class="stack gap-20">
|
|
<div class="stack gap-15">
|
|
<header>
|
|
<div class="wrapper stack gap-2">
|
|
<a class="back-link" href="/work/"><Icon icon="arrow-left" /> Work</a>
|
|
<Hero title={entry.data.title} align="start">
|
|
<div class="details">
|
|
<div class="tags">
|
|
{entry.data.tags.map((t) => <Pill>{t}</Pill>)}
|
|
</div>
|
|
<p class="description">{entry.data.description}</p>
|
|
</div>
|
|
</Hero>
|
|
</div>
|
|
</header>
|
|
<main class="wrapper">
|
|
<div class="stack gap-10 content">
|
|
{entry.data.img && <img src={entry.data.img} alt={entry.data.img_alt || ''} />}
|
|
<div class="content">
|
|
<Content />
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
<ContactCTA />
|
|
</div>
|
|
</BaseLayout>
|
|
|
|
<style>
|
|
header {
|
|
padding-bottom: 2.5rem;
|
|
border-bottom: 1px solid var(--gray-800);
|
|
}
|
|
|
|
.back-link {
|
|
display: none;
|
|
}
|
|
|
|
.details {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 0.5rem;
|
|
gap: 1.5rem;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.tags {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.description {
|
|
font-size: var(--text-lg);
|
|
max-width: 54ch;
|
|
}
|
|
|
|
.content {
|
|
max-width: 65ch;
|
|
margin-inline: auto;
|
|
}
|
|
|
|
.content > :global(* + *) {
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.content :global(h1),
|
|
.content :global(h2),
|
|
.content :global(h3),
|
|
.content :global(h4),
|
|
.content :global(h5) {
|
|
margin: 1.5rem 0;
|
|
}
|
|
|
|
.content :global(img) {
|
|
border-radius: 1.5rem;
|
|
box-shadow: var(--shadow-sm);
|
|
background: var(--gradient-subtle);
|
|
border: 1px solid var(--gray-800);
|
|
}
|
|
|
|
.content :global(blockquote) {
|
|
font-size: var(--text-lg);
|
|
font-family: var(--font-brand);
|
|
font-weight: 600;
|
|
line-height: 1.1;
|
|
padding-inline-start: 1.5rem;
|
|
border-inline-start: 0.25rem solid var(--accent-dark);
|
|
color: var(--gray-0);
|
|
}
|
|
|
|
.back-link,
|
|
.content :global(a) {
|
|
text-decoration: 1px solid underline transparent;
|
|
text-underline-offset: 0.25em;
|
|
transition: text-decoration-color var(--theme-transition);
|
|
}
|
|
|
|
.back-link:hover,
|
|
.back-link:focus,
|
|
.content :global(a:hover),
|
|
.content :global(a:focus) {
|
|
text-decoration-color: currentColor;
|
|
}
|
|
|
|
@media (min-width: 50em) {
|
|
.back-link {
|
|
display: block;
|
|
align-self: flex-start;
|
|
}
|
|
|
|
.details {
|
|
flex-direction: row;
|
|
gap: 2.5rem;
|
|
}
|
|
|
|
.content :global(blockquote) {
|
|
font-size: var(--text-2xl);
|
|
}
|
|
}
|
|
</style>
|