Skip to content

Commit 15ca82d

Browse files
committed
chore: redesign cards
1 parent 327abb4 commit 15ca82d

File tree

17 files changed

+267
-206
lines changed

17 files changed

+267
-206
lines changed

.changeset/blue-ads-juggle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"r.obin.ch": patch
3+
---
4+
5+
Redesign cards

src/components/Button.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ const { href } = Astro.props;
88

99
<style>
1010
a {
11+
display: inline-block;
1112
background-color: var(--primary-color);
1213
color: var(--white-color);
1314
text-decoration: none;
1415
border-radius: var(--border-radius);
15-
padding: 0.2rem 0.4rem;
16+
padding: var(--gap-tiny) var(--gap);
1617
}
1718

1819
a:hover {
19-
background-color: var(--primary-color-120);
20+
background-color: var(--primary-color-80);
2021
}
2122
</style>
2223

src/components/Card.astro

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
import { Image } from "astro:assets";
3+
import DerivedCover from "./DerivedCover.astro";
4+
5+
type Props = {
6+
link: string;
7+
title: string;
8+
cover?: { alt?: string; src: ImageMetadata };
9+
headingLevel?: 2 | 3 | 4 | 5 | 6;
10+
dividerFlip?: boolean;
11+
};
12+
13+
const {
14+
link,
15+
title,
16+
cover,
17+
headingLevel = 3,
18+
dividerFlip,
19+
} = Astro.props;
20+
const HeadingTag = `h${headingLevel}` as keyof HTMLElementTagNameMap;
21+
---
22+
23+
<style>
24+
a {
25+
display: flex;
26+
flex-direction: column;
27+
width: calc(100% + var(--gap) * 2);
28+
border-radius: var(--border-radius);
29+
overflow: hidden;
30+
text-decoration: none;
31+
margin: calc(var(--gap) * -1);
32+
height: calc(100% + var(--gap) * 2);
33+
hyphens: auto;
34+
}
35+
36+
.cover {
37+
display: flex;
38+
position: relative;
39+
flex-grow: 1;
40+
height: 20rem;
41+
}
42+
43+
.overlay {
44+
position: absolute;
45+
left: 0;
46+
right: 0;
47+
bottom: 0;
48+
background-color: var(--primary-color-240);
49+
color: var(--text-color);
50+
padding: var(--gap);
51+
padding-top: var(--gap-big);
52+
clip-path: polygon(0 0, 100% 1rem, 100% 100%, 0 100%);
53+
font-size: 0.8rem;
54+
}
55+
56+
.overlay.divider-flip {
57+
clip-path: polygon(0 1rem, 100% 0, 100% 100%, 0 100%);
58+
}
59+
60+
a:hover .overlay,
61+
a:hover .content {
62+
background-color: var(--primary-color-220);
63+
transition: var(--transition-duration);
64+
}
65+
66+
a:hover :global(svg),
67+
a:hover :global(img) {
68+
transform: scale(1.05);
69+
transition: var(--transition-duration);
70+
transition-origin: center;
71+
}
72+
73+
.overlay :global(h3),
74+
.overlay :global(h4),
75+
.overlay :global(h5),
76+
.overlay :global(h6) {
77+
margin: 0;
78+
}
79+
80+
.super-title {
81+
font-size: 0.8rem;
82+
font-weight: 500;
83+
}
84+
85+
.content {
86+
background-color: var(--primary-color-240);
87+
color: var(--text-color);
88+
padding-inline: var(--gap);
89+
padding-bottom: var(--gap);
90+
margin-top: -0.5px;
91+
z-index: 10;
92+
}
93+
94+
a :global(svg),
95+
a :global(img) {
96+
display: block;
97+
width: 100%;
98+
border-radius: 0;
99+
flex-grow: 1;
100+
object-fit: cover;
101+
}
102+
</style>
103+
104+
<a href={link}>
105+
<div class="cover">
106+
{
107+
cover ? (
108+
<Image src={cover.src} alt={cover.alt || title} widths={[1280, 720]} />
109+
) : (
110+
<DerivedCover value={title} />
111+
)
112+
}
113+
<div class:list={{ overlay: true, "divider-flip": dividerFlip }}>
114+
<slot name="super-title" />
115+
<HeadingTag>{title}</HeadingTag>
116+
<slot name="sub-title" />
117+
</div>
118+
</div>
119+
<div class="content">
120+
<slot />
121+
</div>
122+
</a>

