better cards

This commit is contained in:
2026-02-10 02:34:25 -05:00
parent b63c62a732
commit 03df2b3a6c
24 changed files with 669 additions and 127 deletions

View File

@@ -0,0 +1,63 @@
---
type Props = {
href: string;
title: string;
summary?: string;
imageUrl?: string;
dateLabel?: string;
viewsLabel?: string;
sourceLabel: string;
isExternal?: boolean;
linkAttrs?: Record<string, any>;
};
const {
href,
title,
summary,
imageUrl,
dateLabel,
viewsLabel,
sourceLabel,
isExternal,
linkAttrs,
} = Astro.props;
function truncate(s: string, n: number) {
const t = (s || "").trim();
if (!t) return "";
if (t.length <= n) return t;
// ASCII ellipsis to avoid encoding issues in generated HTML.
return `${t.slice(0, Math.max(0, n - 3)).trimEnd()}...`;
}
const summaryText = truncate(summary || "", 180);
---
<a
class="card"
href={href}
target={isExternal ? "_blank" : undefined}
rel={isExternal ? "noopener noreferrer" : undefined}
{...(linkAttrs || {})}
>
<div class="card-media">
{imageUrl ? <img src={imageUrl} alt="" loading="lazy" /> : <div class="card-placeholder" />}
</div>
<div class="card-body">
<div class="card-content">
<h3 class="card-title">{title}</h3>
{summaryText ? <p class="card-summary">{summaryText}</p> : null}
</div>
<div class="card-footer">
<span class="muted card-date">{dateLabel || ""}</span>
<span class="muted card-views" aria-hidden={viewsLabel ? undefined : "true"}>
{viewsLabel || ""}
</span>
<span class={`pill pill-${sourceLabel}`}>{sourceLabel}</span>
</div>
</div>
</a>