Skip to content

Commit 926641a

Browse files
authored
Merge pull request #1634 from recodehive/copilot/fix-ui-card-display-issue
Align blog post author card with reference layout in production
2 parents 4c023ff + e9e38d8 commit 926641a

3 files changed

Lines changed: 162 additions & 95 deletions

File tree

src/theme/BlogPostItem/Footer/index.tsx

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import React from "react";
22
import Link from "@docusaurus/Link";
3+
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
34
import { useBlogPost } from "@docusaurus/plugin-content-blog/client";
45
import BlogPostItemFooterOriginal from "@theme-original/BlogPostItem/Footer";
56
import type BlogPostItemFooterType from "@theme/BlogPostItem/Footer";
67
import type { WrapperProps } from "@docusaurus/types";
7-
import { getAuthorProfile } from "@site/src/utils/authors";
8+
import { getAuthorProfile } from "../../../utils/authors";
89

910
import styles from "./styles.module.css";
1011

1112
type Props = WrapperProps<typeof BlogPostItemFooterType>;
13+
const META_SEPARATOR = " • ";
1214

1315
function getGitHubUrl(author: {
1416
key?: string;
@@ -26,7 +28,26 @@ function getGitHubUrl(author: {
2628
return undefined;
2729
}
2830

31+
function getGitHubHandle(author: {
32+
key?: string;
33+
url?: string;
34+
}): string | undefined {
35+
if (author.url && /github\.com\//i.test(author.url)) {
36+
const matched = author.url.match(/github\.com\/([^/?#]+)/i);
37+
if (matched?.[1]) {
38+
return `@${matched[1]}`;
39+
}
40+
}
41+
42+
if (author.key) {
43+
return `@${author.key}`;
44+
}
45+
46+
return undefined;
47+
}
48+
2949
export default function BlogPostItemFooterWrapper(props: Props): JSX.Element {
50+
const { siteConfig } = useDocusaurusContext();
3051
const { metadata, isBlogPostPage } = useBlogPost();
3152
const primaryAuthor = metadata.authors?.[0];
3253

@@ -46,20 +67,27 @@ export default function BlogPostItemFooterWrapper(props: Props): JSX.Element {
4667

4768
const roundedReadTime = Math.max(1, Math.ceil(metadata.readingTime || 0));
4869
const readTimeText = `${roundedReadTime} min read`;
70+
const authorHandle = primaryAuthor
71+
? getGitHubHandle({
72+
key: primaryAuthor.key,
73+
url: primaryAuthor.url,
74+
})
75+
: undefined;
4976
const authorSummary =
5077
primaryAuthor?.description ||
5178
profile?.description ||
5279
primaryAuthor?.title ||
5380
profile?.title;
5481
const blogDate =
55-
metadata.formattedDate ||
56-
(metadata.date
57-
? new Date(metadata.date).toLocaleDateString("en-US", {
58-
year: "numeric",
59-
month: "short",
60-
day: "numeric",
61-
})
62-
: "");
82+
metadata.date &&
83+
new Intl.DateTimeFormat(siteConfig.i18n?.defaultLocale || "en-US", {
84+
year: "numeric",
85+
month: "short",
86+
day: "numeric",
87+
}).format(new Date(metadata.date));
88+
const metaItems = [authorHandle, blogDate, readTimeText]
89+
.filter(Boolean)
90+
.join(META_SEPARATOR);
6391

6492
const showAuthorCard = Boolean(isBlogPostPage && primaryAuthor && authorName);
6593

@@ -68,41 +96,53 @@ export default function BlogPostItemFooterWrapper(props: Props): JSX.Element {
6896
<BlogPostItemFooterOriginal {...props} />
6997
{showAuthorCard && (
7098
<section className={styles.authorCard} aria-label="Post author details">
71-
<div className={styles.authorLeft}>
72-
{authorAvatar ? (
73-
<img
74-
className={styles.authorAvatar}
75-
src={authorAvatar}
76-
alt={`${authorName} profile picture`}
77-
loading="lazy"
78-
/>
79-
) : (
80-
<div className={styles.authorAvatarFallback} aria-hidden="true">
81-
{authorName?.charAt(0).toUpperCase()}
82-
</div>
83-
)}
99+
<div className={styles.authorBody}>
100+
<div className={styles.authorAvatarWrapper}>
101+
{authorAvatar ? (
102+
<img
103+
className={styles.authorAvatar}
104+
src={authorAvatar}
105+
alt={`${authorName} profile picture`}
106+
loading="lazy"
107+
/>
108+
) : (
109+
<div className={styles.authorAvatarFallback} aria-hidden="true">
110+
{authorName?.charAt(0).toUpperCase()}
111+
</div>
112+
)}
113+
<span className={styles.verifiedBadge} aria-hidden="true">
114+
115+
</span>
116+
</div>
84117
<div className={styles.authorIdentity}>
85-
<p className={styles.authorName}>{authorName}</p>
86-
{blogDate ? <p className={styles.authorDate}>{blogDate}</p> : null}
118+
<div className={styles.authorNameRow}>
119+
<p className={styles.authorName}>{authorName}</p>
120+
<span className={styles.authorBadge}>Author</span>
121+
</div>
122+
{metaItems ? <p className={styles.authorMeta}>{metaItems}</p> : null}
87123
{authorSummary ? (
88124
<p className={styles.authorSummary}>{authorSummary}</p>
89125
) : null}
126+
{githubUrl ? (
127+
<Link
128+
className={styles.githubButton}
129+
to={githubUrl}
130+
target="_blank"
131+
rel="noopener noreferrer"
132+
>
133+
<span className={styles.githubIcon} aria-hidden="true">
134+
<svg viewBox="0 0 16 16" width="14" height="14" focusable="false">
135+
<path
136+
fill="currentColor"
137+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.5-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82A7.5 7.5 0 0 1 8 3.8c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8Z"
138+
/>
139+
</svg>
140+
</span>
141+
GitHub
142+
</Link>
143+
) : null}
90144
</div>
91145
</div>
92-
93-
<div className={styles.authorRight}>
94-
<p className={styles.readTime}>{readTimeText}</p>
95-
{githubUrl ? (
96-
<Link
97-
className={styles.githubButton}
98-
to={githubUrl}
99-
target="_blank"
100-
rel="noopener noreferrer"
101-
>
102-
GitHub Profile
103-
</Link>
104-
) : null}
105-
</div>
106146
</section>
107147
)}
108148
</>
Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
11
.authorCard {
2-
position: relative;
32
width: 100%;
4-
margin-top: 1.25rem;
5-
padding: 1rem;
6-
padding-bottom: 3.75rem;
3+
margin-top: 1.5rem;
4+
padding: 1.5rem;
75
border: 1px solid var(--ifm-color-emphasis-300);
8-
border-radius: 12px;
9-
display: flex;
10-
align-items: stretch;
11-
justify-content: space-between;
12-
gap: 1rem;
13-
background: var(--ifm-background-surface-color);
6+
border-radius: 16px;
7+
background: linear-gradient(
8+
90deg,
9+
color-mix(in srgb, var(--ifm-color-emphasis-100) 80%, transparent),
10+
color-mix(in srgb, var(--ifm-color-emphasis-200) 45%, transparent)
11+
);
1412
box-sizing: border-box;
1513
}
1614

17-
.authorLeft {
15+
.authorBody {
1816
display: flex;
19-
align-items: center;
20-
gap: 0.75rem;
21-
min-width: 0;
17+
align-items: flex-start;
18+
gap: 1rem;
19+
}
20+
21+
.authorAvatarWrapper {
22+
position: relative;
23+
flex-shrink: 0;
24+
}
25+
26+
.verifiedBadge {
27+
position: absolute;
28+
right: -1px;
29+
bottom: -1px;
30+
width: 18px;
31+
height: 18px;
32+
border-radius: 999px;
33+
border: 2px solid var(--ifm-background-color);
34+
background: var(--ifm-color-success);
35+
color: var(--ifm-color-white);
36+
display: grid;
37+
place-items: center;
38+
font-size: 11px;
39+
line-height: 1;
40+
font-weight: 700;
2241
}
2342

2443
.authorAvatar,
2544
.authorAvatarFallback {
26-
width: 52px;
27-
height: 52px;
45+
width: 84px;
46+
height: 84px;
2847
border-radius: 50%;
29-
flex-shrink: 0;
3048
}
3149

3250
.authorAvatar {
@@ -44,56 +62,64 @@
4462

4563
.authorIdentity {
4664
min-width: 0;
65+
flex: 1;
4766
}
4867

4968
.authorName {
5069
margin: 0;
51-
font-weight: 700;
70+
font-size: 1.75rem;
71+
font-weight: 800;
5272
line-height: 1.2;
5373
}
5474

55-
.authorDate {
56-
margin: 0.25rem 0 0;
57-
color: var(--ifm-color-emphasis-700);
58-
font-size: 0.9rem;
75+
.authorNameRow {
76+
display: flex;
77+
align-items: center;
78+
gap: 0.75rem;
79+
flex-wrap: wrap;
5980
}
6081

61-
.authorSummary {
62-
margin: 0.45rem 0 0;
63-
color: var(--ifm-color-emphasis-800);
64-
font-size: 0.92rem;
65-
line-height: 1.4;
66-
max-width: 56ch;
82+
.authorBadge {
83+
padding: 0.2rem 0.55rem;
84+
border-radius: 999px;
85+
font-size: 0.75rem;
86+
font-weight: 600;
87+
color: var(--ifm-color-primary);
88+
background: var(--ifm-color-primary-contrast-background);
6789
}
6890

69-
.authorRight {
70-
margin-left: auto;
71-
display: flex;
72-
flex-direction: column;
73-
align-items: flex-end;
74-
justify-content: flex-start;
75-
gap: 0.75rem;
76-
text-align: right;
91+
.authorMeta {
92+
margin: 0.35rem 0 0;
93+
color: var(--ifm-color-emphasis-700);
94+
font-size: 1rem;
7795
}
7896

79-
.readTime {
80-
margin: 0;
81-
color: var(--ifm-color-emphasis-700);
82-
font-weight: 600;
97+
.authorSummary {
98+
margin: 0.65rem 0 0;
99+
color: var(--ifm-color-emphasis-800);
100+
font-size: 1.1rem;
101+
line-height: 1.4;
102+
max-width: 68ch;
83103
}
84104

85105
.githubButton {
86-
position: absolute;
87-
right: 1rem;
88-
bottom: 1rem;
106+
margin-top: 1rem;
89107
display: inline-flex;
90108
align-items: center;
91-
justify-content: center;
92-
padding: 0.45rem 0.8rem;
93-
border-radius: 8px;
94-
border: 1px solid var(--ifm-color-primary);
109+
gap: 0.4rem;
110+
padding: 0.35rem 0.9rem;
111+
border-radius: 999px;
112+
border: 1px solid var(--ifm-color-emphasis-300);
113+
background: var(--ifm-background-color);
114+
color: var(--ifm-font-color-base);
115+
font-size: 0.95rem;
95116
font-weight: 600;
96117
text-decoration: none;
118+
width: fit-content;
119+
}
120+
121+
.githubIcon {
122+
display: inline-flex;
97123
}
98124

99125
.githubButton:hover {
@@ -102,19 +128,20 @@
102128

103129
@media (max-width: 640px) {
104130
.authorCard {
105-
padding-bottom: 1rem;
131+
padding: 1rem;
132+
}
133+
134+
.authorBody {
106135
flex-direction: column;
107-
align-items: flex-start;
108136
}
109137

110-
.authorRight {
111-
width: 100%;
112-
margin-left: 0;
113-
align-items: flex-start;
114-
text-align: left;
138+
.authorAvatar,
139+
.authorAvatarFallback {
140+
width: 64px;
141+
height: 64px;
115142
}
116143

117-
.githubButton {
118-
position: static;
144+
.authorName {
145+
font-size: 1.25rem;
119146
}
120147
}

tsconfig.tsbuildinfo

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)