Skip to content

Commit 00dc2a6

Browse files
committed
Merge remote-tracking branch 'upstream/main' into added-header-logo-in-darktheme
2 parents c6e0baf + b3f511c commit 00dc2a6

3 files changed

Lines changed: 372 additions & 1 deletion

File tree

src/css/custom.css

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2054,4 +2054,145 @@ html[data-theme="light"] {
20542054
html[data-theme="dark"] {
20552055
scrollbar-width: thin !important;
20562056
scrollbar-color: #334155 transparent !important;
2057-
}
2057+
}
2058+
2059+
/* =====================================================
2060+
SECTION 15: BLOG POST PAGE — CENTER + TOC FIX
2061+
2062+
SAFE: Only targets .blog-wrapper (individual post page)
2063+
Remove any previous SECTION 15 block before adding this.
2064+
===================================================== */
2065+
2066+
/* Full width container — no artificial max-width cutting space */
2067+
.blog-wrapper .container {
2068+
max-width: 100% !important;
2069+
width: 100% !important;
2070+
padding-left: 1rem !important;
2071+
padding-right: 1rem !important;
2072+
}
2073+
2074+
/* Row: full width flex, no gaps, sidebars hug the edges */
2075+
.blog-wrapper .container>.row {
2076+
display: flex !important;
2077+
flex-wrap: nowrap !important;
2078+
align-items: flex-start !important;
2079+
width: 100% !important;
2080+
margin: 0 !important;
2081+
padding: 0 !important;
2082+
}
2083+
2084+
/* LEFT sidebar — Recent Posts, fixed width, left edge */
2085+
.blog-wrapper .container>.row>.col.col--3 {
2086+
flex: 0 0 240px !important;
2087+
width: 240px !important;
2088+
max-width: 240px !important;
2089+
padding-left: 0.5rem !important;
2090+
padding-right: 1.5rem !important;
2091+
}
2092+
2093+
/* CENTER content — takes all remaining space between sidebars */
2094+
.blog-wrapper .container>.row>.col:not(.col--2):not(.col--3) {
2095+
flex: 1 1 auto !important;
2096+
min-width: 0 !important;
2097+
max-width: 100% !important;
2098+
/* Center the text content within this column */
2099+
padding-left: 3rem !important;
2100+
padding-right: 3rem !important;
2101+
}
2102+
2103+
/* RIGHT sidebar — TOC, wider so text is readable, right edge */
2104+
.blog-wrapper .container>.row>.col.col--2 {
2105+
flex: 0 0 280px !important;
2106+
/* ← expanded from ~220px to 280px */
2107+
width: 280px !important;
2108+
max-width: 280px !important;
2109+
padding-left: 1rem !important;
2110+
padding-right: 0.5rem !important;
2111+
}
2112+
2113+
/* TOC links: allow text to wrap properly instead of squishing */
2114+
.blog-wrapper .table-of-contents__link {
2115+
white-space: normal !important;
2116+
word-break: break-word !important;
2117+
line-height: 1.4 !important;
2118+
display: block !important;
2119+
padding: 2px 0 !important;
2120+
font-size: 0.85rem !important;
2121+
}
2122+
2123+
/* TOC heading items — slightly bolder for hierarchy */
2124+
.blog-wrapper .table-of-contents li>.table-of-contents__link {
2125+
font-size: 0.875rem !important;
2126+
}
2127+
2128+
/* Comfortable reading styles */
2129+
.blog-post-page .markdown {
2130+
max-width: 100% !important;
2131+
line-height: 1.8 !important;
2132+
}
2133+
2134+
/* ── Large desktop (≥1400px) ── */
2135+
@media (min-width: 1400px) {
2136+
.blog-wrapper .container>.row>.col.col--3 {
2137+
flex: 0 0 260px !important;
2138+
width: 260px !important;
2139+
max-width: 260px !important;
2140+
}
2141+
2142+
.blog-wrapper .container>.row>.col.col--2 {
2143+
flex: 0 0 300px !important;
2144+
width: 300px !important;
2145+
max-width: 300px !important;
2146+
}
2147+
2148+
.blog-wrapper .container>.row>.col:not(.col--2):not(.col--3) {
2149+
padding-left: 4rem !important;
2150+
padding-right: 4rem !important;
2151+
}
2152+
}
2153+
2154+
/* ── Tablet (997px–1199px) ── */
2155+
@media (max-width: 1199px) and (min-width: 997px) {
2156+
.blog-wrapper .container>.row>.col.col--3 {
2157+
flex: 0 0 200px !important;
2158+
width: 200px !important;
2159+
max-width: 200px !important;
2160+
}
2161+
2162+
.blog-wrapper .container>.row>.col.col--2 {
2163+
flex: 0 0 220px !important;
2164+
width: 220px !important;
2165+
max-width: 220px !important;
2166+
}
2167+
2168+
.blog-wrapper .container>.row>.col:not(.col--2):not(.col--3) {
2169+
padding-left: 2rem !important;
2170+
padding-right: 2rem !important;
2171+
}
2172+
}
2173+
2174+
/* ── Mobile (≤996px): stack columns naturally ── */
2175+
@media (max-width: 996px) {
2176+
.blog-wrapper .container {
2177+
padding-left: 1rem !important;
2178+
padding-right: 1rem !important;
2179+
}
2180+
2181+
.blog-wrapper .container>.row {
2182+
flex-direction: column !important;
2183+
}
2184+
2185+
.blog-wrapper .container>.row>.col.col--3,
2186+
.blog-wrapper .container>.row>.col.col--2,
2187+
.blog-wrapper .container>.row>.col:not(.col--2):not(.col--3) {
2188+
flex: 1 1 auto !important;
2189+
width: 100% !important;
2190+
max-width: 100% !important;
2191+
padding-left: 0 !important;
2192+
padding-right: 0 !important;
2193+
}
2194+
}
2195+
2196+
/* =====================================================
2197+
END SECTION 15
2198+
===================================================== */
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import React from "react";
2+
import Link from "@docusaurus/Link";
3+
import { useBlogPost } from "@docusaurus/plugin-content-blog/client";
4+
import BlogPostItemFooterOriginal from "@theme-original/BlogPostItem/Footer";
5+
import type BlogPostItemFooterType from "@theme/BlogPostItem/Footer";
6+
import type { WrapperProps } from "@docusaurus/types";
7+
import { getAuthorProfile } from "@site/src/utils/authors";
8+
9+
import styles from "./styles.module.css";
10+
11+
type Props = WrapperProps<typeof BlogPostItemFooterType>;
12+
13+
function getGitHubUrl(author: {
14+
key?: string;
15+
url?: string;
16+
name?: string;
17+
}): string | undefined {
18+
if (author.key) {
19+
return getAuthorProfile(author.key).githubUrl;
20+
}
21+
22+
if (author.url && /github\.com\//i.test(author.url)) {
23+
return author.url.startsWith("http") ? author.url : `https://${author.url}`;
24+
}
25+
26+
return undefined;
27+
}
28+
29+
export default function BlogPostItemFooterWrapper(props: Props): JSX.Element {
30+
const { metadata, isBlogPostPage } = useBlogPost();
31+
const primaryAuthor = metadata.authors?.[0];
32+
33+
const profile = primaryAuthor?.key
34+
? getAuthorProfile(primaryAuthor.key)
35+
: undefined;
36+
37+
const authorName = primaryAuthor?.name || profile?.name;
38+
const authorAvatar = primaryAuthor?.imageURL || profile?.imageUrl;
39+
const githubUrl = primaryAuthor
40+
? getGitHubUrl({
41+
key: primaryAuthor.key,
42+
name: primaryAuthor.name,
43+
url: primaryAuthor.url,
44+
})
45+
: undefined;
46+
47+
const roundedReadTime = Math.max(1, Math.ceil(metadata.readingTime || 0));
48+
const readTimeText = `${roundedReadTime} min read`;
49+
const authorSummary =
50+
primaryAuthor?.description ||
51+
profile?.description ||
52+
primaryAuthor?.title ||
53+
profile?.title;
54+
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+
: "");
63+
64+
const showAuthorCard = Boolean(isBlogPostPage && primaryAuthor && authorName);
65+
66+
return (
67+
<>
68+
<BlogPostItemFooterOriginal {...props} />
69+
{showAuthorCard && (
70+
<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+
)}
84+
<div className={styles.authorIdentity}>
85+
<p className={styles.authorName}>{authorName}</p>
86+
{blogDate ? <p className={styles.authorDate}>{blogDate}</p> : null}
87+
{authorSummary ? (
88+
<p className={styles.authorSummary}>{authorSummary}</p>
89+
) : null}
90+
</div>
91+
</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>
106+
</section>
107+
)}
108+
</>
109+
);
110+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
.authorCard {
2+
position: relative;
3+
width: 100%;
4+
margin-top: 1.25rem;
5+
padding: 1rem;
6+
padding-bottom: 3.75rem;
7+
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);
14+
box-sizing: border-box;
15+
}
16+
17+
.authorLeft {
18+
display: flex;
19+
align-items: center;
20+
gap: 0.75rem;
21+
min-width: 0;
22+
}
23+
24+
.authorAvatar,
25+
.authorAvatarFallback {
26+
width: 52px;
27+
height: 52px;
28+
border-radius: 50%;
29+
flex-shrink: 0;
30+
}
31+
32+
.authorAvatar {
33+
object-fit: cover;
34+
border: 1px solid var(--ifm-color-emphasis-300);
35+
}
36+
37+
.authorAvatarFallback {
38+
display: grid;
39+
place-items: center;
40+
font-weight: 700;
41+
color: var(--ifm-color-primary-darkest);
42+
background: var(--ifm-color-emphasis-200);
43+
}
44+
45+
.authorIdentity {
46+
min-width: 0;
47+
}
48+
49+
.authorName {
50+
margin: 0;
51+
font-weight: 700;
52+
line-height: 1.2;
53+
}
54+
55+
.authorDate {
56+
margin: 0.25rem 0 0;
57+
color: var(--ifm-color-emphasis-700);
58+
font-size: 0.9rem;
59+
}
60+
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;
67+
}
68+
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;
77+
}
78+
79+
.readTime {
80+
margin: 0;
81+
color: var(--ifm-color-emphasis-700);
82+
font-weight: 600;
83+
}
84+
85+
.githubButton {
86+
position: absolute;
87+
right: 1rem;
88+
bottom: 1rem;
89+
display: inline-flex;
90+
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);
95+
font-weight: 600;
96+
text-decoration: none;
97+
}
98+
99+
.githubButton:hover {
100+
text-decoration: none;
101+
}
102+
103+
@media (max-width: 640px) {
104+
.authorCard {
105+
padding-bottom: 1rem;
106+
flex-direction: column;
107+
align-items: flex-start;
108+
}
109+
110+
.authorRight {
111+
width: 100%;
112+
margin-left: 0;
113+
align-items: flex-start;
114+
text-align: left;
115+
}
116+
117+
.githubButton {
118+
position: static;
119+
}
120+
}

0 commit comments

Comments
 (0)