/
ComponentsGrid.tsx
99 lines (84 loc) · 2.42 KB
/
ComponentsGrid.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
95
96
97
98
99
import React, { useMemo } from 'react'
import styled from 'styled-components'
import { ComponentsGridItem } from './ComponentsGridItem'
import * as nav from '../../../data/nav'
import media from '../../../theming/mediaQueries'
import { ChartNavData } from '../../../types'
type FilterFunction = (item: ChartNavData) => boolean
const getFilterFunction = (term?: string | null, filter?: string | null): FilterFunction => {
let predicates: FilterFunction[] = []
if (term && term.length > 0) {
predicates.push(({ name }) => name.toLowerCase().includes(term.toLowerCase()))
}
if (filter) {
predicates.push(({ flavors }) => flavors[filter.toLowerCase()] === true)
}
return item => predicates.every(predicate => predicate(item))
}
interface ComponentsGridProps {
filter?: string | null
term?: string | null
}
export const ComponentsGrid = ({ filter, term }: ComponentsGridProps) => {
let items = nav.components
if (term || filter) {
const filterFunction = getFilterFunction(term, filter)
items = items.filter(filterFunction)
}
if (items.length === 0) {
return (
<Empty>
<EmptyIcon>{`¯\\_(ツ)_/¯`}</EmptyIcon>
<div>no result, sorry…</div>
</Empty>
)
}
return (
<Grid>
{items.map(item => (
<ComponentsGridItem key={item.id} {...item} />
))}
</Grid>
)
}
const Grid = styled.div`
display: grid;
grid-row-gap: 15px;
margin-bottom: 30px;
${media.desktopLarge`
& {
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
grid-column-gap: 30px;
}
`}
${media.desktop`
& {
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
grid-column-gap: 20px;
}
`}
${media.tablet`
& {
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
grid-column-gap: 20px;
}
`}
${media.mobile`
& {
grid-template-columns: 1fr;
grid-row-gap: 0;
box-shadow: ${({ theme }) => theme.cardShadow};
}
`}
`
const Empty = styled.div`
margin-top: 120px;
text-align: center;
`
const EmptyIcon = styled.span`
font-size: 64px;
display: block;
margin-bottom: 50px;
white-space: pre;
color: ${({ theme }) => theme.colors.accent};
`