Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save parkournick3/6d88dad60b83dbb30a99c08955b76a98 to your computer and use it in GitHub Desktop.
Save parkournick3/6d88dad60b83dbb30a99c08955b76a98 to your computer and use it in GitHub Desktop.
React (and NextJS, Typescript) Hook which returns the current TailwindCSS breakpoint size based on the current window width.
import { useEffect, useState } from 'react'
import throttle from 'lodash.throttle'
import resolveConfig from 'tailwindcss/resolveConfig'
import tailwindConfig from '../../tailwind.config'
type Breakpoint = 'sm' | 'md' | 'lg' | 'xl' | '2xl'
const findKeyByValue = (object: { [x: string]: unknown }, value: string) =>
Object.keys(object).find((key) => object[key] === value)
const getDeviceConfig = (width: number): Breakpoint => {
const fullConfig = resolveConfig(tailwindConfig)
const { screens } = fullConfig.theme
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
/* @ts-ignore */
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const bpSizes = Object.keys(screens).map((screenSize) => parseInt(screens[screenSize]))
const bpShapes = bpSizes.map((size, index) => ({
min: !index ? 0 : bpSizes[index - 1],
max: size,
key: findKeyByValue(screens, `${size}px`),
}))
let breakpoint: Breakpoint | null = 'md'
bpShapes.forEach((shape) => {
if (!shape.min && width < shape.max) {
breakpoint = shape.key as Breakpoint
} else if (shape.min && width >= shape.min && width < shape.max) {
breakpoint = shape.key as Breakpoint
} else if (!shape.max && width >= shape.max) {
breakpoint = shape.key as Breakpoint
}
})
return breakpoint
}
export const useTailwindBreakpoint = () => {
const [dimensions, setDimensions] = useState({
width: typeof window !== 'undefined' ? window.innerWidth : 0,
height: typeof window !== 'undefined' ? window.innerHeight : 0,
})
const handleResize = throttle(function () {
setDimensions({
width: typeof window !== 'undefined' ? window.innerWidth : 0,
height: typeof window !== 'undefined' ? window.innerHeight : 0,
})
}, 200)
useEffect(() => {
window.addEventListener('resize', handleResize, false)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return getDeviceConfig(dimensions.width)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment