Skip to content

Revisar el sistema de temas del mapa #195

Open
@benjavicente

Description

@benjavicente

Me llamó la atención como está implementado los temas.

export const useThemeObserver = (map: mapboxgl.Map | undefined) => {
const [theme, setTheme] = useState(
typeof window !== "undefined" && localStorage?.theme === "dark" ? "dark-v11" : "streets-v12",
);
const observer = useRef<MutationObserver | null>(null);
const onClassChange = useCallback(() => {
if (typeof window !== "undefined") {
const isDark = document.documentElement.classList.contains("dark");
setTheme(isDark ? "dark-v11" : "streets-v12");
map?.setStyle(`mapbox://styles/mapbox/${isDark ? "dark-v11" : "streets-v12"}?optimize=true`);
}
}, [map, setTheme]);
useEffect(() => {
observer.current = new MutationObserver(onClassChange);
observer.current.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
return () => {
observer.current?.disconnect();
};
}, [onClassChange]);
return [theme];
};

¿Por qué es el hook que dicta el estilo del mapa? ¿No debería ser al revés?

export default function DarkModeSelector() {
const [isDark, setIsDark] = useState(false);
const [isButtonDisabled, setIsButtonDisabled] = useState(false);
const switchTheme = () => {
document.documentElement.classList.toggle("dark", !isDark);
setIsDark(!isDark);
localStorage.theme = !isDark ? "dark" : "light";
setIsButtonDisabled(true);
setTimeout(() => setIsButtonDisabled(false), 700);
};
const setSystemTheme = () => {
const savedTheme = localStorage.theme;
if (savedTheme === "dark" || (!savedTheme && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
switchTheme();
}
};
useEffect(() => {
setSystemTheme();
}, []);
return (
<div className="flex items-center ml-auto">
<button
className="rounded-lg hover:bg-sky-700 p-1 text-xl"
onClick={() => switchTheme()}
disabled={isButtonDisabled} // Deshabilitar el botón
>
{isDark ? "🌙" : "🌞"}
</button>
</div>
);
}

Este botón tiene mucha responsabilidad, yo haría que solo cambie le tema y no se preocupe de sincronizarlo.


Yo lo que recomendaría es cambiarlo para que sea como estos selectores de 3 estados: tema del dispositivo, dark mode, light mode.

  1. Crear un contexto global del tema.

Hacer un contexto de theme, donde se exponga el estado del tema actual (que depende de la clase dark o del prefers-color-scheme si es que no está la clase), y una función que cambie el tema a light, dark o reiniciar(null) que permita modificar la clase que modifica el tema.

El botón para cambiar el estilo usuarioa esta función, y cualquier js que requiera el tema actual, lo podría sacar de este hook.

  1. Aprovechar el css para definir cambios de colores (esto no está probado)
:root:not(.dark) {
  --bg-color: white;
  --text-color: black;
}

@media (prefers-color-scheme: dark) {
  :root:not(.light) {
    --bg-color: black;
    --text-color: white;
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions