UNPKG

@w11r/use-breakpoint

Version:

React useBreakpoint hook to have different values for a variable based on a breakpoints.

281 lines (219 loc) 6.69 kB
# Intro React `useBreakpoint` hook to have different values for a variable based on a breakpoints. # Demo https://wintercounter.github.io/use-breakpoint # Install ```bash npm i @w11r/use-breakpoint ``` # Setup ## Add provider Add `BreakpointProvider` in your React tree. ```jsx import { BreakpointProvider } from '@w11r/use-breakpoint' ... <BreakpointProvider> ... </BreakpointProvider> ... ``` ## Default breakpoints The following default breakpoints are being used, including several shorthands. ```js const breakpoints = { micro: [0, 375], mi: [0, 375], mobile: [376, 639], m: [376, 639], tablet: [640, 1023], t: [640, 1023], small: [1024, 1439], s: [1024, 1439], medium: [1440, 1919], med: [1440, 1919], large: [1920, 10000], l: [1920, 10000], // Multi range device: [0, 1023], d: [0, 1023], smallDevice: [0, 639], sd: [0, 639] } ``` ## Override default settings ```js import { setup, breakpoints } from '@w11r/use-breakpoint' setup({ breakpoints: { // Extend default values ...breakpoints, alienDevice: [342, 43534] // from, to } }) ``` # Usage ## With passing values ```js useBreakpoint(defaultValue, breakpointValues) // breakpointValues: array of breakpoint based values [ ['mobile', 300], ['tablet', 400] ] // In case you have a single breakpoint value, `['mobile', 300]` is enough instead of `[['mobile', 300]]` ``` ## Without passing values In case you don't specify any value to the hook, it'll return a generated object including boolean values for each breakpoint keys that's being defined in options. It'll return the following object with the basic setup. ``` { isLandscape: false, isPortrait: true, isHDPI: false, isMicro: false, isMobile: true, isTablet: false, isSmall: false, isMedium: false, isLarge: false, 'is-Micro': false, 'is|Micro': false, 'isMicro+': true, 'is-Micro+': true, 'is|Micro+': true, 'isMicro-': false, 'is-Micro-': false, 'is|Micro-': false, 'is-Mobile': true, 'is|Mobile': true, 'isMobile+': true, 'is-Mobile+': true, 'is|Mobile+': true, 'isMobile-': true, 'is-Mobile-': true, 'is|Mobile-': true, 'is-Tablet': false, 'is|Tablet': false, 'isTablet+': false, 'is-Tablet+': false, 'is|Tablet+': false, 'isTablet-': true, 'is-Tablet-': true, 'is|Tablet-': true, 'is-Small': false, 'is|Small': false, 'isSmall+': false, 'is-Small+': false, 'is|Small+': false, 'isSmall-': true, 'is-Small-': true, 'is|Small-': true, 'is-Medium': false, 'is|Medium': false, 'isMedium+': false, 'is-Medium+': false, 'is|Medium+': false, 'isMedium-': true, 'is-Medium-': true, 'is|Medium-': true, 'is-Large': false, 'is|Large': false, 'isLarge+': false, 'is-Large+': false, 'is|Large+': false, 'isLarge-': true, 'is-Large-': true, 'is|Large-': true } ``` Usage ```js const { isMobile } = useBreakpoint() // The above is basically a replacement for const isMobile = useBreakpoint(false, ['mobile', true]) ``` > You can also access the values with suffix and prefix, but you need > to rename the variables because it contains invalid character: > `const { 'isMobile+': isMobile } = useBreakpoint()` Component example ```jsx import useBreakpoint from '@w11r/use-breakpoint' const MyCmp = () => { const columns = useBreakpoint([1,2], ['mobile', [2,1]]) return <Grid cols={columns} /> } // Or using inline const MyCmp = () => { return <Grid cols={useBreakpoint([1,2], ['mobile', [2,1]])} /> } ``` > _Rules-of-Hooks_ are still true in this case as well. Make sure > your component will __ALWAYS__ run it without any condition! ## Modifiers All breakpoint names coming with modifiers included. ### Orientation prefix - `` (none): all - `-`: Landscape - `|`: Portrait ### Range suffix You can also control your value to behave as `and up` and `and down`. - `` (none): all - `+`: `and up` - `-`: `and down` ### Examples - `['|mobile', 300]`: on mobile, on portrait - `['|mobile+', 300]`: on mobile and up, on portrait - `['mobile+', 300]`: on mobile and up, both portrait and landscape - `['mobile', 300]`: on mobile, both portrait and landscape - `['tablet-', 300]`: on tablet and below, both portrait and landscape - `['mobile-', 300]`: on mobile and down, both portrait and landscape ## Generate Media Query strings using the same logic It is useful when you just need simple CSS. For example with `styled-components`: ```js import styled from 'styled-components' import { mediaQuery } from '@w11r/use-breakpoint' const mediaQueryString = mediaQuery( ['mobile-', `width: 100%;`] ) const Box = styled.div` ${mediaQuery( ['mobile-', `width: 100%;`] )} ` // You can still use multiple queries at once just like with the hook: mediaQuery([['mobile-', `width: 100%`], ['medium+', `width: 50%`]]) ``` This utility comes with additional support for `shorthands` which is configurable through `options`. ```js setup({ shorthands: { foo: '@media (wow: bar) and (hmm: khm)' } }) mediaQuery(['foo', value]) ``` Additionally, it supports `dark` and `light` mode prefixes: - `(`: Light mode - `)`: Dark mode ```js mediaQuery([')mobile', 'content']) // @media screen and (min-width: 376px) and (max-width: 639px) and (prefers-color-scheme: dark) { content } mediaQuery([')', 'content']) // @media screen and (prefers-color-scheme: dark) { content } ``` # FAQ ## Is there any best practice suggestion? Yes! Use as fewer hooks as possible. It's always faster to have a single `isMobile` variable and have simple conditions based on it. It's even better if you can solve your size related cases using pure CSS Media Queries. ## Why not using an `Object`? Why the `Array` structure? Object's cannot guarantee the order of the defined keys. It is crucial to check for values in the correct order because `useBreakpoint` uses eager evaluation and `mediaQuery` must maintain the defined order of the generated Media Queries. ## Which rule is being prioritized? The hook uses _eager_ evaluation, so the first truthy breakpoint value gets returned.