/
media-query.tsx
94 lines (78 loc) · 2.41 KB
/
media-query.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { useTheme } from "@chakra-ui/system"
import { Dict, memoizedGet as get, __DEV__ } from "@chakra-ui/utils"
import * as React from "react"
import { useMediaQuery } from "./use-media-query"
interface VisibilityProps {
breakpoint: string
hide?: boolean
children: React.ReactNode
}
/**
* Visibility
*
* React component to control the visibility of its
* children based on the current breakpoint
*/
const Visibility: React.FC<VisibilityProps> = (props) => {
const { breakpoint, hide, children } = props
const [show] = useMediaQuery(breakpoint)
const isVisible = hide ? !show : show
const rendered = isVisible ? children : null
return rendered as React.ReactElement
}
export type HideProps = ShowProps
export const Hide: React.FC<HideProps> = (props) => {
const { children } = props
const query = useQuery(props)
return (
<Visibility breakpoint={query} hide>
{children}
</Visibility>
)
}
if (__DEV__) {
Hide.displayName = "Hide"
}
export interface ShowProps {
/**
* A custom css media query that determines when the `children` are rendered. Will render `children` if that query resolves to `true`.
*/
breakpoint?: string
/**
* A value from the `breakpoints` section in the theme. Will render `children` from that breakpoint and below. Similar to `max-width`. Default breakpoint values: `sm`, `md`, `lg`, `xl`, `2xl`.
*/
below?: string
/**
* A value from the `breakpoints` section in the theme. Will render `children` from that breakpoint and above. Similar to `min-width`. Default breakpoint values: `sm`, `md`, `lg`, `xl`, `2xl`.
*/
above?: string
children?: React.ReactNode
}
export const Show: React.FC<ShowProps> = (props) => {
const { children } = props
const query = useQuery(props)
return <Visibility breakpoint={query}>{children}</Visibility>
}
if (__DEV__) {
Show.displayName = "Show"
}
const getBreakpoint = (theme: Dict, value: any) =>
get(theme, `breakpoints.${value}`, value)
export interface UseQueryProps {
breakpoint?: string
below?: string
above?: string
}
export function useQuery(props: UseQueryProps) {
const { breakpoint = "", below, above } = props
const theme = useTheme()
const bpBelow = getBreakpoint(theme, below)
const bpAbove = getBreakpoint(theme, above)
let query = breakpoint
if (bpBelow) {
query = `(max-width: ${bpBelow})`
} else if (bpAbove) {
query = `(min-width: ${bpAbove})`
}
return query
}