site: media + colocation — chunk 1/4 (code, configs, docs)
Code, configs, README, CHANGELOG, sources/log files, .claude. Subsequent chunks land the renamed media files.
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import type { FindItem } from '../lib/find-items';
|
||||
import { findHero } from '../lib/find-hero';
|
||||
import SourceBadge from './SourceBadge.astro';
|
||||
|
||||
interface Props {
|
||||
item: FindItem;
|
||||
}
|
||||
const { item } = Astro.props;
|
||||
const hero = findHero(item.id);
|
||||
|
||||
function host(url: string) {
|
||||
try {
|
||||
@@ -16,36 +19,64 @@ function host(url: string) {
|
||||
}
|
||||
---
|
||||
|
||||
<a href={`/find/${item.id}/`} class="find-card">
|
||||
<div class="head">
|
||||
<span class="name">{item.data.name}</span>
|
||||
<SourceBadge source={item.data.source} />
|
||||
<article class:list={['find-card', { 'has-hero': !!hero }]}>
|
||||
{import.meta.env.DEV && (
|
||||
<label class="edit-checkbox" aria-label={`Select ${item.data.name}`}>
|
||||
<input type="checkbox" data-find-checkbox data-slug={item.id} />
|
||||
</label>
|
||||
)}
|
||||
{hero && (
|
||||
<Image
|
||||
class="media"
|
||||
src={hero}
|
||||
widths={[320, 480, 640]}
|
||||
sizes="(max-width: 520px) 92vw, (max-width: 880px) 45vw, 240px"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
alt={item.data.name}
|
||||
/>
|
||||
)}
|
||||
<div class="content">
|
||||
<div class="head">
|
||||
<a href={`/find/${item.id}/`} class="name">{item.data.name}</a>
|
||||
<SourceBadge source={item.data.source} />
|
||||
</div>
|
||||
{item.data.subtitle && <p class="subtitle">{item.data.subtitle}</p>}
|
||||
<p class="external">
|
||||
<span class="ext-label">→</span>
|
||||
<span class="host">{host(item.data.link)}</span>
|
||||
</p>
|
||||
</div>
|
||||
{item.data.subtitle && <p class="subtitle">{item.data.subtitle}</p>}
|
||||
<p class="external">
|
||||
<span class="ext-label">→</span>
|
||||
<span class="host">{host(item.data.link)}</span>
|
||||
</p>
|
||||
</a>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.find-card {
|
||||
display: block;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--rule);
|
||||
background: var(--bg);
|
||||
padding: 0.95rem 1.05rem 1rem;
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
|
||||
}
|
||||
.find-card:hover {
|
||||
text-decoration: none;
|
||||
transform: translateY(-2px);
|
||||
border-color: color-mix(in srgb, var(--accent) 40%, var(--rule));
|
||||
box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
.find-card:hover .name { color: var(--accent); }
|
||||
|
||||
.media {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: var(--card-fill);
|
||||
border-bottom: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0.95rem 1.05rem 1rem;
|
||||
}
|
||||
|
||||
.head {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -58,8 +89,23 @@ function host(url: string) {
|
||||
font-size: 1.05rem;
|
||||
color: var(--fg);
|
||||
letter-spacing: -0.01em;
|
||||
text-decoration: none;
|
||||
transition: color 0.18s ease;
|
||||
}
|
||||
.name:hover { text-decoration: none; }
|
||||
/* Stretched click target — covers the whole card. */
|
||||
.name::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
}
|
||||
/* Anchors inside the card (e.g. the source badge) sit above the stretched target. */
|
||||
.find-card :global(a:not(.name)) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
margin: 0 0 0.6rem;
|
||||
color: var(--muted);
|
||||
@@ -77,4 +123,31 @@ function host(url: string) {
|
||||
align-items: baseline;
|
||||
}
|
||||
.ext-label { color: var(--accent); font-family: ui-sans-serif, system-ui, sans-serif; }
|
||||
|
||||
.edit-checkbox {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
z-index: 3;
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--rule);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.edit-checkbox input {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
accent-color: var(--accent);
|
||||
}
|
||||
.find-card:has(.edit-checkbox input:checked) {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 28%, transparent);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user