src/components/GalleryCard.astro

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/components/PostCard.astro

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/components/ReboundDivider.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ const flipVertically = Astro.props.flipVertically ? -1 : 1;
1515
}}
1616
>
1717
svg {
18-
width: calc(100% + 1.01px);
18+
width: calc(100% + 1.5px);
1919
height: auto;
2020
transform: scaleX(var(--flip-horizontally)) scaleY(var(--flip-vertically));
2121
fill: var(--divider-fill, #000);
22-
margin: -1.01px;
22+
margin: -1.5px;
2323
}
2424
</style>
2525

src/content.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ const projectsCollection = defineCollection({
5050
z.object({
5151
homepage: z.string().url().optional(),
5252
source: z.string().url().optional(),
53-
cover: image().optional(),
53+
cover: z.object({
54+
src: image(),
55+
alt: z.string().optional(),
56+
}).optional(),
5457
status: z.enum(["active", "maintenance", "archived"]),
5558
type: z.enum(["website", "app", "library", "tool", "other"]),
5659
images: z.array(

src/layouts/sections/LatestBlogsSection.astro

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
---
22
import { parseLocale, useTranslations } from "../../utils/i18n";
3-
import PostCard from "../../components/PostCard.astro";
43
import CardList from "../../components/CardList.astro";
54
import { defaultBlogCollection } from "../../collections/blog";
65
import { i18nProps } from "astro-loader-i18n";
76
import { defaultPropsAndParamsOptions } from "../../utils/paths";
87
import { render } from "astro:content";
98
import slug from "limax";
9+
import Card from "../../components/Card.astro";
10+
import DateTime from "../../components/DateTime.astro";
1011
1112
type Props = {
1213
locale: string;
@@ -27,7 +28,7 @@ const filteredPosts = posts.slice(0, 4);
2728
section :global(ul) {
2829
display: grid;
2930
grid-template-columns: 1fr 1fr;
30-
gap: 1rem;
31+
gap: 4rem;
3132
}
3233

3334
@media (max-width: 1280px) {
@@ -41,17 +42,14 @@ const filteredPosts = posts.slice(0, 4);
4142
<h2>{t("latestPostsLabel")}</h2>
4243
<CardList>
4344
{
44-
filteredPosts.map(async (post) => {
45+
filteredPosts.map(async (post, i) => {
4546
const { remarkPluginFrontmatter } = await render(post);
4647
return (
4748
<li>
48-
<PostCard
49-
title={post.data.title}
50-
cover={post.data.cover}
51-
publishedAt={post.data.publishedAt}
52-
translatedPath={post.translatedPath}
53-
excerpt={remarkPluginFrontmatter.excerpt}
54-
/>
49+
<Card title={post.data.title} cover={post.data.cover} link={post.translatedPath} dividerFlip={i % 2 === 0}>
50+
<DateTime slot="super-title" date={post.data.publishedAt} />
51+
{remarkPluginFrontmatter.excerpt}...
52+
</Card>
5553
</li>
5654
);
5755
})

src/pages/[...locale]/[blog]/[...page].astro

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type { GetStaticPaths } from "astro";
33
import DefaultLayout from "../../../layouts/DefaultLayout.astro";
44
import { parseLocale, useTranslations } from "../../../utils/i18n";
55
import Page from "../../../layouts/pages/Page.astro";
6-
import PostCard from "../../../components/PostCard.astro";
76
import CardList from "../../../components/CardList.astro";
87
import Pagination from "../../../components/Pagination.astro";
98
import Meta from "../../../layouts/groups/Meta.astro";
@@ -16,6 +15,8 @@ import {
1615
} from "../../../utils/paths";
1716
import { C } from "../../../site.config";
1817
import { render } from "astro:content";
18+
import Card from "../../../components/Card.astro";
19+
import DateTime from "../../../components/DateTime.astro";
1920
2021
export const getStaticPaths = (async ({ paginate }) => {
2122
const routePattern = "[...locale]/[blog]/[...slug]";
@@ -24,7 +25,9 @@ export const getStaticPaths = (async ({ paginate }) => {
2425
const propsAndParams = i18nPropsAndParams(collection, {
2526
...defaultPropsAndParamsOptions,
2627
routePattern,
27-
generateSegments: (entry) => ({ slug: `${entry.data.contentPath}/${slug(entry.data.title)}` }),
28+
generateSegments: (entry) => ({
29+
slug: `${entry.data.contentPath}/${slug(entry.data.title)}`,
30+
}),
2831
});
2932
3033
const locales = propsAndParams.reduce(
@@ -70,8 +73,8 @@ const t = useTranslations(parseLocale(locale));
7073
:global(.vertical) {
7174
display: flex;
7275
flex-direction: column;
73-
gap: 1.4rem;
74-
margin: 1.4rem 0 !important;
76+
gap: 4rem;
77+
margin-block: 3rem !important;
7578
}
7679
</style>
7780

@@ -82,17 +85,19 @@ const t = useTranslations(parseLocale(locale));
8285
<Pagination page={page} />
8386
<CardList classNames="vertical">
8487
{
85-
page.data.map(async (post) => {
88+
page.data.map(async (post, i) => {
8689
const { remarkPluginFrontmatter } = await render(post);
8790
return (
8891
<li>
89-
<PostCard
92+
<Card
9093
title={post.data.title}
9194
cover={post.data.cover}
92-
publishedAt={post.data.publishedAt}
93-
translatedPath={post.translatedPath}
94-
excerpt={remarkPluginFrontmatter.excerpt}
95-
/>
95+
link={post.translatedPath}
96+
dividerFlip={i % 2 === 0}
97+
>
98+
<DateTime slot="super-title" date={post.data.publishedAt} />
99+
{remarkPluginFrontmatter.excerpt}...
100+
</Card>
96101
</li>
97102
);
98103
})

0 commit comments

Comments
 (0)