1
1
import React , { useState , useEffect } from "react"
2
- import styled from "@emotion/styled"
3
2
import { useIntl } from "react-intl"
4
3
import axios from "axios"
5
4
import { kebabCase } from "lodash"
6
5
import { AreaChart , ResponsiveContainer , Area , XAxis } from "recharts"
7
6
7
+ import { VStack , Grid , Box , Icon , Button , Text , Flex } from "@chakra-ui/react"
8
+ import { MdInfoOutline } from "react-icons/md"
9
+
8
10
import Translation from "./Translation"
9
11
import Tooltip from "./Tooltip"
10
12
import Link from "./Link"
11
- import Icon from "./Icon"
12
13
import StatErrorMessage from "./StatErrorMessage"
13
14
import StatLoadingMessage from "./StatLoadingMessage"
14
15
@@ -23,122 +24,6 @@ import { GATSBY_FUNCTIONS_PATH } from "../constants"
23
24
import { Lang } from "../utils/languages"
24
25
import { Direction } from "../types"
25
26
26
- const Value = styled . span `
27
- position: absolute;
28
- bottom: 8%;
29
- font-size: min(4.4vw, 4rem);
30
- font-weight: 600;
31
- margin-top: 0rem;
32
- margin-bottom: 1rem;
33
- color: ${ ( { theme } ) => theme . colors . text } ;
34
- flex-wrap: wrap;
35
- text-overflow: ellipsis;
36
- @media (max-width: ${ ( { theme } ) => theme . breakpoints . l } ) {
37
- font-size: max(8.8vw, 48px);
38
- }
39
- `
40
-
41
- const Title = styled . p `
42
- font-size: 1.25rem;
43
- margin-bottom: 0.5rem;
44
- color: ${ ( { theme } ) => theme . colors . text } ;
45
- text-transform: uppercase;
46
- font-family: ${ ( props ) => props . theme . fonts . monospace } ;
47
- `
48
-
49
- const Grid = styled . div `
50
- display: grid;
51
- grid-template-columns: repeat(2, 1fr);
52
- margin: 2rem 2rem 0;
53
- border-radius: 2px;
54
- @media (max-width: ${ ( { theme } ) => theme . breakpoints . l } ) {
55
- display: flex;
56
- flex-direction: column;
57
- width: 100%;
58
- margin: 2rem 0 0;
59
- }
60
- @media (max-width: ${ ( { theme } ) => theme . breakpoints . s } ) {
61
- margin: 0;
62
- }
63
- `
64
-
65
- const Box = styled . div `
66
- position: relative;
67
- color: ${ ( { theme } ) => theme . colors . text } ;
68
- height: 20rem;
69
- background: ${ ( { theme, color = "" } ) => theme . colors [ color ] } ;
70
- display: flex;
71
- flex-direction: column;
72
- justify-content: space-between;
73
- align-items: flex-start;
74
- border: 1px solid ${ ( { theme } ) => theme . colors . color } ;
75
- padding: 1.5rem;
76
- @media (max-width: ${ ( { theme } ) => theme . breakpoints . l } ) {
77
- border-left: 0px solid #000000;
78
- border-right: 0px solid #000000;
79
- margin-top: -1px;
80
- padding: 1rem;
81
- padding-top: 2rem;
82
- }
83
- `
84
-
85
- const StatRow = styled . div `
86
- display: flex;
87
- flex-direction: column;
88
- `
89
-
90
- const StyledIcon = styled ( Icon ) `
91
- fill: ${ ( { theme } ) => theme . colors . text } ;
92
- margin-right: 0.5rem;
93
- @media (max-width: ${ ( { theme } ) => theme . breakpoints . l } ) {
94
- }
95
- &:hover,
96
- &:active,
97
- &:focus {
98
- fill: ${ ( { theme } ) => theme . colors . primary } ;
99
- }
100
- `
101
-
102
- const Lines = styled . div `
103
- position: absolute;
104
- left: 0;
105
- bottom: 0;
106
- width: 100%;
107
- height: 65%;
108
- `
109
-
110
- const ButtonContainer = styled . div < { dir ?: Direction } > `
111
- position: absolute;
112
- ${ ( { dir } ) => ( dir === "rtl" ? "left" : "right" ) } : 20px;
113
- bottom: 20px;
114
- font-family: ${ ( props ) => props . theme . fonts . monospace } ;
115
- `
116
-
117
- const Button = styled . button < { color : string } > `
118
- background: ${ ( props ) => props . theme . colors . background } ;
119
- font-family: ${ ( props ) => props . theme . fonts . monospace } ;
120
- font-size: 1.25rem;
121
- color: ${ ( { theme } ) => theme . colors . text } ;
122
- padding: 2px 15px;
123
- border-radius: 1px;
124
- border: 1px solid ${ ( { theme, color } ) => theme . colors [ color ] } ;
125
- cursor: pointer;
126
-
127
- &:disabled {
128
- cursor: default;
129
- opacity: 0.7;
130
- }
131
- `
132
-
133
- const ButtonToggle = styled ( Button ) < { active : boolean } > `
134
- ${ ( { active, theme } ) =>
135
- active &&
136
- `
137
- background-color: ${ theme . colors . homeBoxPurple } ;
138
- opacity: 1;
139
- ` }
140
- `
141
-
142
27
const ranges = [ "30d" , "90d" ] as const
143
28
144
29
interface State {
@@ -170,14 +55,22 @@ const GridItem: React.FC<IGridItemProps> = ({ metric, dir }) => {
170
55
) : isLoading ? (
171
56
< StatLoadingMessage />
172
57
) : (
173
- < StatRow >
174
- < span >
58
+ < VStack >
59
+ < Box >
175
60
{ state . value } { " " }
176
61
< Tooltip content = { tooltipContent ( metric ) } >
177
- < StyledIcon name = "info" />
62
+ < Icon
63
+ as = { MdInfoOutline }
64
+ boxSize = { 6 }
65
+ fill = "text"
66
+ mr = { 2 }
67
+ _hover = { { fill : "primary" } }
68
+ _active = { { fill : "primary" } }
69
+ _focus = { { fill : "primary" } }
70
+ > </ Icon >
178
71
</ Tooltip >
179
- </ span >
180
- </ StatRow >
72
+ </ Box >
73
+ </ VStack >
181
74
)
182
75
183
76
// Returns either 90 or 30-day data range depending on `range` selection
@@ -233,19 +126,82 @@ const GridItem: React.FC<IGridItemProps> = ({ metric, dir }) => {
233
126
)
234
127
235
128
return (
236
- < Box >
129
+ < Flex
130
+ position = "relative"
131
+ color = "text"
132
+ height = { 80 }
133
+ flexDirection = "column"
134
+ justifyContent = "space-between"
135
+ alignItems = "flex-start"
136
+ borderX = { {
137
+ base : "0px solid #000000" ,
138
+ lg : "1px solid" ,
139
+ } }
140
+ borderY = "1px solid"
141
+ marginTop = { {
142
+ base : "-1px" ,
143
+ lg : "0" ,
144
+ } }
145
+ padding = { { base : "2rem 1rem 1rem" , lg : "1.5rem" } }
146
+ >
237
147
< div >
238
- < Title > { title } </ Title >
148
+ < Text
149
+ fontSize = "xl"
150
+ mb = { 2 }
151
+ color = "text"
152
+ textTransform = "uppercase"
153
+ fontFamily = "monospace"
154
+ >
155
+ { title }
156
+ </ Text >
239
157
< p > { description } </ p >
240
158
</ div >
241
159
{ ! state . hasError && ! isLoading && (
242
160
< >
243
- < Lines > { chart } </ Lines >
244
- < ButtonContainer dir = { dir } > { buttonContainer } </ ButtonContainer >
161
+ < Box
162
+ position = "absolute"
163
+ left = { 0 }
164
+ bottom = { 0 }
165
+ width = "100%"
166
+ height = "65%"
167
+ >
168
+ { chart }
169
+ </ Box >
170
+ { dir === "rtl" ? (
171
+ < Box
172
+ position = "absolute"
173
+ bottom = "20px"
174
+ fontFamily = "monospace"
175
+ left = "20px"
176
+ >
177
+ { buttonContainer }
178
+ </ Box >
179
+ ) : (
180
+ < Box
181
+ position = "absolute"
182
+ bottom = "20px"
183
+ fontFamily = "monospace"
184
+ right = "20px"
185
+ >
186
+ { buttonContainer }
187
+ </ Box >
188
+ ) }
245
189
</ >
246
190
) }
247
- < Value > { value } </ Value >
248
- </ Box >
191
+ < Text
192
+ position = "absolute"
193
+ bottom = "8%"
194
+ fontSize = { { base : "max(8.8vw, 48px)" , lg : "min(4.4vw, 4rem)" } }
195
+ fontWeight = { 600 }
196
+ marginTop = { 0 }
197
+ marginBottom = { 4 }
198
+ color = "text"
199
+ flexWrap = "wrap"
200
+ textOverflow = "ellipsis"
201
+ >
202
+ { value }
203
+ </ Text >
204
+ </ Flex >
249
205
)
250
206
}
251
207
@@ -264,16 +220,29 @@ interface IRangeSelectorProps {
264
220
const RangeSelector : React . FC < IRangeSelectorProps > = ( { state, setState } ) => (
265
221
< div >
266
222
{ ranges . map ( ( range , idx ) => (
267
- < ButtonToggle
268
- active = { state === range }
269
- onClick = { ( ) => {
270
- setState ( ranges [ idx ] )
271
- } }
223
+ < Button
224
+ onClick = { ( ) => setState ( ranges [ idx ] ) }
272
225
key = { idx }
273
226
color = { "" }
227
+ background = "background"
228
+ fontFamily = "monospace"
229
+ fontSize = "xl"
230
+ padding = "2px 15px"
231
+ borderRadius = "1px"
232
+ border = "1px solid"
233
+ cursor = "pointer"
234
+ _focus = { { outline : "none" } }
235
+ _hover = { { color : "" } }
236
+ _active = { { color : "" } }
237
+ _disabled = { {
238
+ cursor : "default" ,
239
+ opacity : "0.7" ,
240
+ } }
241
+ size = "sm"
242
+ backgroundColor = { state === ranges [ idx ] ? "homeBoxPurple" : "" }
274
243
>
275
244
{ range }
276
- </ ButtonToggle >
245
+ </ Button >
277
246
) ) }
278
247
</ div >
279
248
)
@@ -563,7 +532,23 @@ const StatsBoxGrid: React.FC<IProps> = () => {
563
532
]
564
533
const dir = isLangRightToLeft ( intl . locale as Lang ) ? "rtl" : "ltr"
565
534
return (
566
- < Grid >
535
+ < Grid
536
+ display = { {
537
+ base : "flex" ,
538
+ lg : "grid" ,
539
+ } }
540
+ gridTemplateColumns = "repeat(2, 1fr)"
541
+ margin = { {
542
+ base : "0" ,
543
+ sm : "2rem 0 0" ,
544
+ lg : "2rem 2rem 0" ,
545
+ } }
546
+ borderRadius = "sm"
547
+ flexDirection = { {
548
+ base : "column" ,
549
+ lg : "column" ,
550
+ } }
551
+ >
567
552
{ metrics . map ( ( metric , idx ) => (
568
553
< GridItem key = { idx } metric = { metric } dir = { dir } />
569
554
) ) }
0 commit comments