Skip to content

Instantly share code, notes, and snippets.

@lbssousa
Last active February 18, 2020 15:11
Show Gist options
  • Save lbssousa/dc605f900e041dd141c932fd093b13ef to your computer and use it in GitHub Desktop.
Save lbssousa/dc605f900e041dd141c932fd093b13ef to your computer and use it in GitHub Desktop.
Vue composition to get reactive Tailwind CSS breakpoints
/*
* Usage in a component:
*
* import { createComponent } from '@vue/composition-api'
* import { useTailwindBreakpoints } from 'path/to/useTailwindBreakpoints'
* import tailwindConfig from 'tailwind.config.js'
*
* interface Props {
* (...)
* }
*
* export default createComponent<Props>({
* (...)
* setup () {
* (...)
* const { width, height, breakpoint, xs, sm, md, lg, xl, smOnly, mdOnly, lgOnly } = useTailwindBreakpoints(tailwindConfig)
* (...)
* return {
* width,
* height,
* breakpoint,
* xs,
* sm,
* md,
* lg,
* xl,
* smOnly,
* mdOnly,
* lgOnly
* }
* }
* })
*/
import { onBeforeUnmount, onMounted, reactive, toRefs } from '@vue/composition-api'
import resolveConfig from 'tailwindcss/resolveConfig'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function useTailwindBreakpoints (tailwindConfig?: unknown) {
const config = resolveConfig(tailwindConfig)
const screens = {
sm: parseInt(config.theme.screens.sm),
md: parseInt(config.theme.screens.md),
lg: parseInt(config.theme.screens.lg),
xl: parseInt(config.theme.screens.xl)
}
const sm = (width: number): boolean => width >= screens.sm
const md = (width: number): boolean => width >= screens.md
const lg = (width: number): boolean => width >= screens.lg
const xl = (width: number): boolean => width >= screens.xl
const xs = (width: number): boolean => !sm(width)
const smOnly = (width: number): boolean => sm(width) && !md(width)
const mdOnly = (width: number): boolean => md(width) && !lg(width)
const lgOnly = (width: number): boolean => lg(width) && !xl(width)
const breakpoint = (width: number): string =>
xl(width) ? 'xl' : lg(width) ? 'lg' : md(width) ? 'md' : sm(width) ? 'sm' : 'xs'
const breakpoints = reactive({
width: window.innerWidth,
height: window.innerHeight,
breakpoint: breakpoint(window.innerWidth),
xs: xs(window.innerWidth),
sm: sm(window.innerWidth),
md: md(window.innerWidth),
lg: lg(window.innerWidth),
xl: xl(window.innerWidth),
smOnly: smOnly(window.innerWidth),
mdOnly: mdOnly(window.innerWidth),
lgOnly: lgOnly(window.innerWidth)
})
const updateBreakpoints = (): void => {
breakpoints.width = window.innerWidth
breakpoints.height = window.innerHeight
breakpoints.breakpoint = breakpoint(window.innerWidth)
breakpoints.xs = xs(window.innerWidth)
breakpoints.sm = sm(window.innerWidth)
breakpoints.md = md(window.innerWidth)
breakpoints.lg = lg(window.innerWidth)
breakpoints.xl = xl(window.innerWidth)
breakpoints.smOnly = smOnly(window.innerWidth)
breakpoints.mdOnly = mdOnly(window.innerWidth)
breakpoints.lgOnly = lgOnly(window.innerWidth)
}
onMounted(() => {
window.addEventListener(
'resize',
updateBreakpoints,
{ passive: true }
)
})
onBeforeUnmount(() => {
window.removeEventListener(
'resize',
updateBreakpoints
)
})
return toRefs(breakpoints)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment