Skip to content

Commit c58faab

Browse files
feat: migrate Layer2ProductCard to tailwind and shadcn
1 parent dfe8d57 commit c58faab

File tree

2 files changed

+132
-63
lines changed

2 files changed

+132
-63
lines changed

src/components/Layer2ProductCard.tsx

Lines changed: 76 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// Libraries
21
import { StaticImageData } from "next/image"
2+
import Image from "next/image"
3+
import Link from "next/link"
34
import { useTranslation } from "next-i18next"
4-
import { Box, Center, Flex, Heading } from "@chakra-ui/react"
5+
import { RiExternalLinkLine } from "react-icons/ri"
56

6-
import { ButtonLink } from "@/components/Buttons"
7-
import { Image } from "@/components/Image"
8-
import InlineLink from "@/components/Link"
9-
import Text from "@/components/OldText"
7+
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
8+
9+
import { Button } from "./ui/button"
1010

1111
export type Layer2ProductCardProps = {
1212
children?: React.ReactNode
@@ -38,72 +38,85 @@ const Layer2ProductCard = ({
3838
const { t } = useTranslation("page-layer-2")
3939

4040
return (
41-
<Flex
42-
color="text"
43-
boxShadow={"0px 14px 66px rgba(0, 0, 0, 0.07)"}
44-
direction="column"
45-
justify="space-between"
46-
bg="searchBackground"
47-
borderRadius="base"
48-
border={"1px solid lightBorder"}
49-
textDecoration="none"
50-
padding={2}
51-
_hover={{ transition: "transform 0.1s", transform: "scale(1.02)" }}
52-
>
53-
<Center
54-
bg={background}
55-
boxShadow="inset 0px -1px 0px rgba(0, 0, 0, 0.1)"
56-
minH="200px"
41+
<Card className="text-foreground flex flex-col justify-between rounded-md border-0 p-2 shadow-lg transition-transform duration-100 hover:scale-[1.02] dark:bg-background-medium">
42+
<div
43+
className="mb-4 flex min-h-[200px] items-center justify-center border-b"
44+
style={{ backgroundColor: background }}
5745
>
5846
<Image
5947
src={image}
6048
alt={alt}
6149
width={100}
62-
maxH={"257px"}
63-
style={{ objectFit: "contain" }}
50+
height={100}
51+
className="max-h-[257px] object-contain"
6452
/>
65-
</Center>
66-
<Flex p={6} h="100%" direction="column">
67-
<Box>
68-
<Heading as="h3" fontSize={{ base: "xl", md: "2xl" }} mb={3}>
69-
{name}
70-
</Heading>
71-
{children && (
72-
<Box mt={4} mb={4}>
73-
{children}
74-
</Box>
75-
)}
76-
<Text fontSize="sm" mb={2} lineHeight="140%">
77-
{description}
78-
</Text>
79-
{note.length > 0 && (
80-
<Text fontSize="sm" mb={2} lineHeight="140%">
53+
</div>
54+
55+
<CardHeader className="py-0">
56+
<div className="space-y-4">
57+
<h3 className="mb-3 text-xl font-semibold md:text-2xl">{name}</h3>
58+
{children && <div>{children}</div>}
59+
</div>
60+
</CardHeader>
61+
62+
<CardContent className="flex flex-grow flex-col gap-0 space-y-1 px-6 py-4">
63+
<div className="space-y-2">
64+
<p className="text-sm leading-snug">{description}</p>
65+
66+
{note && (
67+
<p className="text-sm leading-snug">
8168
{t("layer-2-note")} {note}
82-
</Text>
69+
</p>
8370
)}
84-
</Box>
85-
{bridge && (
86-
<InlineLink href={bridge}>
87-
{name} {t("layer-2-bridge")}
88-
</InlineLink>
89-
)}
90-
{ecosystemPortal && (
91-
<InlineLink href={ecosystemPortal}>
92-
{name} {t("layer-2-ecosystem-portal")}
93-
</InlineLink>
94-
)}
95-
{tokenLists && (
96-
<InlineLink href={tokenLists}>
97-
{name} {t("layer-2-token-lists")}
98-
</InlineLink>
71+
</div>
72+
73+
<div className="space-y-1">
74+
{bridge && (
75+
<Link
76+
href={bridge}
77+
className="block text-primary underline hover:text-primary/80"
78+
>
79+
{name} {t("layer-2-bridge")}
80+
</Link>
81+
)}
82+
83+
{ecosystemPortal && (
84+
<Link
85+
href={ecosystemPortal}
86+
className="block text-primary underline hover:text-primary/80"
87+
>
88+
{name} {t("layer-2-ecosystem-portal")}
89+
</Link>
90+
)}
91+
92+
{tokenLists && (
93+
<Link
94+
href={tokenLists}
95+
className="block text-primary underline hover:text-primary/80"
96+
>
97+
{name} {t("layer-2-token-lists")}
98+
</Link>
99+
)}
100+
</div>
101+
</CardContent>
102+
103+
<CardFooter className="mt-2 p-2">
104+
{url && (
105+
<Button
106+
variant={"default"}
107+
asChild
108+
className="w-full rounded-sm hover:text-white hover:shadow-[4px_4px_4px_rgba(147,51,234,0.25)] dark:bg-primary-action dark:hover:bg-primary/90 dark:hover:shadow-[4px_4px_4px_rgba(0,0,0,0.9)]"
109+
>
110+
<Link
111+
href={url}
112+
className="flex items-center gap-0 text-lg text-white no-underline"
113+
>
114+
{t("layer-2-explore")} {name} <RiExternalLinkLine />
115+
</Link>
116+
</Button>
99117
)}
100-
</Flex>
101-
<Box>
102-
<ButtonLink m={2} href={url} display="flex">
103-
{t("layer-2-explore")} {name}
104-
</ButtonLink>
105-
</Box>
106-
</Flex>
118+
</CardFooter>
119+
</Card>
107120
)
108121
}
109122

src/components/ui/button.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm 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 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9+
{
10+
variants: {
11+
variant: {
12+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
13+
destructive:
14+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
15+
outline:
16+
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17+
secondary:
18+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
19+
ghost: "hover:bg-accent hover:text-accent-foreground",
20+
link: "text-primary underline-offset-4 hover:underline",
21+
},
22+
size: {
23+
default: "h-10 px-4 py-2",
24+
sm: "h-9 rounded-md px-3",
25+
lg: "h-11 rounded-md px-8",
26+
icon: "h-10 w-10",
27+
},
28+
},
29+
defaultVariants: {
30+
variant: "default",
31+
size: "default",
32+
},
33+
}
34+
)
35+
36+
export interface ButtonProps
37+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38+
VariantProps<typeof buttonVariants> {
39+
asChild?: boolean
40+
}
41+
42+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43+
({ className, variant, size, asChild = false, ...props }, ref) => {
44+
const Comp = asChild ? Slot : "button"
45+
return (
46+
<Comp
47+
className={cn(buttonVariants({ variant, size, className }))}
48+
ref={ref}
49+
{...props}
50+
/>
51+
)
52+
}
53+
)
54+
Button.displayName = "Button"
55+
56+
export { Button, buttonVariants }

0 commit comments

Comments
 (0)