Initial Commit

This commit is contained in:
Greg Kilmer
2026-07-04 07:42:24 -04:00
commit 71bffad507
77 changed files with 14437 additions and 0 deletions
@@ -0,0 +1,95 @@
---
/**
* Timeline.astro
* ---------------------------------------------------------------------------
* Vertical timeline for the Experience section. Each entry has a marker (mdi
* icon), a period label, company/title, focus, and rendered markdown body (the
* bullet list from the experience collection entry).
*
* The vertical line is drawn with a pseudo-element; markers sit on it. Entry
* bodies are expandable detail (the spec asks for "expandable detail"). On
* small screens the marker line stays but spacing tightens.
*
* Astro 7 content layer: `render(entry)` returns `{ Content }` (an Astro
* component), which we render with `<Content />` rather than stringifying.
*/
import { type CollectionEntry, render } from 'astro:content';
import Icon from '@components/Icon.astro';
import Reveal from '@components/motion/Reveal.astro';
interface Props {
entries: CollectionEntry<'experience'>[];
}
const { entries } = Astro.props;
// Pre-render each entry to get its Content component (Astro 7 API).
const rendered = await Promise.all(
entries.map(async (e) => ({
entry: e,
Content: (await render(e)).Content,
})),
);
---
<ol class="relative flex flex-col gap-10">
{/* The vertical line. */}
<span
class="absolute left-[1.15rem] top-2 bottom-2 w-px"
style="background: var(--color-border);"
aria-hidden="true"
></span>
{rendered.map(({ entry, Content }, i) => (
<li class="relative pl-12">
<Reveal delay={i * 80}>
{/* Marker */}
<span
class="absolute left-0 top-0 inline-flex h-9 w-9 items-center justify-center rounded-full border-4"
style="background: var(--color-surface-raised); border-color: var(--color-surface);"
aria-hidden="true"
>
<span
class="inline-flex h-9 w-9 items-center justify-center rounded-full"
style="background: color-mix(in srgb, var(--color-accent) 16%, transparent);"
>
<Icon name={entry.data.icon} class="h-4 w-4" />
</span>
</span>
<div class="card flex flex-col gap-3">
<div class="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1">
<h3 style="color: var(--color-text);">{entry.data.company}</h3>
<span class="font-mono text-xs uppercase tracking-[0.18em]" style="color: var(--color-text-subtle);">
{entry.data.period}
</span>
</div>
<p class="font-sans font-semibold" style="color: var(--color-accent);">
{entry.data.title}
</p>
{entry.data.focus && (
<p class="text-sm italic" style="color: var(--color-text-muted);">
Focus: {entry.data.focus}
</p>
)}
<details class="group mt-1">
<summary
class="flex cursor-pointer list-none items-center gap-2 font-sans text-sm font-semibold transition-colors"
style="color: var(--color-accent);"
>
<Icon name="chevron-down" class="h-4 w-4 transition-transform group-open:rotate-180" />
Show details
</summary>
<div
class="mt-4 flex flex-col gap-3 text-sm leading-relaxed [&_ul]:flex [&_ul]:flex-col [&_ul]:gap-2 [&_li]:ml-4 [&_li]:list-disc [&_strong]:font-semibold [&_strong]:text-[var(--color-text)] [&_p:first-child]:mt-0"
style="color: var(--color-text-muted);"
>
<Content />
</div>
</details>
</div>
</Reveal>
</li>
))}
</ol>