Skip to content

Commit 4d6dcf5

Browse files
committed
migrate footer, skiplink & link component
1 parent c175e35 commit 4d6dcf5

File tree

11 files changed

+362
-134
lines changed

11 files changed

+362
-134
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@radix-ui/react-accordion": "^1.2.0",
3737
"@radix-ui/react-navigation-menu": "^1.2.0",
3838
"@radix-ui/react-slot": "^1.1.0",
39+
"@radix-ui/react-visually-hidden": "^1.1.0",
3940
"@socialgouv/matomo-next": "^1.8.0",
4041
"chart.js": "^4.4.2",
4142
"chartjs-plugin-datalabels": "^2.2.0",

src/components/Footer.tsx

Lines changed: 39 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
import { useTranslation } from "next-i18next"
22
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa"
33
import { IoChevronUpSharp } from "react-icons/io5"
4-
import {
5-
Box,
6-
Flex,
7-
Heading,
8-
Icon,
9-
List,
10-
ListItem,
11-
SimpleGrid,
12-
Text,
13-
} from "@chakra-ui/react"
144

155
import type { FooterLink, FooterLinkSection } from "@/lib/types"
166

17-
import { BaseLink } from "@/components/Link"
187
import Translation from "@/components/Translation"
198

209
import { scrollIntoView } from "@/lib/utils/scrollIntoView"
2110

22-
import { Button } from "./Buttons"
11+
import { BaseLink } from "../../tailwind/Link"
12+
13+
import { Button, ButtonIcon } from "./ui/button"
14+
import { List, ListItem } from "./ui/list"
2315

