Skip to content

Commit dbe540e

Browse files
authored
Merge pull request #4 from compstatgenlab/copilot/improve-blog-article-visualization
Fix blog article typography and improve article listing layout
2 parents 2085697 + c7ce8c7 commit dbe540e

6 files changed

Lines changed: 140 additions & 49 deletions

File tree

package-lock.json

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
"preview": "astro preview"
99
},
1010
"dependencies": {
11-
"astro": "4.16.0",
12-
"@astrojs/tailwind": "5.1.5",
1311
"@astrojs/sitemap": "3.2.0",
12+
"@astrojs/tailwind": "5.1.5",
13+
"@tailwindcss/typography": "^0.5.19",
14+
"astro": "4.16.0",
1415
"tailwindcss": "3.4.0"
1516
}
1617
}

src/layouts/Article.astro

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,70 @@ const { title, description, date, author = 'Simone Rubinacci', tags = [], heroIm
1414
const formatted = date.toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' });
1515
---
1616
<Page title={title} description={description}>
17-
<article class="max-w-2xl mx-auto px-6 py-16">
17+
<article class="max-w-3xl mx-auto px-6 py-16">
1818

1919
<!-- Breadcrumb -->
20-
<div class="font-mono text-xs text-stone-400 mb-8">
20+
<div class="font-mono text-[0.68rem] tracking-wider text-stone-400 mb-10 flex items-center gap-2">
2121
<a href="/articles" class="hover:text-blue-700 no-underline transition-colors">Articles</a>
22-
<span class="mx-2"</span>
22+
<span class="text-stone-300">/</span>
2323
<span>{formatted}</span>
2424
</div>
2525

2626
<!-- Header -->
27-
<header class="mb-10">
27+
<header class="mb-12">
2828
{tags.length > 0 && (
29-
<div class="flex flex-wrap gap-2 mb-4">
29+
<div class="flex flex-wrap gap-2 mb-5">
3030
{tags.map(tag => (
31-
<span class="font-mono text-[0.65rem] tracking-widest uppercase px-2 py-0.5 bg-blue-50 text-blue-700 rounded border border-blue-100">
31+
<span class="font-mono text-[0.63rem] tracking-widest uppercase px-2.5 py-1 bg-blue-50 text-blue-700 rounded-full border border-blue-100">
3232
{tag}
3333
</span>
3434
))}
3535
</div>
3636
)}
37-
<h1 class="font-serif text-3xl md:text-4xl text-stone-900 font-normal leading-snug mb-4">{title}</h1>
38-
{description && <p class="text-stone-500 text-lg leading-relaxed">{description}</p>}
39-
<div class="mt-5 pt-5 border-t border-stone-100 flex items-center gap-3">
40-
<img src="/images/lab/spiral-logo.png" alt={author} class="w-8 h-8 rounded-full object-cover border border-stone-200" />
41-
<span class="text-sm text-stone-500">{author} · {formatted}</span>
37+
<h1 class="font-serif text-3xl md:text-[2.6rem] text-stone-900 font-normal leading-tight mb-5">{title}</h1>
38+
{description && (
39+
<p class="text-stone-500 text-lg md:text-xl leading-relaxed border-l-2 border-blue-200 pl-4 italic">{description}</p>
40+
)}
41+
<div class="mt-7 pt-6 border-t border-stone-100 flex items-center gap-3">
42+
<img src="/images/lab/spiral-logo.png" alt={author} class="w-9 h-9 rounded-full object-cover border border-stone-200" />
43+
<div class="flex flex-col leading-tight">
44+
<span class="text-sm font-medium text-stone-700">{author}</span>
45+
<span class="text-xs text-stone-400">{formatted}</span>
46+
</div>
4247
</div>
4348
</header>
4449

4550
{heroImage && (
4651
<img
4752
src={heroImage}
4853
alt={title}
49-
class="w-full rounded-xl mb-10 object-cover max-h-80 border border-stone-100"
54+
class="w-full rounded-xl mb-12 object-cover max-h-80 border border-stone-100 shadow-sm"
5055
/>
5156
)}
5257

5358
<!-- Content -->
54-
<div class="prose prose-stone prose-lg max-w-none
55-
prose-headings:font-serif prose-headings:font-normal
56-
prose-a:text-blue-700 prose-a:no-underline hover:prose-a:underline
57-
prose-code:font-mono prose-code:text-sm
58-
prose-blockquote:border-blue-200 prose-blockquote:text-stone-500">
59+
<div class="prose prose-stone max-w-none
60+
[&_p]:text-[1.0625rem] [&_p]:leading-[1.85] [&_p]:text-stone-700
61+
[&_h2]:font-serif [&_h2]:font-normal [&_h2]:text-stone-900 [&_h2]:text-2xl [&_h2]:mt-10 [&_h2]:mb-4
62+
[&_h3]:font-serif [&_h3]:font-normal [&_h3]:text-stone-900 [&_h3]:text-xl [&_h3]:mt-8 [&_h3]:mb-3
63+
[&_a]:text-blue-700 [&_a]:underline [&_a]:underline-offset-2 [&_a]:decoration-blue-200 [&_a]:font-medium
64+
hover:[&_a]:text-blue-800 hover:[&_a]:decoration-blue-600
65+
[&_code]:font-mono [&_code]:text-sm [&_code]:bg-stone-100 [&_code]:rounded [&_code]:px-1.5 [&_code]:py-0.5
66+
[&_blockquote]:border-l-2 [&_blockquote]:border-blue-200 [&_blockquote]:pl-5 [&_blockquote]:text-stone-500 [&_blockquote]:italic
67+
[&_hr]:border-stone-100 [&_hr]:my-10
68+
[&_img]:rounded-lg [&_img]:shadow-sm [&_img]:border [&_img]:border-stone-100
69+
[&_ul]:pl-5 [&_ul>li]:mt-1.5 [&_ul>li]:text-stone-700
70+
[&_ol>li]:mt-1.5 [&_ol>li]:text-stone-700
71+
[&_strong]:text-stone-900 [&_strong]:font-semibold">
5972
<slot />
6073
</div>
6174

62-
<!-- Back -->
63-
<div class="mt-16 pt-8 border-t border-stone-100">
64-
<a href="/articles" class="font-mono text-xs text-stone-400 hover:text-blue-700 no-underline transition-colors">
65-
← All articles
75+
<!-- Footer navigation -->
76+
<div class="mt-16 pt-8 border-t border-stone-100 flex items-center justify-between">
77+
<a href="/articles"
78+
class="group inline-flex items-center gap-2 font-mono text-xs text-stone-400 hover:text-blue-700 no-underline transition-colors">
79+
<span class="transition-transform group-hover:-translate-x-0.5">←</span>
80+
All articles
6681
</a>
6782
</div>
6883

src/pages/articles/index.astro

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,54 @@ const posts = (await getCollection('articles'))
77
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
88
---
99
<Page title="Articles" description="Deep dives into our papers and methods">
10-
<div class="max-w-5xl mx-auto px-6 py-16">
10+
<div class="max-w-3xl mx-auto px-6 py-16">
1111

1212
<p class="font-mono text-[0.68rem] tracking-[0.18em] uppercase text-teal-600 mb-3">From the lab</p>
1313
<h1 class="font-serif text-4xl text-stone-900 font-normal mb-4">Articles</h1>
1414
<div class="w-10 h-0.5 bg-gradient-to-r from-blue-600 to-teal-500 mb-4"></div>
15-
<p class="text-stone-500 leading-relaxed mb-14 max-w-5xl">
15+
<p class="text-stone-500 leading-relaxed mb-14 max-w-2xl">
1616
Here we try to go beyond the abstract, giving our insights into the intuitions, methods, and implications behind our papers, mostly for a non-specialist audience.
1717
</p>
1818

1919
{posts.length === 0 && (
2020
<p class="text-stone-400 text-sm">Articles coming soon.</p>
2121
)}
2222

23-
<div class="space-y-0 divide-y divide-stone-100">
23+
<div class="flex flex-col gap-4">
2424
{posts.map(post => (
2525
<a href={`/articles/${post.slug}`}
26-
class="group flex gap-6 py-8 no-underline hover:no-underline block">
27-
<div class="hidden sm:block w-16 shrink-0 text-right">
28-
<span class="font-mono text-[0.62rem] text-stone-400 uppercase tracking-wider">
29-
{post.data.date.toLocaleDateString('en-GB', { month: 'short', year: 'numeric' })}
26+
class="group relative flex flex-col gap-3 p-6 rounded-xl border border-stone-100 bg-white hover:border-blue-100 hover:shadow-sm transition-all no-underline hover:no-underline">
27+
28+
<!-- Date + tags row -->
29+
<div class="flex flex-wrap items-center gap-3">
30+
<span class="font-mono text-[0.62rem] text-stone-400 uppercase tracking-wider shrink-0">
31+
{post.data.date.toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })}
3032
</span>
31-
</div>
32-
<div class="flex-1">
3333
{post.data.tags && post.data.tags.length > 0 && (
34-
<div class="flex gap-2 mb-2">
35-
{post.data.tags.slice(0,3).map(tag => (
36-
<span class="font-mono text-[0.6rem] tracking-widest uppercase px-1.5 py-0.5 bg-blue-50 text-blue-600 rounded">
34+
<div class="flex flex-wrap gap-1.5">
35+
{post.data.tags.slice(0, 3).map(tag => (
36+
<span class="font-mono text-[0.6rem] tracking-widest uppercase px-2 py-0.5 bg-blue-50 text-blue-600 rounded-full">
3737
{tag}
3838
</span>
3939
))}
4040
</div>
4141
)}
42-
<h2 class="font-serif text-xl text-stone-900 font-normal leading-snug group-hover:text-blue-700 transition-colors mb-2">
43-
{post.data.title}
44-
</h2>
45-
<p class="text-stone-500 text-sm leading-relaxed">{post.data.description}</p>
4642
</div>
47-
<div class="hidden md:block shrink-0 pt-1">
48-
<span class="font-mono text-xs text-stone-300 group-hover:text-blue-400 transition-colors">→</span>
43+
44+
<!-- Title -->
45+
<h2 class="font-serif text-xl md:text-2xl text-stone-900 font-normal leading-snug group-hover:text-blue-700 transition-colors">
46+
{post.data.title}
47+
</h2>
48+
49+
<!-- Description -->
50+
<p class="text-stone-500 text-sm leading-relaxed">{post.data.description}</p>
51+
52+
<!-- Read link -->
53+
<div class="flex items-center gap-1 text-blue-600 font-mono text-xs mt-1 group-hover:gap-2 transition-all">
54+
<span>Read article</span>
55+
<span class="transition-transform group-hover:translate-x-0.5">→</span>
4956
</div>
57+
5058
</a>
5159
))}
5260
</div>

src/styles/global.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
image-rendering: auto;
2121
}
2222

23-
p {
23+
p:not(.prose p):not(article p) {
2424
text-align: justify;
2525
}
2626
@media (max-width: 640px) {
27-
p {
27+
p:not(.prose p):not(article p) {
2828
text-align: left;
2929
}
3030
}

tailwind.config.mjs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import typography from '@tailwindcss/typography';
2+
13
/** @type {import('tailwindcss').Config} */
24
export default {
35
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,ts,tsx}'],
@@ -39,16 +41,55 @@ export default {
3941
DEFAULT: {
4042
css: {
4143
fontFamily: theme('fontFamily.sans').join(', '),
44+
fontSize: '1.0625rem',
45+
lineHeight: '1.85',
4246
color: theme('colors.stone.700'),
43-
h1: { fontFamily: theme('fontFamily.serif').join(', '), color: theme('colors.stone.900') },
44-
h2: { fontFamily: theme('fontFamily.serif').join(', '), color: theme('colors.stone.900') },
45-
h3: { fontFamily: theme('fontFamily.serif').join(', '), color: theme('colors.stone.900') },
46-
a: { color: theme('colors.blue.700'), textDecoration: 'none', '&:hover': { textDecoration: 'underline' } },
47-
'code': { fontFamily: theme('fontFamily.mono').join(', ') },
47+
maxWidth: 'none',
48+
p: { marginTop: '1.35em', marginBottom: '1.35em' },
49+
h1: { fontFamily: theme('fontFamily.serif').join(', '), fontWeight: '400', color: theme('colors.stone.900'), marginBottom: '0.6em' },
50+
h2: { fontFamily: theme('fontFamily.serif').join(', '), fontWeight: '400', color: theme('colors.stone.900'), marginTop: '2em', marginBottom: '0.6em', fontSize: '1.4em' },
51+
h3: { fontFamily: theme('fontFamily.serif').join(', '), fontWeight: '400', color: theme('colors.stone.900'), marginTop: '1.75em', fontSize: '1.15em' },
52+
a: {
53+
color: theme('colors.blue.700'),
54+
textDecoration: 'underline',
55+
textDecorationColor: theme('colors.blue.200'),
56+
textUnderlineOffset: '3px',
57+
fontWeight: '500',
58+
'&:hover': {
59+
color: theme('colors.blue.800'),
60+
textDecorationColor: theme('colors.blue.600'),
61+
},
62+
},
63+
'code': {
64+
fontFamily: theme('fontFamily.mono').join(', '),
65+
fontSize: '0.875em',
66+
backgroundColor: theme('colors.stone.100'),
67+
borderRadius: '0.25rem',
68+
paddingTop: '0.15em',
69+
paddingBottom: '0.15em',
70+
paddingLeft: '0.35em',
71+
paddingRight: '0.35em',
72+
fontWeight: '400',
73+
},
74+
'code::before': { content: 'none' },
75+
'code::after': { content: 'none' },
76+
blockquote: {
77+
borderLeftColor: theme('colors.blue.200'),
78+
color: theme('colors.stone.500'),
79+
fontStyle: 'italic',
80+
paddingLeft: '1.25em',
81+
},
82+
'blockquote p': { marginTop: '0.4em', marginBottom: '0.4em' },
83+
hr: { borderColor: theme('colors.stone.100'), marginTop: '2.5em', marginBottom: '2.5em' },
84+
ul: { paddingLeft: '1.4em' },
85+
li: { marginTop: '0.4em', marginBottom: '0.4em' },
86+
img: { borderRadius: '0.5rem', marginTop: '1.5em', marginBottom: '0.5em' },
87+
'figure figcaption': { color: theme('colors.stone.400'), fontSize: '0.82em', textAlign: 'center', marginTop: '0.5em' },
88+
strong: { color: theme('colors.stone.900'), fontWeight: '600' },
4889
},
4990
},
5091
}),
5192
},
5293
},
53-
plugins: [],
94+
plugins: [typography],
5495
};

0 commit comments

Comments
 (0)