Fork of Chiri for Astro for my blog
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore(favicon): improve theme handling

the3ash aefddc95 1e7164bb

+93 -26
+10
netlify.toml
··· 39 39 object-src 'none'; 40 40 worker-src 'self' blob:; 41 41 child-src 'self' blob:; 42 + media-src 'self' blob:; 42 43 ''' 43 44 44 45 # Static assets caching ··· 96 97 for = "*.webp" 97 98 [headers.values] 98 99 Cache-Control = "public, max-age=31536000, immutable" 100 + Vary = "Accept-Encoding" 101 + 102 + # Favicon - no cache for real-time theme switching 103 + [[headers]] 104 + for = "/favicon.svg" 105 + [headers.values] 106 + Cache-Control = "no-cache, no-store, must-revalidate" 107 + Pragma = "no-cache" 108 + Expires = "0" 99 109 Vary = "Accept-Encoding" 100 110 101 111 # Homepage with resource hints
+2 -10
public/favicon.svg
··· 1 1 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 2 <path 3 + id="favicon-path" 3 4 d="M12.3785 2C16.2799 2.0001 15.793 5.9958 15.3053 7.99414C16.7687 6.99515 19.8498 5.92943 21.6451 8.99414C23.1079 11.4917 19.6947 14.3221 17.7437 14.9883C19.2069 15.9875 21.3523 18.5847 18.231 20.9824C15.1095 23.3803 12.7031 20.983 11.8902 19.4844C10.9146 20.983 8.28152 23.3801 5.55039 20.9824C2.81905 18.5846 4.41233 16.3199 5.55039 15.4873C3.76201 14.9878 0.672689 12.0909 2.62363 8.49414C3.85202 6.22947 7.01339 6.66254 7.98886 7.49512C7.6637 5.66344 8.47661 2 12.3785 2ZM12.3121 9.49316C8.42708 9.49327 7.3044 16.1247 12.3121 15.4375C15.6222 14.9833 15.6814 9.49316 12.3121 9.49316Z" 5 + fill="#111" 4 6 /> 5 - <style> 6 - path { 7 - fill:#111; 8 - } 9 - @media (prefers-color-scheme: dark) { 10 - path { 11 - fill: #ccc; 12 - } 13 - } 14 - </style> 15 7 </svg>
-16
src/components/layout/BaseHead.astro
··· 101 101 return isDark ? 'dark' : 'light' 102 102 } 103 103 104 - // Get current actual theme state 105 - function getCurrentTheme() { 106 - const hasLight = htmlElement.classList.contains('light') 107 - const hasDark = htmlElement.classList.contains('dark') 108 - 109 - if (hasLight) { 110 - return 'light' 111 - } 112 - if (hasDark) { 113 - return 'dark' 114 - } 115 - 116 - const systemTheme = getSystemTheme() 117 - return systemTheme 118 - } 119 - 120 104 // Apply theme 121 105 function applyTheme(theme) { 122 106 htmlElement.classList.remove('light', 'dark')
+79
src/components/ui/FaviconThemeSwitcher.astro
··· 1 + <script is:inline> 2 + // Favicon theme switcher for system theme-based favicon updates 3 + class FaviconThemeSwitcher { 4 + constructor() { 5 + this.faviconLink = document.querySelector('link[rel="icon"]') 6 + this.currentColor = null 7 + this.init() 8 + } 9 + 10 + init() { 11 + // Listen for system theme changes only 12 + this.observeSystemThemeChanges() 13 + 14 + // Set initial favicon color based on system theme 15 + this.updateFaviconForSystemTheme() 16 + } 17 + 18 + observeSystemThemeChanges() { 19 + // Listen for system theme changes using media query 20 + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') 21 + 22 + mediaQuery.addEventListener('change', () => { 23 + this.updateFaviconForSystemTheme() 24 + }) 25 + } 26 + 27 + updateFaviconForSystemTheme() { 28 + // Only use system theme preference, ignore manual theme toggle 29 + const isSystemDark = window.matchMedia('(prefers-color-scheme: dark)').matches 30 + const newColor = isSystemDark ? '#ccc' : '#111' 31 + 32 + // Only update if color has changed 33 + if (this.currentColor !== newColor) { 34 + this.currentColor = newColor 35 + this.updateFaviconColor(newColor) 36 + } 37 + } 38 + 39 + updateFaviconColor(color) { 40 + if (!this.faviconLink) return 41 + 42 + const currentHref = this.faviconLink.href 43 + 44 + fetch(currentHref) 45 + .then((response) => response.text()) 46 + .then((svgText) => { 47 + const parser = new DOMParser() 48 + const svgDoc = parser.parseFromString(svgText, 'image/svg+xml') 49 + const path = svgDoc.getElementById('favicon-path') 50 + 51 + if (path) { 52 + path.setAttribute('fill', color) 53 + const serializer = new XMLSerializer() 54 + const updatedSvg = serializer.serializeToString(svgDoc) 55 + const blob = new Blob([updatedSvg], { type: 'image/svg+xml' }) 56 + const url = URL.createObjectURL(blob) 57 + this.faviconLink.href = url 58 + } 59 + }) 60 + .catch((error) => { 61 + console.warn('Failed to update favicon color:', error) 62 + }) 63 + } 64 + } 65 + 66 + // Initialize favicon theme switcher when DOM is ready 67 + if (document.readyState === 'loading') { 68 + document.addEventListener('DOMContentLoaded', () => { 69 + new FaviconThemeSwitcher() 70 + }) 71 + } else { 72 + new FaviconThemeSwitcher() 73 + } 74 + 75 + // Re-initialize on Astro page loads 76 + document.addEventListener('astro:page-load', () => { 77 + new FaviconThemeSwitcher() 78 + }) 79 + </script>
+2
src/layouts/BaseLayout.astro
··· 1 1 --- 2 2 import { themeConfig } from '@/config' 3 3 import TransitionWrapper from '@/components/layout/TransitionWrapper.astro' 4 + import FaviconThemeSwitcher from '@/components/ui/FaviconThemeSwitcher.astro' 4 5 import type { LayoutProps } from '@/types' 5 6 6 7 type Props = LayoutProps ··· 34 35 <TransitionWrapper type={type} class="layout-wrapper"> 35 36 <slot /> 36 37 </TransitionWrapper> 38 + <FaviconThemeSwitcher /> 37 39 </body> 38 40 </html> 39 41