@solid-primitives/media
Collection of reactive primitives to deal with media queries.
Installation
npm install @solid-primitives/media
# or
yarn add @solid-primitives/media
makeMediaQueryListener
Attaches a MediaQuery listener to window, listeneing to changes to provided query
import { makeMediaQueryListener } from "@solid-primitives/media";
const clear = makeMediaQueryListener("(max-width: 767px)", e => {
console.log(e.matches);
});
clear();
createMediaQuery
Creates a very simple and straightforward media query monitor.
import { createMediaQuery } from "@solid-primitives/media";
const isSmall = createMediaQuery("(max-width: 767px)");
console.log(isSmall());
Server fallback
createMediaQuery
accepts a serverFallback
argument — value that should be returned on the server — defaults to false
.
const isSmall = createMediaQuery("(max-width: 767px)", true);
console.log(isSmall());
Working Demo
createBreakpoints
Creates a multi-breakpoint monitor to make responsive components easily.
import { createBreakpoints } from "@solid-primitives/media";
const breakpoints = {
sm: "640px",
lg: "1024px",
xl: "1280px",
};
const Example: Component = () => {
const matches = createBreakpoints(breakpoints);
createEffect(() => {
console.log(matches.sm);
console.log(matches.lg);
console.log(matches.xl);
});
return (
<div
classList={{
"text-tiny flex flex-column": true, // tiny text with flex column layout
"text-small": matches.sm, // small text with flex column layout
"text-base flex-row": matches.lg, // base text with flex row layout
"text-huge": matches.xl, // huge text with flex row layout
}}
>
<Switch fallback={<div>Smallest</div>}>
<Match when={matches.xl}>Extra Large</Match>
<Match when={matches.lg}>Large</Match>
<Match when={matches.sm}>Small</Match>
{/*
Instead of fallback, you can also use `!matches.sm`
<Match when={!matches.sm}>Smallest</Match>
*/}
</Switch>
</div>
);
};
.toString
method
As a convenience feature, the return value of createBreakpoints
also contains a non-enumerable .key
property that will return the last matching breakpoint id to allow using it as an object key:
import { createBreakpoints } from "@solid-primitives/media";
const breakpoints = {
sm: "640px",
lg: "1024px",
xl: "1280px",
};
const matches = createBreakpoints(breakpoints);
const moduleSize = () =>
({
sm: 2,
lg: 4,
xl: 6,
})[matches.key];
This can be very helpful for things like the mapHeight
option in createMasonry
.
Warning for this feature to work, the breakpoints needs to be ordered from small to large. If you cannot ensure this, use the sortBreakpoints
helper.
sortBreakpoints
helper
If you cannot rely on the order of the breakpoints from smallest to largest, this small helper fixes it for you:
const breakpoints = {
xl: "1280px",
lg: "1024px",
sm: "640px",
};
const matches = createBreakpoints(sortBreakpoints(breakpoints));
const moduleSize = () =>
({
sm: 2,
lg: 4,
xl: 6,
})[matches.key];
Demo
Working Demo
createPrefersDark
Provides a signal indicating if the user has requested dark color theme. The setting is being watched with a Media Query.
How to use it
import { createPrefersDark } from "@solid-primitives/media";
const prefersDark = createPrefersDark();
createEffect(() => {
prefersDark();
});
Server fallback
createPrefersDark
accepts a serverFallback
argument — value that should be returned on the server — defaults to false
.
const prefersDark = createPrefersDark(true);
prefersDark();
usePrefersDark
This primitive provides a singleton root variant that will reuse the same signal and media query across the whole application.
import { usePrefersDark } from "@solid-primitives/media";
const prefersDark = usePrefersDark();
createEffect(() => {
prefersDark();
});
Note: usePrefersDark
will deopt to createPrefersDark
if used during hydration. (see issue #310)
Notes
iOS 13 Support & Deprecated addListener
Due to older versions of mobile Safari on iOS 13 not supporting addEventListener
on the MediaQueryList API, this primitive will need to be polyfilled. If your application needs to support much older versions of the browser you should use a polyfill utility or patch the missing function like so:
if (!'addEventListener' in MediaQueryList) {
MediaQueryList.prototype.addEventListener = function(type, callback) {
if (type === "change") this.addListener(callback)
}
MediaQueryList.prototype.removeEventListener = function(type, callback) {
if (type === "change") this.removeListener(callback)
}
}
Changelog
See CHANGELOG.md
Contributors
Thanks to Aditya Agarwal for contributing createBreakpoints.