eratic / packages / core / src / components / EntryList.astro
276 words
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
---
/**
 * The listing used by every index page on every site.
 *
 * One component so blog, fav, io and the home page cannot drift apart. Each
 * item is a link, a date, a title and a summary; `kicker` carries whatever the
 * section wants to say about the kind of thing it is ("photographs", "book",
 * "issue 4").
 */
import { formatDate, isoDate } from '../lib/format.js';

export interface ListEntry {
	path: string;
	title: string;
	summary: string;
	pubDate: Date;
	kicker?: string;
	/** Absolute URL, for cross-site listings on the home page. */
	href?: string;
}

interface Props {
	entries: ListEntry[];
	/** Show dates. Off for short cross-section lists on the home page. */
	dates?: boolean;
	/** Empty-state text. */
	empty?: string;
}

const { entries, dates = true, empty = 'Nothing here yet.' } = Astro.props;
---

{
	entries.length === 0 ? (
		<p class="meta">{empty}</p>
	) : (
		<ul class="entry-list">
			{entries.map((entry) => (
				<li>
					<a href={entry.href ?? entry.path}>
						<h2>{entry.title}</h2>
					</a>
					<p class="entry-list__summary">{entry.summary}</p>
					<p class="meta entry-list__meta">
						{entry.kicker && <span class="entry-list__kicker">{entry.kicker}</span>}
						{dates && (
							<time datetime={isoDate(entry.pubDate)}>{formatDate(entry.pubDate)}</time>
						)}
					</p>
				</li>
			))}
		</ul>
	)
}

<style>
	.entry-list {
		list-style: none;
		padding: 0;
		margin: 0;
		display: flex;
		flex-direction: column;
		gap: var(--space-l);
	}

	.entry-list li {
		display: flex;
		flex-direction: column;
		gap: var(--space-3xs);
	}

	.entry-list a {
		text-decoration: none;
		color: inherit;
	}

	.entry-list h2 {
		font-family: var(--font-prose);
		font-size: var(--step-2);
		font-weight: 600;
		line-height: var(--leading-tight);
		letter-spacing: -0.014em;
		text-wrap: balance;
		font-optical-sizing: auto;
	}

	.entry-list a:hover h2 {
		color: var(--accent);
	}

	.entry-list__summary {
		font-family: var(--font-prose);
		font-size: var(--step-0);
		color: var(--ink-muted);
		text-wrap: pretty;
		max-inline-size: var(--measure);
	}

	.entry-list__meta {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-2xs);
		font-variant-numeric: oldstyle-nums;
		color: var(--ink-faint);
	}

	.entry-list__kicker::after {
		content: ' ·';
	}
</style>

static mirror of HEAD · about · clone: git clone https://git.makefuture.ro/eratic.git