From afefb8fc5bd28da6e80eaeadf893e94ccfe14b2a Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Sun, 4 Jan 2026 01:32:59 -0500 Subject: [PATCH] fix mobile scroll, weird padding box, improve styles --- src/components/blog/PostBodyClient.tsx | 59 +++++++---- src/routes/blog/[title]/index.tsx | 140 ++++++++++++------------- src/routes/blog/post.css | 24 +++-- 3 files changed, 124 insertions(+), 99 deletions(-) diff --git a/src/components/blog/PostBodyClient.tsx b/src/components/blog/PostBodyClient.tsx index 3d46b54..0d4aec7 100644 --- a/src/components/blog/PostBodyClient.tsx +++ b/src/components/blog/PostBodyClient.tsx @@ -103,22 +103,47 @@ export default function PostBodyClient(props: PostBodyClientProps) { codeBlocks.forEach((codeBlock) => { const pre = codeBlock.parentElement; - if (!pre || pre.querySelector(".copy-button")) return; + if (!pre) return; + + // Check if already processed (has header with copy button) + const existingHeader = pre.previousElementSibling; + if ( + existingHeader?.classList.contains("language-header") && + existingHeader.querySelector(".copy-button") + ) { + return; + } + + // Set off-black background for code block + pre.style.backgroundColor = "#1a1a1a"; // Extract language from code block classes const classes = Array.from(codeBlock.classList); const languageClass = classes.find((cls) => cls.startsWith("language-")); const language = languageClass?.replace("language-", "") || ""; - // Create language header if language is detected and not already present - if ( - language && - pre.previousElementSibling?.classList.contains("language-header") === - false - ) { + // Create language header if language is detected + if (language) { const languageHeader = document.createElement("div"); languageHeader.className = "language-header"; - languageHeader.textContent = language; + languageHeader.style.backgroundColor = "#1a1a1a"; + + // Add language label + const languageLabel = document.createElement("span"); + languageLabel.textContent = language; + languageHeader.appendChild(languageLabel); + + // Create copy button in header + const copyButton = document.createElement("button"); + copyButton.className = "copy-button"; + copyButton.textContent = "Copy"; + copyButton.dataset.codeBlock = "true"; + + // Store reference to the code block for copying + copyButton.dataset.codeBlockId = `code-${Math.random().toString(36).substr(2, 9)}`; + codeBlock.dataset.codeBlockId = copyButton.dataset.codeBlockId; + + languageHeader.appendChild(copyButton); // Insert header before pre element pre.parentElement?.insertBefore(languageHeader, pre); @@ -144,14 +169,6 @@ export default function PostBodyClient(props: PostBodyClientProps) { pre.appendChild(lineNumbers); } - - // Create copy button - const copyButton = document.createElement("button"); - copyButton.className = "copy-button"; - copyButton.textContent = "Copy"; - copyButton.dataset.codeBlock = "true"; - - pre.appendChild(copyButton); }); }; @@ -340,8 +357,14 @@ export default function PostBodyClient(props: PostBodyClientProps) { // Handle click if (e.type === "click" && target.classList.contains("copy-button")) { - const pre = target.parentElement; - const codeBlock = pre?.querySelector("code"); + // Find the code block using the stored ID + const codeBlockId = target.dataset.codeBlockId; + const codeBlock = codeBlockId + ? contentRef?.querySelector( + `code[data-code-block-id="${codeBlockId}"]` + ) + : null; + if (!codeBlock) return; const code = codeBlock.textContent || ""; diff --git a/src/routes/blog/[title]/index.tsx b/src/routes/blog/[title]/index.tsx index 9ac37e1..fd6aa67 100644 --- a/src/routes/blog/[title]/index.tsx +++ b/src/routes/blog/[title]/index.tsx @@ -300,77 +300,73 @@ export default function PostPage() { }; return ( - - - - } - > - {(loadedData) => { - // Handle redirect for by-id route - if ("redirect" in loadedData()) { - return ; + + + + } + > + {(loadedData) => { + // Handle redirect for by-id route + if ("redirect" in loadedData()) { + return ; + } - return ( - } - > - {(p) => { - const postData = loadedData(); + return ( + } + > + {(p) => { + const postData = loadedData(); - // Convert arrays back to Maps for component - const userCommentMap = new Map( - postData.userCommentArray || [] - ); - const reactionMap = new Map( - postData.reactionArray || [] - ); + // Convert arrays back to Maps for component + const userCommentMap = new Map( + postData.userCommentArray || [] + ); + const reactionMap = new Map( + postData.reactionArray || [] + ); - return ( - <> - - {p().title.replaceAll("_", " ")} | Michael Freno - - + return ( + <> + + {p().title.replaceAll("_", " ")} | Michael Freno + + -
- {/* Fixed banner image background */} -
- post-cover -
-
- {p().title.replaceAll("_", " ")} - -
- {p().subtitle} -
-
+
+ {/* Fixed banner image background */} +
+ post-cover +
+
+ {p().title.replaceAll("_", " ")} + +
+ {p().subtitle} +
+
+
-
-
{/* Content that slides over the fixed image */}
@@ -506,14 +502,14 @@ export default function PostPage() {
- -
- - ); - }} - - ); - }} - +
+ + ); + }} + + ); + }} + + ); } diff --git a/src/routes/blog/post.css b/src/routes/blog/post.css index 54cb6f7..63ecb7a 100644 --- a/src/routes/blog/post.css +++ b/src/routes/blog/post.css @@ -692,7 +692,7 @@ button:active, position: relative; overflow: auto; max-height: 60vh; - background-color: var(--color-crust); + background-color: #1a1a1a; color: #fff; font-family: "Source Code Pro", monospace; border-radius: 0.5rem; @@ -711,12 +711,16 @@ button:active, /* Language header */ #post-content-body .language-header { + position: relative; + display: flex; + align-items: center; + justify-content: space-between; padding: 0.5rem 1rem; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; - background-color: var(--color-mantle); + background-color: #1a1a1a; color: var(--color-subtext1); border-bottom: 1px solid var(--color-surface0); border-top-left-radius: 0.375rem; @@ -741,7 +745,7 @@ button:active, text-align: right; user-select: none; pointer-events: none; - background-color: var(--color-crust); + background-color: #1a1a1a; border-right: 1px solid var(--color-surface0); color: var(--color-overlay0); font-size: 0.875rem; @@ -755,13 +759,13 @@ button:active, padding-left: 4rem; } -/* Copy button */ +/* Copy button - now in header */ #post-content-body .copy-button { - position: absolute; - top: 0.5rem; - right: 0.5rem; - padding: 0.375rem 0.75rem; - font-size: 0.75rem; + position: relative; + top: unset; + right: unset; + padding: 0.25rem 0.625rem; + font-size: 0.625rem; font-weight: 500; border-radius: 0.25rem; transition: all 0.2s; @@ -770,6 +774,8 @@ button:active, color: var(--color-text); border: 1px solid var(--color-overlay0); cursor: pointer; + text-transform: none; + letter-spacing: normal; } #post-content-body .copy-button:hover {