Skip to content

Instantly share code, notes, and snippets.

@intrnl
Created September 28, 2023 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save intrnl/643d174199ee07fecc054ccebcdf92b3 to your computer and use it in GitHub Desktop.
Save intrnl/643d174199ee07fecc054ccebcdf92b3 to your computer and use it in GitHub Desktop.
Solid.js media query
import { type Accessor, createSignal, onCleanup } from 'solid-js';
interface MediaStore {
/** State backing */
a: Accessor<boolean>;
/** Amount of subscriptions */
n: number;
/** Cleanup function */
c: () => void;
}
const map: Record<string, MediaStore> = {};
export const useMediaQuery = (query: string): Accessor<boolean> => {
let media = map[query];
if (!media) {
const matcher = window.matchMedia(query);
const [state, setState] = createSignal(matcher.matches);
const callback = () => setState(matcher.matches);
matcher.addEventListener('change', callback);
media = map[query] = {
n: 0,
a: state,
c: () => {
if (--media.n < 1) {
delete map[query];
matcher.removeEventListener('change', callback);
}
},
};
}
media.n++;
onCleanup(media.c);
return media.a;
};
@intrnl
Copy link
Author

intrnl commented Sep 28, 2023

App theming example

createRoot(() => {
    createRenderEffect((prev: LocalSettings['theme']) => {
        const prefs = preferences.local;
        const theme = prefs?.theme ?? 'auto';

        if (prev === theme) {
            return theme;
        }

        const cl = document.documentElement.classList;

        if (theme === 'auto') {
            const isDark = useMediaQuery('(prefers-color-scheme: dark)');

            createRenderEffect(() => {
                cl.toggle('is-dark', isDark());
            });
        } else {
            cl.toggle('is-dark', theme === 'dark');
        }

        return theme;
    });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment