Skip to content

Commit 5d6cfe4

Browse files
authored
Merge pull request #8843 from victorpatru/statsboxgrid_migration
Migrate `StatsBoxGrid.tsx` to Chakra
2 parents 992d2f4 + e5feed8 commit 5d6cfe4

File tree

1 file changed

+121
-136
lines changed

1 file changed

+121
-136
lines changed

src/components/StatsBoxGrid.tsx

Lines changed: 121 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import React, { useState, useEffect } from "react"
2-
import styled from "@emotion/styled"
32
import { useIntl } from "react-intl"
43
import axios from "axios"
54
import { kebabCase } from "lodash"
65
import { AreaChart, ResponsiveContainer, Area, XAxis } from "recharts"
76

7+
import { VStack, Grid, Box, Icon, Button, Text, Flex } from "@chakra-ui/react"
8+
import { MdInfoOutline } from "react-icons/md"
9+
810
import Translation from "./Translation"
911
import Tooltip from "./Tooltip"
1012
import Link from "./Link"
11-
import Icon from "./Icon"
1213
import StatErrorMessage from "./StatErrorMessage"
1314
import StatLoadingMessage from "./StatLoadingMessage"
1415

@@ -23,122 +24,6 @@ import { GATSBY_FUNCTIONS_PATH } from "../constants"
2324
import { Lang } from "../utils/languages"
2425
import { Direction } from "../types"
2526

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-
14227
const ranges = ["30d", "90d"] as const
14328

14429
interface State {
@@ -170,14 +55,22 @@ const GridItem: React.FC<IGridItemProps> = ({ metric, dir }) => {
17055
) : isLoading ? (
17156
<StatLoadingMessage />
17257
) : (
173-
<StatRow>
174-
<span>
58+
<VStack>
59+
<Box>
17560
{state.value}{" "}
17661
<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>
17871
</Tooltip>
179-
</span>
180-
</StatRow>
72+
</Box>
73+
</VStack>
18174
)
18275

18376
// Returns either 90 or 30-day data range depending on `range` selection
@@ -233,19 +126,82 @@ const GridItem: React.FC<IGridItemProps> = ({ metric, dir }) => {
233126
)
234127

235128
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+
>
237147
<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>
239157
<p>{description}</p>
240158
</div>
241159
{!state.hasError && !isLoading && (
242160
<>
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+
)}
245189
</>
246190
)}
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>
249205
)
250206
}
251207

@@ -264,16 +220,29 @@ interface IRangeSelectorProps {
264220
const RangeSelector: React.FC<IRangeSelectorProps> = ({ state, setState }) => (
265221
<div>
266222
{ranges.map((range, idx) => (
267-
<ButtonToggle
268-
active={state === range}
269-
onClick={() => {
270-
setState(ranges[idx])
271-
}}
223+
<Button
224+
onClick={() => setState(ranges[idx])}
272225
key={idx}
273226
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" : ""}
274243
>
275244
{range}
276-
</ButtonToggle>
245+
</Button>
277246
))}
278247
</div>
279248
)
@@ -563,7 +532,23 @@ const StatsBoxGrid: React.FC<IProps> = () => {
563532
]
564533
const dir = isLangRightToLeft(intl.locale as Lang) ? "rtl" : "ltr"
565534
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+
>
567552
{metrics.map((metric, idx) => (
568553
<GridItem key={idx} metric={metric} dir={dir} />
569554
))}

0 commit comments

Comments
 (0)