Copilot commented on code in PR #147:
URL: https://github.com/apache/datafusion-site/pull/147#discussion_r2768783432


##########
_typos.toml:
##########
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Configuration for typos spell checker
+# https://github.com/crate-ci/typos
+
+# Custom dictionary for technical terms
+[default.extend-words]
+# Add any false positives here if needed 

Review Comment:
   There is a trailing space at the end of this comment line. Remove the 
trailing space to maintain clean code formatting.
   ```suggestion
   # Add any false positives here if needed
   ```



##########
.github/workflows/typo-check.yml:
##########
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Typo Check
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+
+jobs:
+  typos:
+    name: Spell Check with Typos
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8  # 
v5.0.0

Review Comment:
   The version v5.0.0 of actions/checkout should be verified. As of January 
2025, the latest major version was v4. If v5 has been released since then, this 
is correct. However, for consistency with other workflows in this repository 
(publish-site.yml and stage-site.yml), consider using the same version notation 
style. The other workflows use @v4 instead of pinned hashes. If pinned hashes 
are preferred for security, consider updating the other workflows as well for 
consistency.



##########
content/theme/templates/menu.html:
##########
@@ -15,6 +15,10 @@
                     <a class="nav-link" href="/blog/feed.xml">RSS</a>
                 </li>
             </ul>
+            <button id="theme-toggle" class="theme-toggle" aria-label="Toggle 
dark mode" title="Toggle dark mode">
+                <span class="icon-sun">☀️</span>
+                <span class="icon-moon">🌙</span>

Review Comment:
   Using emoji characters (☀️ and 🌙) for the toggle icons may cause 
inconsistent rendering across different browsers and operating systems. 
Consider using SVG icons or icon fonts (like the FontAwesome already included 
in the project) for more consistent cross-platform appearance and better 
control over styling. Additionally, the emoji may be announced by screen 
readers, which could be confusing since the button already has an aria-label.
   ```suggestion
                   <i class="icon-sun fa-regular fa-sun" aria-hidden="true"></i>
                   <i class="icon-moon fa-regular fa-moon" 
aria-hidden="true"></i>
   ```



