mirror of
https://github.com/prdlk/website.git
synced 2026-08-02 17:31:41 +00:00
refactor(ui): rename blog post and note components for consistency
This commit is contained in:
@@ -70,8 +70,8 @@ const socialImageURL = new URL(ogImage ? ogImage : "/social-card.png", Astro.url
|
|||||||
<link href="/sitemap-index.xml" rel="sitemap" />
|
<link href="/sitemap-index.xml" rel="sitemap" />
|
||||||
|
|
||||||
{/* RSS auto-discovery */}
|
{/* RSS auto-discovery */}
|
||||||
<link href="/rss.xml" title="Blog" rel="alternate" type="application/rss+xml" />
|
<link href="/rss.xml" title="Writing" rel="alternate" type="application/rss+xml" />
|
||||||
<link href="/notes/rss.xml" title="Notes" rel="alternate" type="application/rss+xml" />
|
<link href="/projects/rss.xml" title="Projects" rel="alternate" type="application/rss+xml" />
|
||||||
|
|
||||||
{/* Webmentions */}
|
{/* Webmentions */}
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
import { getEntries } from "astro:content";
|
||||||
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
experiences: CollectionEntry<"projects" | "writing" | "speaking">["data"]["experiences"];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { experiences } = Astro.props;
|
||||||
|
const entries = experiences.length ? await getEntries(experiences) : [];
|
||||||
|
---
|
||||||
|
|
||||||
|
{
|
||||||
|
entries.length > 0 && (
|
||||||
|
<ul class="flex flex-wrap gap-2">
|
||||||
|
{entries.map((exp) => (
|
||||||
|
<li>
|
||||||
|
<a class="cactus-link inline-block" href={`/experience/${exp.id}/`}>
|
||||||
|
{exp.data.title}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
import { streamOrigin } from "@/site.config";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
videoId: string;
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { videoId, title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="aspect-video overflow-hidden rounded-md">
|
||||||
|
<iframe
|
||||||
|
class="h-full w-full border-0"
|
||||||
|
src={`${streamOrigin}/${videoId}/iframe`}
|
||||||
|
title={title}
|
||||||
|
loading="lazy"
|
||||||
|
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
|
||||||
|
allowfullscreen></iframe>
|
||||||
|
</div>
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import type { CollectionEntry } from "astro:content";
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
import ExperienceTags from "@/components/ExperienceTags.astro";
|
||||||
import FormattedDate from "@/components/FormattedDate.astro";
|
import FormattedDate from "@/components/FormattedDate.astro";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
content: CollectionEntry<"post">;
|
content: CollectionEntry<"writing">;
|
||||||
readingTime: string;
|
readingTime: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,34 +52,9 @@ const dateTimeOptions: Intl.DateTimeFormatOptions = {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
!!data.tags?.length && (
|
!!data.experiences?.length && (
|
||||||
<div class="mt-2">
|
<div class="mt-3">
|
||||||
<svg
|
<ExperienceTags experiences={data.experiences} />
|
||||||
aria-hidden="true"
|
|
||||||
class="inline-block h-6 w-6"
|
|
||||||
fill="none"
|
|
||||||
focusable="false"
|
|
||||||
stroke="var(--color-muted)"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="1.5"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path d="M0 0h24v24H0z" fill="none" stroke="none" />
|
|
||||||
<path d="M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z" />
|
|
||||||
<path d="M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116" />
|
|
||||||
<path d="M6 9h-.01" />
|
|
||||||
</svg>
|
|
||||||
{data.tags.map((tag, i) => (
|
|
||||||
<>
|
|
||||||
{/* prettier-ignore */}
|
|
||||||
<span class="contents">
|
|
||||||
<a class="cactus-link inline-block before:content-['#']" data-pagefind-filter={`tag:${tag}`} href={`/tags/${tag}/`}><span class="sr-only">View more blogs with the tag </span>{tag}
|
|
||||||
</a>{i < data.tags.length - 1 && ", "}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { HTMLTag, Polymorphic } from "astro/types";
|
|||||||
import FormattedDate from "@/components/FormattedDate.astro";
|
import FormattedDate from "@/components/FormattedDate.astro";
|
||||||
|
|
||||||
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
|
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
|
||||||
post: CollectionEntry<"post">;
|
post: CollectionEntry<"writing">;
|
||||||
withDesc?: boolean;
|
withDesc?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ const { as: Tag = "div", post, withDesc = false } = Astro.props;
|
|||||||
<FormattedDate class="text-muted min-w-30 font-semibold" date={post.data.publishDate} />
|
<FormattedDate class="text-muted min-w-30 font-semibold" date={post.data.publishDate} />
|
||||||
<Tag>
|
<Tag>
|
||||||
{post.data.draft && <span class="text-red-500">(Draft) </span>}
|
{post.data.draft && <span class="text-red-500">(Draft) </span>}
|
||||||
<a class="cactus-link" href={`/posts/${post.id}/`}>
|
<a class="cactus-link" href={`/writing/${post.id}/`}>
|
||||||
{post.data.title}
|
{post.data.title}
|
||||||
</a>
|
</a>
|
||||||
</Tag>
|
</Tag>
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
---
|
|
||||||
import { type CollectionEntry, render } from "astro:content";
|
|
||||||
import type { HTMLTag, Polymorphic } from "astro/types";
|
|
||||||
import FormattedDate from "@/components/FormattedDate.astro";
|
|
||||||
|
|
||||||
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
|
|
||||||
note: CollectionEntry<"note">;
|
|
||||||
isPreview?: boolean | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
const { as: Tag = "div", note, isPreview = false } = Astro.props;
|
|
||||||
const { Content } = await render(note);
|
|
||||||
---
|
|
||||||
|
|
||||||
<article
|
|
||||||
class:list={[isPreview && "bg-global-text/5 inline-grid rounded-md px-4 py-3"]}
|
|
||||||
data-pagefind-body={isPreview ? false : true}
|
|
||||||
>
|
|
||||||
<Tag class="title" class:list={{ "text-base": isPreview }}>
|
|
||||||
{
|
|
||||||
isPreview ? (
|
|
||||||
<a class="cactus-link" href={`/notes/${note.id}/`}>
|
|
||||||
{note.data.title}
|
|
||||||
</a>
|
|
||||||
) : (
|
|
||||||
<>{note.data.title}</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Tag>
|
|
||||||
<FormattedDate
|
|
||||||
dateTimeOptions={{
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
year: "2-digit",
|
|
||||||
month: "2-digit",
|
|
||||||
day: "2-digit",
|
|
||||||
}}
|
|
||||||
date={note.data.publishDate}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0"
|
|
||||||
class:list={{ "line-clamp-6": isPreview }}
|
|
||||||
>
|
|
||||||
<Content />
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
import { type CollectionEntry, render } from "astro:content";
|
||||||
|
import type { HTMLTag, Polymorphic } from "astro/types";
|
||||||
|
import ExperienceTags from "@/components/ExperienceTags.astro";
|
||||||
|
import FormattedDate from "@/components/FormattedDate.astro";
|
||||||
|
|
||||||
|
type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
|
||||||
|
project: CollectionEntry<"projects">;
|
||||||
|
isPreview?: boolean | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { as: Tag = "div", project, isPreview = false } = Astro.props;
|
||||||
|
const { Content } = await render(project);
|
||||||
|
const { title, publishDate, link, repo, experiences } = project.data;
|
||||||
|
---
|
||||||
|
|
||||||
|
<article
|
||||||
|
class:list={[isPreview && "bg-global-text/5 inline-grid rounded-md px-4 py-3"]}
|
||||||
|
data-pagefind-body={isPreview ? false : true}
|
||||||
|
>
|
||||||
|
<Tag class="title" class:list={{ "text-base": isPreview }}>
|
||||||
|
{
|
||||||
|
isPreview ? (
|
||||||
|
<a class="cactus-link" href={`/projects/${project.id}/`}>
|
||||||
|
{title}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<>{title}</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Tag>
|
||||||
|
<FormattedDate date={publishDate} />
|
||||||
|
{
|
||||||
|
!isPreview && (link || repo) && (
|
||||||
|
<div class="mt-2 flex flex-wrap gap-x-4 gap-y-1">
|
||||||
|
{link && (
|
||||||
|
<a class="cactus-link" href={link} rel="noopener noreferrer" target="_blank">
|
||||||
|
Visit →
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
{repo && (
|
||||||
|
<a class="cactus-link" href={repo} rel="noopener noreferrer" target="_blank">
|
||||||
|
Source →
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<div
|
||||||
|
class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0"
|
||||||
|
class:list={{ "line-clamp-6": isPreview }}
|
||||||
|
>
|
||||||
|
<Content />
|
||||||
|
</div>
|
||||||
|
{!isPreview && experiences.length > 0 && <div class="mt-6"><ExperienceTags experiences={experiences} /></div>}
|
||||||
|
</article>
|
||||||
@@ -8,7 +8,7 @@ import WebMentions from "@/components/blog/webmentions/index.astro";
|
|||||||
import BaseLayout from "./Base.astro";
|
import BaseLayout from "./Base.astro";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
post: CollectionEntry<"post">;
|
post: CollectionEntry<"writing">;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { post } = Astro.props;
|
const { post } = Astro.props;
|
||||||
|
|||||||
Reference in New Issue
Block a user