2416
const socialLinks = [
2517
{
@@ -306,132 +298,69 @@ const Footer = ({ lastDeployLocaleTimestamp }: FooterProps) => {
306298
},
307299
]
308300

309-
const hoverStyles = {
310-
textDecor: "none",
311-
color: "primary.base",
312-
_after: {
313-
color: "primary.base",
314-
},
315-
"& svg": {
316-
fill: "primary.base",
317-
},
318-
}
319-
320-
const linkProps = {
321-
isPartiallyActive: false,
322-
textDecor: "none",
323-
color: "body.medium",
324-
fontWeight: "normal",
325-
_hover: hoverStyles,
326-
sx: {
327-
"& svg": {
328-
fill: "body.medium",
329-
},
330-
},
331-
}
332-
333301
return (
334-
<Box as="footer" py="4" px="8">
335-
<Flex
336-
justify={{ base: "center", md: "space-between" }}
337-
alignItems="center"
338-
flexWrap="wrap"
339-
gap={8}
340-
pt={4}
341-
pb={4}
342-
borderTop={"1px solid"}
343-
borderColor={"body.light"}
344-
>
345-
<Text fontSize={"sm"} fontStyle={"italic"} color={"body.medium"}>
302+
<footer className="px-8 py-4">
303+
<div className="flex flex-wrap items-center justify-center gap-8 border-t border-body-light pb-4 pt-4 md:justify-between">
304+
<p className="text-sm italic text-body-medium">
346305
<Translation id="website-last-updated" />: {lastDeployLocaleTimestamp}
347-
</Text>
306+
</p>
348307

349-
<Button
350-
leftIcon={<IoChevronUpSharp />}
351-
variant="outline"
352-
isSecondary
353-
onClick={() => scrollIntoView("__next")}
354-
>
355-
{t("go-to-top")}
308+
<Button variant="secondary" onClick={() => scrollIntoView("__next")}>
309+
<ButtonIcon icon={<IoChevronUpSharp />} /> Go to top
356310
</Button>
357-
</Flex>
311+
</div>
358312

359-
<SimpleGrid
360-
gap={4}
361-
justifyContent="space-between"
362-
templateColumns={{
363-
base: "auto",
364-
sm: "repeat(2, auto)",
365-
md: "repeat(3, auto)",
366-
xl: "repeat(6, auto)",
367-
}}
368-
>
313+
<div className="grid auto-cols-auto justify-between gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-5">
369314
{linkSections.map((section: FooterLinkSection, idx) => (
370-
<Box key={idx}>
371-
<Heading as="h3" fontSize="sm" lineHeight="base" my="1.14em">
315+
<div key={idx}>
316+
<h3 className="my-5 text-sm font-bold">
372317
<Translation id={section.title} />
373-
</Heading>
374-
<List fontSize="sm" lineHeight="base" fontWeight="normal" m="0">
318+
</h3>
319+
<List className="text-sm">
375320
{section.links.map((link, linkIdx) => (
376-
<ListItem key={linkIdx} mb={4}>
377-
<BaseLink href={link.to} {...linkProps}>
321+
<ListItem key={linkIdx} className="mb-4">
322+
<BaseLink
323+
href={link.to}
324+
className="text-body-medium no-underline hover:text-primary hover:after:text-primary"
325+
isPartiallyActive={false}
326+
>
378327
{link.text}
379328
</BaseLink>
380329
</ListItem>
381330
))}
382331
</List>
383-
</Box>
332+
</div>
384333
))}
385-
</SimpleGrid>
386-
<Flex
387-
p={6}
388-
flexDir="column"
389-
alignItems="center"
390-
justifyContent="center"
391-
fontSize="sm"
392-
bg="background.highlight"
393-
>
394-
<Box display="flex" gap={4}>
395-
{socialLinks.map(({ to, ariaLabel, icon }) => (
334+
</div>
335+
<div className="flex flex-col items-center justify-center bg-background-highlight p-6 text-sm">
336+
<div className="flex gap-4">
337+
{socialLinks.map(({ to, ariaLabel, icon: Icon }) => (
396338
<BaseLink
397339
key={to}
398340
href={to}
399341
hideArrow
400-
color="body.base"
401342
aria-label={ariaLabel}
402-
_focus={{ color: "primary.base" }}
343+
className="text-body hover:text-primary"
403344
>
404-
<Icon
405-
as={icon}
406-
_hover={{
407-
transition:
408-
"color 0.2s ease-in-out, transform 0.2s ease-in-out",
409-
}}
410-
fontSize="4xl"
411-
/>
345+
<Icon className="h-9 w-9 hover:transform hover:transition-colors" />
412346
</BaseLink>
413347
))}
414-
</Box>
415-
<List
416-
display="flex"
417-
flexDir={{ base: "column", sm: "row" }}
418-
flexWrap="wrap"
419-
justifyContent={{ base: "center", sm: "space-between", md: "center" }}
420-
fontWeight="normal"
421-
fontSize="sm"
422-
p={5}
423-
m={0}
424-
>
348+
</div>
349+
<List className="m-0 flex flex-col flex-wrap justify-center p-5 text-sm font-normal sm:flex-row sm:justify-between md:justify-center">
425350
{dipperLinks.map(({ to, text }) => (
426-
<ListItem key={text} textAlign="center" px="2">
427-
<BaseLink href={to} w={["100%", null]} {...linkProps}>
351+
<ListItem key={text} className="px-2 text-center">
352+
<BaseLink
353+
href={to}
354+
className="w-full text-body-medium no-underline hover:text-primary hover:after:text-primary sm:w-auto"
355+
isPartiallyActive={false}
356+
>
428357
{text}
429358
</BaseLink>
430359
</ListItem>
431360
))}
432361
</List>
433-
</Flex>
434-
</Box>
362+
</div>
363+
</footer>
435364
)
436365
}
437366

src/components/SkipLink.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,19 @@
11
import { useTranslation } from "next-i18next"
2-
import { Box } from "@chakra-ui/react"
3-
4-
import { BaseLink } from "@/components/Link"
52

63
import { MAIN_CONTENT_ID } from "@/lib/constants"
74

5+
import { BaseLink } from "../../tailwind/Link"
6+
87
export const SkipLink = () => {
98
const { t } = useTranslation()
109
return (
11-
<Box bg="primary.base">
10+
<div className="bg-primary">
1211
<BaseLink
1312
href={"#" + MAIN_CONTENT_ID}
14-
lineHeight="taller"
15-
position="absolute"
16-
top="-12"
17-
ms="2"
18-
color="background.base"
19-
textDecorationLine="none"
20-
_hover={{ textDecoration: "none" }}
21-
_focus={{ position: "static" }}
13+
className="absolute -top-3 ms-2 leading-8 text-background no-underline hover:no-underline focus:static"
2214
>
2315
{t("skip-to-main-content")}
2416
</BaseLink>
25-
</Box>
17+
</div>
2618
)
2719
}

src/components/ThemeProvider.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ const ThemeProvider = ({ children }: Pick<ThemeProviderProps, "children">) => {
3333
disableTransitionOnChange
3434
storageKey={COLOR_MODE_STORAGE_KEY}
3535
>
36-
<ChakraBaseProvider theme={theme} colorModeManager={colorModeManager}>
36+
<ChakraBaseProvider
37+
theme={theme}
38+
colorModeManager={colorModeManager}
39+
resetCSS={false}
40+
>
3741
{/* TODO: Can these CSS Vars be moved to `global.css`? */}
3842
<style jsx global>
3943
{`

src/components/ui/button.tsx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import * as React from "react"
2+
import { cva, type VariantProps } from "class-variance-authority"
3+
import { Slot } from "@radix-ui/react-slot"
4+
5+
import { cn } from "@/lib/utils/cn"
6+
7+
/** FIXME: TEMP COMPONENT FOR TESTING PURPOSES */
8+
9+
const buttonVariants = cva(
10+
"inline-flex items-center justify-cente whitespace-nowrap rounded font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
11+
{
12+
variants: {
13+
variant: {
14+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
15+
destructive:
16+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
17+
outline:
18+
"border border-primary text-primary bg-background hover:bg-accent hover:text-accent-foreground",
19+
secondary:
20+
"border border-body bg-background hover:bg-accent hover:text-accent-foreground",
21+
ghost: "hover:bg-accent hover:text-accent-foreground",
22+
link: "text-primary underline-offset-4 hover:underline",
23+
},
24+
size: {
25+
default: "h-10 px-4 py-2",
26+
sm: "h-9 rounded px-3",
27+
lg: "h-11 rounded px-8",
28+
icon: "h-10 w-10",
29+
},
30+
},
31+
defaultVariants: {
32+
variant: "default",
33+
size: "default",
34+
},
35+
}
36+
)
37+
38+
export interface ButtonProps
39+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
40+
VariantProps<typeof buttonVariants> {
41+
asChild?: boolean
42+
}
43+
44+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
45+
({ className, variant, size, asChild = false, ...props }, ref) => {
46+
const Comp = asChild ? Slot : "button"
47+
return (
48+
<Comp
49+
className={cn(buttonVariants({ variant, size, className }))}
50+
ref={ref}
51+
{...props}
52+
/>
53+
)
54+
}
55+
)
56+
Button.displayName = "Button"
57+
58+
const ButtonIcon = React.forwardRef<
59+
HTMLSpanElement,
60+
React.ButtonHTMLAttributes<HTMLSpanElement> & { icon: React.ReactNode }
61+
>(({ className, icon, ...props }, ref) => {
62+
return (
63+
<span
64+
className={cn("me-2 text-base md:text-2xl", className)}
65+
ref={ref}
66+
{...props}
67+
>
68+
{icon}
69+
</span>
70+
)
71+
})
72+
ButtonIcon.displayName = "ButtonIcon"
73+
74+
export { Button, ButtonIcon, buttonVariants }

src/components/ui/list.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { BaseHTMLAttributes, ElementRef, forwardRef } from "react"
2+
3+
import { cn } from "@/lib/utils/cn"
4+
5+
const List = forwardRef<ElementRef<"ul">, BaseHTMLAttributes<HTMLUListElement>>(
6+
({ className, ...props }, ref) => (
7+
<ul ref={ref} className={cn("m-0", className)} {...props} />
8+
)
9+
)
10+
11+
List.displayName = "List"
12+
13+
const ListItem = forwardRef<
14+
ElementRef<"li">,
15+
BaseHTMLAttributes<HTMLLIElement>
16+
>(({ className, ...props }, ref) => (
17+
<li ref={ref} className={className} {...props} />
18+
))
19+
20+
ListItem.displayName = "ListItem"
21+
22+
export { List, ListItem }

src/layouts/BaseLayout.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// import { join } from "path"
22

33
import dynamic from "next/dynamic"
4-
// import { useRouter } from "next/router"
5-
import { Container } from "@chakra-ui/react"
64

5+
// import { useRouter } from "next/router"
76
import type { Root } from "@/lib/types"
87

98
import Footer from "@/components/Footer"
@@ -54,7 +53,7 @@ export const BaseLayout = ({
5453
* layout on initial load.
5554
*/}
5655
<SkipLink />
57-
<Container maxW="container.2xl" marginInline="auto">
56+
<div className="2xl:container 2xl:mx-auto">
5857
<Nav />
5958

6059
{/* TODO: FIX TRANSLATION BANNER LOGIC FOR https://github.com/ethereum/ethereum-org-website/issues/11305 */}
@@ -72,7 +71,7 @@ export const BaseLayout = ({
7271
{children}
7372

7473
<Footer lastDeployLocaleTimestamp={lastDeployLocaleTimestamp} />
75-
</Container>
74+
</div>
7675
{/**
7776
* The Feedback Widget is positioned below the container to ensure it is not affecting the
7877
* layout on initial load.

0 commit comments

Comments
 (0)