Last active
October 9, 2019 14:21
-
-
Save nathanchicken/9307fd64c4e8bc44f34ac1830c692b54 to your computer and use it in GitHub Desktop.
Update to media-queries, makes it easier to watch for changes and you can use the media libraries for reactive data, or just use events.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script> | |
| import { media } from "@parts/media"; | |
| export default { | |
| data() { | |
| return { | |
| mobile: media.matches('mobile'), | |
| md: media.matches('md'), | |
| sm: media.matches('sm'), | |
| lg: media.matches('lg'), | |
| xl: media.matches('xl'), | |
| xl2: media.matches('xl2'), | |
| reducedMotion: media.matches('reducedMotion'), | |
| } | |
| }, | |
| mounted() { | |
| [ | |
| 'mobile', | |
| 'md', | |
| 'sm', | |
| 'lg', | |
| 'xl', | |
| 'xl2', | |
| 'reducedMotion', | |
| ].forEach( k => { | |
| this[k] = media.matches(k); | |
| this.$emit( k, media.matches(k) ); | |
| }); | |
| [ | |
| 'mobile', | |
| 'md', | |
| 'sm', | |
| 'lg', | |
| 'xl', | |
| 'xl2', | |
| 'reducedMotion', | |
| ].forEach( k => media.on( k, (matches) => { | |
| this[k] = matches; | |
| this.$emit( k, matches ); | |
| }) ); | |
| }, | |
| render() { | |
| return this.$scopedSlots.default ? this.$scopedSlots.default({ | |
| mobile: this.mobile, | |
| md: this.md, | |
| sm: this.sm, | |
| lg: this.lg, | |
| xl: this.xl, | |
| xl2: this.xl2, | |
| reducedMotion: this.reducedMotion, | |
| }) : false; | |
| } | |
| } | |
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { media } from "@parts/media"; | |
| media.on('md', function( matches ) { | |
| if ( matches ) { | |
| console.log("md now matches"); | |
| } else { | |
| console.log("md now DOES NOT match"); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <div class="p-8"> | |
| <div class="p-8 border my-8" v-if="md">md</div> | |
| <div class="p-8 border my-8" v-if="sm">sm</div> | |
| <div class="p-8 border my-8" v-if="lg">lg</div> | |
| <div class="p-8 border my-8" v-if="xl">xl</div> | |
| <div class="p-8 border my-8" v-if="xl2">xl2</div> | |
| </div> | |
| </template> | |
| <script> | |
| import { media } from "@parts/media"; | |
| export default { | |
| data() { | |
| return { | |
| md: media.matches('md'), | |
| sm: media.matches('sm'), | |
| lg: media.matches('lg'), | |
| xl: media.matches('xl'), | |
| xl2: media.matches('xl2'), | |
| } | |
| }, | |
| mounted() { | |
| [ | |
| 'md', | |
| 'sm', | |
| 'lg', | |
| 'xl', | |
| 'xl2', | |
| ].forEach( k => this[k] = media.matches(k) ); | |
| [ | |
| 'md', | |
| 'sm', | |
| 'lg', | |
| 'xl', | |
| 'xl2', | |
| ].forEach( k => media.on( k, (matches) => this[k] = matches ) ); | |
| } | |
| } | |
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // NEW NODE / BROWSERIFY VERSION | |
| const mq = ('matchMedia' in window); | |
| const generateRule = function( query ) { | |
| if (typeof query === "string") { | |
| return query; | |
| } | |
| if (query.hasOwnProperty('max') && query.hasOwnProperty('min')) { | |
| return `(min-width: ${query.min}) and (max-width: ${query.max})`; | |
| } | |
| if (query.hasOwnProperty('min')) { | |
| return `(min-width: ${query.min})`; | |
| } | |
| if (query.hasOwnProperty('max')) { | |
| return `(max-width: ${query.max})`; | |
| } | |
| return false; | |
| }; | |
| export class MediaQueries { | |
| constructor(config, debug) { | |
| if (!mq) { | |
| console.error("matchMedia not supported on this browser"); | |
| return false; | |
| } | |
| const defaults = { | |
| desktop: { | |
| min: "1367px" | |
| }, | |
| laptop: { | |
| max: "1366px" | |
| }, | |
| tablet: { | |
| max: "1024px" | |
| }, | |
| mobile: { | |
| max: "480px" | |
| }, | |
| }; | |
| this.breakpoints = config || defaults; | |
| this.queries = {}; | |
| Object.entries( this.breakpoints ).forEach( ([ key, query ]) => { | |
| console.log( key, query ); | |
| console.log( generateRule( key ) ); | |
| this.queries[ key ] = window.matchMedia( generateRule( query ) ); | |
| }); | |
| return this; | |
| } | |
| _getMatchMedia( key ) { | |
| return this.queries[ key ] || false; | |
| } | |
| matches(key) { | |
| return this._getMatchMedia( key ).matches; | |
| } | |
| on(key, fn) { | |
| const mediaQuery = this._getMatchMedia( key ); | |
| if (!mediaQuery) { | |
| console.error(`${key} not found`); | |
| return; | |
| } | |
| console.log( mediaQuery, key ); | |
| mediaQuery.addEventListener('change', function() { | |
| fn(mediaQuery.matches); | |
| }); | |
| } | |
| } | |
| export default { MediaQueries }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { MediaQueries } from "@libs/media-queries"; | |
| const screens = { | |
| mobile: { max: '639px' }, | |
| sm: { min: '640px' }, | |
| md: { min: '768px' }, | |
| lg: { min: '1025px' }, | |
| xl: { min: '1441px' }, | |
| xl2: { min: '1681px' }, | |
| }; | |
| const m = new MediaQueries( screens ); | |
| export const media = m; | |
| export default { media: m }; |
Author
Author
There's a big problem here where there's a few assumptions and the parts are split, eg the media queries config, the media library, and the vue component. So, possibly he base-media-query component really needs to include the library functionality on its own, and perhaps get its config from somewhere, but this works within a smaller website project at least where we might use the media thing.
Vue 3 and the composition API will make all this a lot simpler though!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
base-media-query.vueis an example of a reusable component that will provide either a scoped slot to access the media queries, or it'll emit events with the same name, eg:<base-media-query @mobile="isMobile = $event" />or