##########
content/css/darkmode.css:
##########
@@ -0,0 +1,673 @@
+/* Dark Mode Styles for Apache DataFusion Blog */
+
+/* Root variables for light mode (default) */
+:root {
+    --bg-primary: #ffffff;
+    --bg-secondary: #f8f9fa;
+    --bg-tertiary: #e9ecef;
+    --text-primary: #212529;
+    --text-secondary: #6c757d;
+    --text-muted: #868e96;
+    --border-color: #dee2e6;
+    --callout-bg: #f8f9fa;
+    --code-bg: #f8f9fa;
+    --link-color: #0d6efd;
+    --link-hover: #0a58ca;
+    --toc-border: #eee;
+    --shadow: rgba(0, 0, 0, 0.1);
+    --accent-color: #0d6efd;
+}
+
+/* Dark mode variables - Modern, high contrast palette */
+[data-theme="dark"] {
+    --bg-primary: #0d1117;
+    --bg-secondary: #161b22;
+    --bg-tertiary: #1c2128;
+    --text-primary: #e6edf3;
+    --text-secondary: #8b949e;
+    --text-muted: #6e7681;
+    --border-color: #30363d;
+    --callout-bg: #161b22;
+    --code-bg: #0d1117;
+    --link-color: #58a6ff;
+    --link-hover: #79c0ff;
+    --toc-border: #30363d;
+    --shadow: rgba(0, 0, 0, 0.5);
+    --accent-color: #58a6ff;
+}
+
+/* Apply dark mode styles */
+[data-theme="dark"] body {
+    background-color: var(--bg-primary);
+    color: var(--text-primary);
+}
+
+/* Main content areas */
+[data-theme="dark"] .bg-white {
+    background-color: var(--bg-primary) !important;
+}
+
+[data-theme="dark"] .bg-light {
+    background-color: var(--bg-secondary) !important;
+}
+
+[data-theme="dark"] #contents {
+    background-color: var(--bg-primary);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] #contents > .bg-white {
+    background-color: var(--bg-secondary) !important;
+    border: 1px solid var(--border-color);
+}
+
+/* Callout boxes - prominent styling */
+[data-theme="dark"] .callout {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    border-left: 4px solid var(--accent-color);
+    padding: 1.5rem;
+    margin: 1rem 0;
+    border-radius: 8px;
+    box-shadow: 0 2px 8px var(--shadow);
+}
+
+[data-theme="dark"] .post {
+    background-color: transparent;
+}
+
+[data-theme="dark"] .post header {
+    border-bottom: 1px solid var(--border-color);
+    padding-bottom: 1rem;
+    margin-bottom: 1rem;
+}
+
+/* Table of Contents */
+[data-theme="dark"] .toc {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+    border-radius: 8px;
+}
+
+[data-theme="dark"] .toc a {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] .toc a:hover {
+    color: var(--link-color);
+}
+
+/* Links */
+[data-theme="dark"] a {
+    color: var(--link-color);
+    text-decoration: none;
+}
+
+[data-theme="dark"] a:hover {
+    color: var(--link-hover);
+    text-decoration: underline;
+}
+
+/* Code blocks and inline code */
+[data-theme="dark"] code {
+    background-color: var(--bg-tertiary);
+    color: #ff7b72;
+    padding: 0.2em 0.4em;
+    border-radius: 4px;
+    font-size: 0.9em;
+}
+
+[data-theme="dark"] pre {
+    background-color: var(--code-bg);
+    border: 1px solid var(--border-color);
+    border-radius: 8px;
+    padding: 1rem;
+    overflow-x: auto;
+}
+
+[data-theme="dark"] pre code {
+    background-color: transparent;
+    color: var(--text-primary);
+    padding: 0;
+}
+
+/* Tables */
+[data-theme="dark"] .table {
+    color: var(--text-primary);
+    border-color: var(--border-color);
+}
+
+[data-theme="dark"] .table-striped > tbody > tr:nth-of-type(odd) > * {
+    background-color: var(--bg-tertiary);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .table > :not(caption) > * > * {
+    background-color: transparent;
+    border-bottom-color: var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .table > thead {
+    border-bottom: 2px solid var(--border-color);
+}
+
+/* Blockquotes */
+[data-theme="dark"] blockquote {
+    border-left: 4px solid var(--accent-color);
+    padding-left: 1rem;
+    margin-left: 0;
+    color: var(--text-secondary);
+    background-color: var(--bg-tertiary);
+    padding: 1rem;
+    border-radius: 4px;
+}
+
+/* Horizontal rules */
+[data-theme="dark"] hr {
+    border-color: var(--border-color);
+    opacity: 0.5;
+}
+
+/* Buttons - comprehensive styling */
+[data-theme="dark"] button,
+[data-theme="dark"] .button,
+[data-theme="dark"] a.button {
+    background-color: var(--accent-color);
+    color: #ffffff;
+    border: 1px solid var(--accent-color);
+    padding: 0.5rem 1.25rem;
+    border-radius: 6px;
+    font-weight: 500;
+    cursor: pointer;
+    transition: all 0.2s ease;
+    text-decoration: none;
+    display: inline-block;
+}
+
+[data-theme="dark"] button:hover,
+[data-theme="dark"] .button:hover,
+[data-theme="dark"] a.button:hover {
+    background-color: var(--link-hover);
+    border-color: var(--link-hover);
+    color: #ffffff;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(88, 166, 255, 0.3);
+    text-decoration: none;
+}
+
+[data-theme="dark"] button:active,
+[data-theme="dark"] .button:active,
+[data-theme="dark"] a.button:active {
+    transform: translateY(0);
+}
+
+/* Comment buttons specific styling */
+[data-theme="dark"] #giscus-load,
+[data-theme="dark"] #giscus-revoke {
+    background-color: var(--bg-tertiary);
+    color: var(--text-primary);
+    border: 1px solid var(--border-color);
+}
+
+[data-theme="dark"] #giscus-load:hover,
+[data-theme="dark"] #giscus-revoke:hover {
+    background-color: var(--accent-color);
+    border-color: var(--accent-color);
+    color: #ffffff;
+}
+
+/* Cards and list items */
+[data-theme="dark"] .card {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .list-group-item {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .list-group-item:hover {
+    background-color: var(--bg-secondary);
+}
+
+/* Post titles and article content */
+[data-theme="dark"] .post header .title h1 a {
+    color: var(--text-primary);
+    font-weight: 600;
+}
+
+[data-theme="dark"] .post header .title h1 a:hover {
+    color: var(--link-hover);
+    text-decoration: none;
+}
+
+[data-theme="dark"] .post header p {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] article {
+    color: var(--text-primary);
+}
+
+/* Headings */
+[data-theme="dark"] h1, 
+[data-theme="dark"] h2, 
+[data-theme="dark"] h3, 
+[data-theme="dark"] h4, 
+[data-theme="dark"] h5, 
+[data-theme="dark"] h6 {
+    color: var(--text-primary);
+    font-weight: 600;
+}
+
+[data-theme="dark"] h1 {
+    border-bottom: 2px solid var(--border-color);
+    padding-bottom: 0.5rem;
+}
+
+[data-theme="dark"] p {
+    color: var(--text-primary);
+}
+
+/* Lists */
+[data-theme="dark"] ul,
+[data-theme="dark"] ol {
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] li {
+    color: var(--text-primary);
+}
+
+/* Stats and tags */
+[data-theme="dark"] .stats li {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] .stats li a {
+    color: var(--text-secondary);
+    background-color: var(--bg-tertiary);
+    padding: 0.25rem 0.75rem;
+    border-radius: 12px;
+    border: 1px solid var(--border-color);
+}
+
+[data-theme="dark"] .stats li a:hover {
+    color: var(--link-hover);
+    border-color: var(--accent-color);
+    text-decoration: none;
+}
+
+/* Navbar - ensure it looks good in dark mode */
+[data-theme="dark"] .navbar-dark {
+    background-color: #0d1117 !important;
+    border-bottom: 1px solid var(--border-color);
+}
+
+[data-theme="dark"] .navbar-brand {
+    color: var(--text-primary) !important;
+}
+
+[data-theme="dark"] .nav-link {
+    color: var(--text-secondary) !important;
+}
+
+[data-theme="dark"] .nav-link:hover {
+    color: var(--link-color) !important;
+}
+
+/* Footer adjustments */
+[data-theme="dark"] footer,
+[data-theme="dark"] .row.g-0 {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] footer a {
+    color: var(--link-color);
+}
+
+/* Image adjustments for dark mode */
+[data-theme="dark"] img:not([src*="logo"]) {
+    opacity: 0.9;
+    border-radius: 4px;
+}
+
+[data-theme="dark"] img:not([src*="logo"]):hover {
+    opacity: 1;
+}
+
+/* Forms and inputs */
+[data-theme="dark"] input,
+[data-theme="dark"] textarea,
+[data-theme="dark"] select {
+    background-color: var(--bg-tertiary);
+    border-color: var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] input:focus,
+[data-theme="dark"] textarea:focus,
+[data-theme="dark"] select:focus {
+    background-color: var(--bg-secondary);
+    border-color: var(--accent-color);
+    outline: none;
+    box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.1);
+}
+
+/* Kbd styling */
+[data-theme="dark"] kbd {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+}
+
+/* Figure caption */
+[data-theme="dark"] figcaption {
+    color: var(--text-secondary);
+}
+
+/* Mark/highlight */
+[data-theme="dark"] mark {
+    background-color: #ffc10726;
+    color: var(--text-primary);
+}
+
+/* Scrollbar styling for dark mode */
+[data-theme="dark"] ::-webkit-scrollbar {
+    width: 12px;
+    height: 12px;
+}
+
+[data-theme="dark"] ::-webkit-scrollbar-track {
+    background: var(--bg-secondary);
+}
+
+[data-theme="dark"] ::-webkit-scrollbar-thumb {
+    background: var(--border-color);
+    border-radius: 6px;
+}
+
+[data-theme="dark"] ::-webkit-scrollbar-thumb:hover {
+    background: var(--text-muted);
+}

Review Comment:
   Add a blank line before this comment for better readability and consistency 
with the rest of the CSS file structure.
   ```suggestion
   }
   ```



##########
content/js/darkmode.js:
##########
@@ -0,0 +1,93 @@
+/**
+ * Dark Mode Toggle Functionality for Apache DataFusion Blog
+ */
+
+(function() {
+    'use strict';
+
+    // Constants
+    const THEME_KEY = 'datafusion-theme';
+    const THEME_DARK = 'dark';
+    const THEME_LIGHT = 'light';
+
+    /**
+     * Get the current theme from localStorage or system preference
+     */
+    function getStoredTheme() {
+        return localStorage.getItem(THEME_KEY);
+    }
+
+    /**
+     * Get the preferred theme based on system settings
+     */
+    function getPreferredTheme() {
+        const storedTheme = getStoredTheme();
+        if (storedTheme) {
+            return storedTheme;
+        }
+        // Check system preference
+        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 
THEME_DARK : THEME_LIGHT;
+    }
+
+    /**
+     * Set the theme on the document
+     */
+    function setTheme(theme) {
+        if (theme === THEME_DARK) {
+            document.documentElement.setAttribute('data-theme', THEME_DARK);
+        } else {
+            document.documentElement.removeAttribute('data-theme');
+        }
+        localStorage.setItem(THEME_KEY, theme);
+    }
+
+    /**
+     * Toggle between light and dark themes
+     */
+    function toggleTheme() {
+        const currentTheme = getStoredTheme() || THEME_LIGHT;
+        const newTheme = currentTheme === THEME_DARK ? THEME_LIGHT : 
THEME_DARK;
+        setTheme(newTheme);
+    }
+
+    /**
+     * Initialize theme on page load
+     */
+    function initTheme() {
+        // Apply theme immediately to prevent flash
+        setTheme(getPreferredTheme());
+
+        // Add event listener to toggle button when DOM is ready
+        if (document.readyState === 'loading') {
+            document.addEventListener('DOMContentLoaded', 
attachToggleListener);
+        } else {
+            attachToggleListener();
+        }
+    }
+
+    /**
+     * Attach click event listener to theme toggle button
+     */
+    function attachToggleListener() {
+        const toggleButton = document.getElementById('theme-toggle');
+        if (toggleButton) {
+            toggleButton.addEventListener('click', function(e) {
+                e.preventDefault();
+                toggleTheme();
+            });

Review Comment:
   The theme toggle button should indicate its current state for screen reader 
users. Consider updating the aria-label dynamically to indicate the current 
state (e.g., "Enable dark mode" vs "Enable light mode") or add an aria-pressed 
attribute that is toggled when the theme changes. This would improve 
accessibility by letting screen reader users know the current theme state and 
what clicking the button will do.



##########
content/css/darkmode.css:
##########
@@ -0,0 +1,673 @@
+/* Dark Mode Styles for Apache DataFusion Blog */
+
+/* Root variables for light mode (default) */
+:root {
+    --bg-primary: #ffffff;
+    --bg-secondary: #f8f9fa;
+    --bg-tertiary: #e9ecef;
+    --text-primary: #212529;
+    --text-secondary: #6c757d;
+    --text-muted: #868e96;
+    --border-color: #dee2e6;
+    --callout-bg: #f8f9fa;
+    --code-bg: #f8f9fa;
+    --link-color: #0d6efd;
+    --link-hover: #0a58ca;
+    --toc-border: #eee;
+    --shadow: rgba(0, 0, 0, 0.1);
+    --accent-color: #0d6efd;
+}
+
+/* Dark mode variables - Modern, high contrast palette */
+[data-theme="dark"] {
+    --bg-primary: #0d1117;
+    --bg-secondary: #161b22;
+    --bg-tertiary: #1c2128;
+    --text-primary: #e6edf3;
+    --text-secondary: #8b949e;
+    --text-muted: #6e7681;
+    --border-color: #30363d;
+    --callout-bg: #161b22;
+    --code-bg: #0d1117;
+    --link-color: #58a6ff;
+    --link-hover: #79c0ff;
+    --toc-border: #30363d;
+    --shadow: rgba(0, 0, 0, 0.5);
+    --accent-color: #58a6ff;
+}
+
+/* Apply dark mode styles */
+[data-theme="dark"] body {
+    background-color: var(--bg-primary);
+    color: var(--text-primary);
+}
+
+/* Main content areas */
+[data-theme="dark"] .bg-white {
+    background-color: var(--bg-primary) !important;
+}
+
+[data-theme="dark"] .bg-light {
+    background-color: var(--bg-secondary) !important;
+}
+
+[data-theme="dark"] #contents {
+    background-color: var(--bg-primary);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] #contents > .bg-white {
+    background-color: var(--bg-secondary) !important;
+    border: 1px solid var(--border-color);
+}
+
+/* Callout boxes - prominent styling */
+[data-theme="dark"] .callout {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    border-left: 4px solid var(--accent-color);
+    padding: 1.5rem;
+    margin: 1rem 0;
+    border-radius: 8px;
+    box-shadow: 0 2px 8px var(--shadow);
+}
+
+[data-theme="dark"] .post {
+    background-color: transparent;
+}
+
+[data-theme="dark"] .post header {
+    border-bottom: 1px solid var(--border-color);
+    padding-bottom: 1rem;
+    margin-bottom: 1rem;
+}
+
+/* Table of Contents */
+[data-theme="dark"] .toc {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+    border-radius: 8px;
+}
+
+[data-theme="dark"] .toc a {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] .toc a:hover {
+    color: var(--link-color);
+}
+
+/* Links */
+[data-theme="dark"] a {
+    color: var(--link-color);
+    text-decoration: none;
+}
+
+[data-theme="dark"] a:hover {
+    color: var(--link-hover);
+    text-decoration: underline;
+}
+
+/* Code blocks and inline code */
+[data-theme="dark"] code {
+    background-color: var(--bg-tertiary);
+    color: #ff7b72;
+    padding: 0.2em 0.4em;
+    border-radius: 4px;
+    font-size: 0.9em;
+}
+
+[data-theme="dark"] pre {
+    background-color: var(--code-bg);
+    border: 1px solid var(--border-color);
+    border-radius: 8px;
+    padding: 1rem;
+    overflow-x: auto;
+}
+
+[data-theme="dark"] pre code {
+    background-color: transparent;
+    color: var(--text-primary);
+    padding: 0;
+}
+
+/* Tables */
+[data-theme="dark"] .table {
+    color: var(--text-primary);
+    border-color: var(--border-color);
+}
+
+[data-theme="dark"] .table-striped > tbody > tr:nth-of-type(odd) > * {
+    background-color: var(--bg-tertiary);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .table > :not(caption) > * > * {
+    background-color: transparent;
+    border-bottom-color: var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .table > thead {
+    border-bottom: 2px solid var(--border-color);
+}
+
+/* Blockquotes */
+[data-theme="dark"] blockquote {
+    border-left: 4px solid var(--accent-color);
+    padding-left: 1rem;
+    margin-left: 0;
+    color: var(--text-secondary);
+    background-color: var(--bg-tertiary);
+    padding: 1rem;
+    border-radius: 4px;
+}
+
+/* Horizontal rules */
+[data-theme="dark"] hr {
+    border-color: var(--border-color);
+    opacity: 0.5;
+}
+
+/* Buttons - comprehensive styling */
+[data-theme="dark"] button,
+[data-theme="dark"] .button,
+[data-theme="dark"] a.button {
+    background-color: var(--accent-color);
+    color: #ffffff;
+    border: 1px solid var(--accent-color);
+    padding: 0.5rem 1.25rem;
+    border-radius: 6px;
+    font-weight: 500;
+    cursor: pointer;
+    transition: all 0.2s ease;
+    text-decoration: none;
+    display: inline-block;
+}
+
+[data-theme="dark"] button:hover,
+[data-theme="dark"] .button:hover,
+[data-theme="dark"] a.button:hover {
+    background-color: var(--link-hover);
+    border-color: var(--link-hover);
+    color: #ffffff;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(88, 166, 255, 0.3);
+    text-decoration: none;
+}
+
+[data-theme="dark"] button:active,
+[data-theme="dark"] .button:active,
+[data-theme="dark"] a.button:active {
+    transform: translateY(0);
+}
+
+/* Comment buttons specific styling */
+[data-theme="dark"] #giscus-load,
+[data-theme="dark"] #giscus-revoke {
+    background-color: var(--bg-tertiary);
+    color: var(--text-primary);
+    border: 1px solid var(--border-color);
+}
+
+[data-theme="dark"] #giscus-load:hover,
+[data-theme="dark"] #giscus-revoke:hover {
+    background-color: var(--accent-color);
+    border-color: var(--accent-color);
+    color: #ffffff;
+}
+
+/* Cards and list items */
+[data-theme="dark"] .card {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .list-group-item {
+    background-color: var(--bg-tertiary);
+    border: 1px solid var(--border-color);
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] .list-group-item:hover {
+    background-color: var(--bg-secondary);
+}
+
+/* Post titles and article content */
+[data-theme="dark"] .post header .title h1 a {
+    color: var(--text-primary);
+    font-weight: 600;
+}
+
+[data-theme="dark"] .post header .title h1 a:hover {
+    color: var(--link-hover);
+    text-decoration: none;
+}
+
+[data-theme="dark"] .post header p {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] article {
+    color: var(--text-primary);
+}
+
+/* Headings */
+[data-theme="dark"] h1, 
+[data-theme="dark"] h2, 
+[data-theme="dark"] h3, 
+[data-theme="dark"] h4, 
+[data-theme="dark"] h5, 
+[data-theme="dark"] h6 {
+    color: var(--text-primary);
+    font-weight: 600;
+}
+
+[data-theme="dark"] h1 {
+    border-bottom: 2px solid var(--border-color);
+    padding-bottom: 0.5rem;
+}
+
+[data-theme="dark"] p {
+    color: var(--text-primary);
+}
+
+/* Lists */
+[data-theme="dark"] ul,
+[data-theme="dark"] ol {
+    color: var(--text-primary);
+}
+
+[data-theme="dark"] li {
+    color: var(--text-primary);
+}
+
+/* Stats and tags */
+[data-theme="dark"] .stats li {
+    color: var(--text-secondary);
+}
+
+[data-theme="dark"] .stats li a {
+    color: var(--text-secondary);
+    background-color: var(--bg-tertiary);
+    padding: 0.25rem 0.75rem;
+    border-radius: 12px;
+    border: 1px solid var(--border-color);
+}
+
+[data-theme="dark"] .stats li a:hover {
+    color: var(--link-hover);
+    border-color: var(--accent-color);
+    text-decoration: none;
+}
+
+/* Navbar - ensure it looks good in dark mode */
+[data-theme="dark"] .navbar-dark {
+    background-color: #0d1117 !important;

Review Comment:
   For consistency with the rest of the CSS, consider using the CSS variable 
instead of the hardcoded color value. Replace `#0d1117` with 
`var(--bg-primary)` to maintain consistency with the color scheme defined at 
the top of the file.
   ```suggestion
       background-color: var(--bg-primary) !important;
   ```



##########
content/theme/templates/menu.html:
##########
@@ -15,6 +15,10 @@
                     <a class="nav-link" href="/blog/feed.xml">RSS</a>
                 </li>
             </ul>
+            <button id="theme-toggle" class="theme-toggle" aria-label="Toggle 
dark mode" title="Toggle dark mode">

Review Comment:
   The button element should have an explicit type attribute. Add 
`type="button"` to prevent the button from inadvertently submitting forms if 
it's ever placed inside a form element.
   ```suggestion
               <button id="theme-toggle" class="theme-toggle" type="button" 
aria-label="Toggle dark mode" title="Toggle dark mode">
   ```



##########
content/js/darkmode.js:
##########
@@ -0,0 +1,93 @@
+/**
+ * Dark Mode Toggle Functionality for Apache DataFusion Blog
+ */
+
+(function() {
+    'use strict';
+
+    // Constants
+    const THEME_KEY = 'datafusion-theme';
+    const THEME_DARK = 'dark';
+    const THEME_LIGHT = 'light';
+
+    /**
+     * Get the current theme from localStorage or system preference
+     */
+    function getStoredTheme() {
+        return localStorage.getItem(THEME_KEY);
+    }
+
+    /**
+     * Get the preferred theme based on system settings
+     */
+    function getPreferredTheme() {
+        const storedTheme = getStoredTheme();
+        if (storedTheme) {
+            return storedTheme;
+        }
+        // Check system preference
+        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 
THEME_DARK : THEME_LIGHT;
+    }
+
+    /**
+     * Set the theme on the document
+     */
+    function setTheme(theme) {
+        if (theme === THEME_DARK) {
+            document.documentElement.setAttribute('data-theme', THEME_DARK);
+        } else {
+            document.documentElement.removeAttribute('data-theme');
+        }
+        localStorage.setItem(THEME_KEY, theme);

Review Comment:
   The localStorage access should be wrapped in try-catch blocks to handle 
cases where localStorage is disabled, unavailable (e.g., in private browsing 
mode), or when storage quota is exceeded. Without error handling, the entire 
script could fail silently, preventing the theme toggle functionality from 
working. Consider wrapping localStorage calls in try-catch blocks similar to 
how giscus-consent.js handles it.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to