Build the Astro site UI
This commit is contained in:
parent
e5a219499e
commit
f27e9ec3fd
84 changed files with 3510 additions and 1949 deletions
69
src/components/ProjectList.astro
Normal file
69
src/components/ProjectList.astro
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
import { getEntry } from 'astro:content';
|
||||
import EntryThumbnail from './EntryThumbnail.astro';
|
||||
import ProjectLinks from './ProjectLinks.astro';
|
||||
import { PROJECT_THUMBNAIL, articlePath, entrySlug } from '../lib/site';
|
||||
|
||||
interface Props {
|
||||
projects: CollectionEntry<'projects'>[];
|
||||
// Opt-in: eagerly load the first thumbnail. Only set when the list is
|
||||
// reliably above the fold. The home and projects-index lists sit below
|
||||
// other sections, so leave this off there.
|
||||
eagerFirstThumbnail?: boolean;
|
||||
}
|
||||
|
||||
const { projects, eagerFirstThumbnail = false } = Astro.props;
|
||||
|
||||
// The `essay` field is a `reference('posts')`, so when present it's always a
|
||||
// `{ collection, id }` shape that `getEntry` resolves to a CollectionEntry.
|
||||
const essayHrefs = new Map<string, string>();
|
||||
for (const project of projects) {
|
||||
const essay = project.data.essay;
|
||||
if (!essay) continue;
|
||||
const resolved = await getEntry(essay);
|
||||
if (resolved) essayHrefs.set(project.id, articlePath(resolved));
|
||||
}
|
||||
---
|
||||
|
||||
<ol class="project-list">
|
||||
{
|
||||
projects.map((project, index) => {
|
||||
const anchor = entrySlug(project);
|
||||
const titleId = `${anchor}-title`;
|
||||
const essayHref = essayHrefs.get(project.id);
|
||||
const primaryHref = essayHref ?? project.data.links[0]?.url;
|
||||
|
||||
return (
|
||||
<li class="project-card" id={anchor}>
|
||||
<EntryThumbnail
|
||||
src={project.data.thumbnail.src}
|
||||
alt={project.data.thumbnail.alt}
|
||||
href={primaryHref}
|
||||
class="project-thumbnail"
|
||||
widths={PROJECT_THUMBNAIL.widths}
|
||||
sizes={PROJECT_THUMBNAIL.sizes}
|
||||
ariaLabel={`Open project: ${project.data.title}`}
|
||||
loading={eagerFirstThumbnail && index === 0 ? 'eager' : 'lazy'}
|
||||
fetchpriority={eagerFirstThumbnail && index === 0 ? 'high' : undefined}
|
||||
/>
|
||||
<article class="project-card__summary">
|
||||
<h3 id={titleId}>
|
||||
{primaryHref ? (
|
||||
<a href={primaryHref}>{project.data.title}</a>
|
||||
) : (
|
||||
project.data.title
|
||||
)}
|
||||
{essayHref && <span class="project-essay-badge">Article</span>}
|
||||
</h3>
|
||||
<p class="project-description">{project.data.description}</p>
|
||||
<p class="project-meta">
|
||||
{project.data.period} · {project.data.technologies.join(', ')}
|
||||
</p>
|
||||
{project.data.links.length > 0 && <ProjectLinks links={project.data.links} />}
|
||||
</article>
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ol>
|
||||
Loading…
Add table
Add a link
Reference in a new issue