|
2 | 2 |
|
3 | 3 | No siempre tenemos que tirar de islas para todo, en este caso vamos a ver como tener tema claro y oscuro en nuestro sitio sin tener que tirar de islas. |
4 | 4 |
|
| 5 | +En esta caso con JavaScript y CSS lo vamos a dejar listo :). |
| 6 | + |
| 7 | +# Manos a la obra |
| 8 | + |
| 9 | +Vamos a añadir un componente para elegir el tema: |
| 10 | + |
| 11 | +_./src/components/theme-icon.astro_ |
| 12 | + |
| 13 | +```tsx |
| 14 | +--- |
| 15 | +--- |
| 16 | +<button id="themeToggle"> |
| 17 | + <svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> |
| 18 | + <path class="sun" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"/> |
| 19 | + <path class="moon" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"/> |
| 20 | + </svg> |
| 21 | +</button> |
| 22 | + |
| 23 | +<style> |
| 24 | + #themeToggle { |
| 25 | + border: 0; |
| 26 | + background: none; |
| 27 | + } |
| 28 | + .sun { fill: black; } |
| 29 | + .moon { fill: transparent; } |
| 30 | + |
| 31 | + :global(.dark) .sun { fill: transparent; } |
| 32 | + :global(.dark) .moon { fill: white; } |
| 33 | +</style> |
| 34 | +``` |
| 35 | + |
| 36 | +Vamos añadir este componente en el _header_ de la página: |
| 37 | + |
| 38 | +_./src/components/header.astro_ |
| 39 | + |
| 40 | +```diff |
| 41 | +--- |
| 42 | +import Hamburger from './hamburger.astro'; |
| 43 | ++ import ThemeIcon from './theme-icon.astro'; |
| 44 | +import Navigation from './navigation.astro'; |
| 45 | +--- |
| 46 | +<header> |
| 47 | + <nav> |
| 48 | + <Hamburger /> |
| 49 | ++ <ThemeIcon /> |
| 50 | + <Navigation /> |
| 51 | + </nav> |
| 52 | +</header> |
| 53 | +``` |
| 54 | + |
| 55 | +Y ahora vamos a añadir CSS global para definir los temas oscuros y claros: |
| 56 | + |
| 57 | +_./src/styles/global.css_ |
| 58 | + |
| 59 | +````diff |
| 60 | +html { |
| 61 | + background-color: #f1f5f9; |
| 62 | + font-family: sans-serif; |
| 63 | +} |
| 64 | + |
| 65 | ++ html.dark { |
| 66 | ++ background-color: #0d0950; |
| 67 | ++ color: #fff; |
| 68 | ++ } |
| 69 | ++ |
| 70 | ++ .dark .nav-links a { |
| 71 | ++ color: #fff; |
| 72 | ++ } |
| 73 | +`` |
| 74 | + |
| 75 | +Y volvemos al _header_ para añadir la lógica de cambio de tema (esta vez la vamos a hacer en JavaScript en línea, lo podríamos sacar a un fichero ts). |
| 76 | + |
| 77 | + |
| 78 | +_./src/components/theme-icon.astro_ |
| 79 | + |
| 80 | +```diff |
| 81 | +</button> |
| 82 | + |
| 83 | +<style> |
| 84 | + #themeToggle { |
| 85 | + border: 0; |
| 86 | + background: none; |
| 87 | + } |
| 88 | + .sun { fill: black; } |
| 89 | + .moon { fill: transparent; } |
| 90 | + |
| 91 | + :global(.dark) .sun { fill: transparent; } |
| 92 | + :global(.dark) .moon { fill: white; } |
| 93 | +</style> |
| 94 | + |
| 95 | + |
| 96 | ++ <script is:inline> |
| 97 | ++ const theme = (() => { |
| 98 | ++ if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) { |
| 99 | ++ return localStorage.getItem('theme'); |
| 100 | ++ } |
| 101 | ++ if (window.matchMedia('(prefers-color-scheme: dark)').matches) { |
| 102 | ++ return 'dark'; |
| 103 | ++ } |
| 104 | ++ return 'light'; |
| 105 | ++ })(); |
| 106 | ++ |
| 107 | ++ if (theme === 'light') { |
| 108 | ++ document.documentElement.classList.remove('dark'); |
| 109 | ++ } else { |
| 110 | ++ document.documentElement.classList.add('dark'); |
| 111 | ++ } |
| 112 | ++ |
| 113 | ++ window.localStorage.setItem('theme', theme); |
| 114 | ++ |
| 115 | ++ const handleToggleClick = () => { |
| 116 | ++ const element = document.documentElement; |
| 117 | ++ element.classList.toggle("dark"); |
| 118 | ++ |
| 119 | ++ const isDark = element.classList.contains("dark"); |
| 120 | ++ localStorage.setItem("theme", isDark ? "dark" : "light"); |
| 121 | ++ } |
| 122 | ++ |
| 123 | ++ document.getElementById("themeToggle").addEventListener("click", handleToggleClick); |
| 124 | ++ </script> |
| 125 | +```` |
0 commit comments