astro-ghostcms/packages/astro-ghostcms-theme-default/src/components/PostPreview.astro

301 lines
6.6 KiB
Plaintext

---
import { getGhostImgPath, formatDate } from "../utils";
import AuthorList from "../components/AuthorList.astro";
import type { Settings, Post, Tag } from "@matthiesenxyz/astro-ghostcms/api";
export type Props = {
post: Post;
settings: Settings;
index?: number;
isHome?: boolean;
};
const { post, settings, index, isHome = false } = Astro.props as Props;
---
<article
class={`post-card ${post.tags && post.tags
.map((tag: Tag) => `tag-${tag.slug}`)
.join(" ")} ${
isHome && post.feature_image && index == 0 ? "post-card-large" : ""
}`}
>
<a class="post-card-image-link" href={`/${post.slug}`} data-astro-reload>
<img
class="post-card-image"
srcset={`
${getGhostImgPath(settings.url, post.feature_image || "", 300)} 300w,
${getGhostImgPath(settings.url, post.feature_image || "", 600)} 600w
${getGhostImgPath(settings.url, post.feature_image || "", 1000)} 1000w
${getGhostImgPath(settings.url, post.feature_image || "", 2000)} 2000w
`}
src={`${getGhostImgPath(settings.url, post.feature_image || "", 600)}`}
alt={post.title}
sizes="(max-width: 1000px) 400px, 800px"
loading="lazy"
transition:name={`img-${post.title}`}
/>
</a>
<div class="post-card-content">
<a class="post-card-content-link" href={`/${post.slug}`} data-astro-reload>
<header class="post-card-header">
{post.primary_tag && (
<div class="post-card-primary-tag">{post.primary_tag.name}</div>
)}
<h2 class="post-card-title" transition:name={post.title}>{post.title}</h2>
</header>
<div class="post-card-excerpt">
<p>{post.excerpt}</p>
</div>
</a>
<footer class="post-card-meta">
<AuthorList post={post} settings={settings} />
<div class="post-card-byline-content">
<span>{post.primary_author?.name ?? ""}</span>
<span class="post-card-byline-date"
><time datetime={formatDate(post.created_at)}
>{formatDate(post.created_at)}
</time>
<span class="bull">&bull;</span>
{post.reading_time} min read
</span>
</div>
</footer>
</div>
</article>
<style lang="scss" is:global>
@use "sass:color";
@import "../styles/variables";
.post-card {
position: relative;
flex: 1 1 301px;
display: flex;
flex-direction: column;
min-height: 220px;
background-size: cover;
word-break: break-word;
}
.post-card-excerpt {
max-width: 56em;
}
.post-card-image-link {
position: relative;
display: block;
overflow: hidden;
border-radius: 3px;
}
.post-card-image {
width: 100%;
height: 200px;
background: $color-lightgrey no-repeat center center;
object-fit: cover;
}
.post-card-content-link {
position: relative;
display: block;
color: $color-darkgrey;
}
.post-card-content-link:hover {
text-decoration: none;
}
.post-card-header {
margin: 20px 0 0;
}
.post-feed .no-image .post-card-content-link {
padding: 0;
}
.no-image .post-card-header {
margin-top: 0;
}
.post-card-primary-tag {
margin: 0 0 0.2em;
color: var(--ghost-accent-color);
font-size: 1.2rem;
font-weight: 500;
letter-spacing: 0.2px;
text-transform: uppercase;
}
.post-card-title {
margin: 0 0 0.4em;
font-size: 2.4rem;
transition: color 0.2s ease-in-out;
}
.no-image .post-card-title {
margin-top: 0;
}
.post-card-content {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.post-card-excerpt p {
margin-bottom: 1em;
display: -webkit-box;
overflow-y: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-word;
}
.post-card-meta {
display: flex;
align-items: center;
padding: 0;
}
.avatar-wrapper {
display: block;
width: 100%;
height: 100%;
background: color.scale($color-lightgrey, $lightness: +8%);
border-radius: 100%;
object-fit: cover;
}
.post-card-meta .profile-image-wrapper,
.post-card-meta .avatar-wrapper {
position: relative;
}
.static-avatar {
display: block;
overflow: hidden;
margin: 0 0 0 -6px;
width: 36px;
height: 36px;
border-radius: 100%;
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.2);
}
.post-card-byline-content {
flex: 1 1 50%;
display: flex;
flex-direction: column;
margin: 0 0 0 8px;
color: color.scale($color-midgrey, $lightness: +10%);
font-size: 1.4rem;
line-height: 1.2em;
font-weight: 400;
}
.post-card-byline-content span {
margin: 0;
}
.post-card-byline-content a {
color: color.scale($color-darkgrey, $lightness: +15%);
font-weight: 600;
}
.post-card-byline-date {
font-size: 1.3rem;
line-height: 1.5em;
}
.post-card-byline-date .bull {
display: inline-block;
margin: 0 2px;
opacity: 0.6;
}
.single-author-byline {
display: flex;
flex-direction: column;
margin-left: 5px;
color: color.scale($color-midgrey, $lightness: -10%);
font-size: 1.3rem;
line-height: 1.4em;
font-weight: 500;
}
.single-author {
display: flex;
align-items: center;
}
.single-author .static-avatar {
margin-left: -2px;
}
.single-author-name {
display: inline-block;
}
/* Special Styling for home page grid (below):
The first post in the list is styled to be bigger than the others and take over
the full width of the grid to give it more emphasis. Wrapped in a media query to
make sure this only happens on large viewports / desktop-ish devices.
*/
@media (min-width: 1001px) {
.post-card-large {
grid-column: 1 / span 3;
display: grid;
grid-gap: 4vmin;
grid-template-columns: 1fr 1fr 1fr;
min-height: 280px;
border-top: 0;
}
.post-card-large:not(.no-image) .post-card-header {
margin-top: 0;
}
.post-card-large .post-card-image-link {
position: relative;
grid-column: 1 / span 2;
margin-bottom: 0;
min-height: 380px;
}
.post-card-large .post-card-image {
position: absolute;
width: 100%;
height: 100%;
}
.post-card-large .post-card-content {
justify-content: center;
}
.post-card-large .post-card-title {
margin-top: 0;
font-size: 3.2rem;
}
.post-card-large .post-card-excerpt p {
margin-bottom: 1.5em;
font-size: 1.7rem;
line-height: 1.55em;
-webkit-line-clamp: 8;
}
}
@media (max-width: 500px) {
.post-card-title {
font-size: 1.9rem;
}
.post-card-excerpt {
font-size: 1.6rem;
}
}
</style>