|
1 | | -import { ReactElement } from "react" |
2 | | -import { Card } from "./card" |
3 | 1 | import { clsx } from "clsx" |
4 | | -import NextLink from "next/link" |
| 2 | +import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr" |
| 3 | +import { learnPages } from "./learn-aggregator/learn-pages" |
5 | 4 |
|
6 | 5 | export function Cards({ |
7 | 6 | items, |
| 7 | + numbered = false, |
8 | 8 | }: { |
9 | 9 | items: { |
10 | | - icon: ReactElement |
| 10 | + icon?: (({ className }: { className?: string }) => React.ReactNode) | React.ReactNode |
11 | 11 | title: string |
12 | 12 | description?: string |
13 | 13 | link: string |
14 | 14 | }[] |
| 15 | + numbered?: boolean |
15 | 16 | }) { |
16 | 17 | return ( |
17 | | - <div className="mt-6 grid grid-cols-2 gap-4"> |
18 | | - {items.map(({ icon: Icon, title, link, description }) => { |
19 | | - const isExternal = link.startsWith("https://") |
| 18 | + <ul className="grid grid-cols-1 justify-stretch gap-2 pt-6 sm:grid-cols-2 lg:gap-4"> |
| 19 | + {items.map((item, index) => { |
| 20 | + // Try to get section from learn-pages |
| 21 | + let section: "getting-started" | "best-practices" | undefined |
| 22 | + |
| 23 | + const path = item.link.replace(/^\/learn\//, "").replace(/\/$/, "") |
| 24 | + const learnPage = learnPages[path as keyof typeof learnPages] |
| 25 | + if (learnPage) { |
| 26 | + section = learnPage.section |
| 27 | + } |
| 28 | + |
20 | 29 | return ( |
21 | | - <Card |
22 | | - key={title} |
23 | | - as={isExternal ? "a" : NextLink} |
24 | | - // @ts-expect-error |
25 | | - href={link} |
26 | | - className={clsx( |
27 | | - "flex flex-col items-center", |
28 | | - isExternal && |
29 | | - "relative after:absolute after:right-4 after:top-4 after:font-sans after:content-['_↗']", |
30 | | - )} |
31 | | - > |
32 | | - {/* @ts-expect-error */} |
33 | | - {typeof Icon === "function" ? <Icon className="h-12" /> : Icon} |
34 | | - <b className="mb-2 mt-4 text-center text-lg">{title}</b> |
35 | | - <span |
36 | | - className={`text-xs md:text-sm text-center${description ? "" : "break-all"}`} |
| 30 | + <li key={item.title} className="flex text-neu-900"> |
| 31 | + <a |
| 32 | + href={item.link} |
| 33 | + className={clsx( |
| 34 | + "gql-focus-visible grid w-full border border-neu-200 bg-neu-0 transition-colors [grid-template-areas:'header''desc'] [grid-template-rows:auto_1fr] hover:ring hover:ring-neu-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:border-neu-100 dark:hover:ring-neu-50 lg:[grid-template-areas:'header_header''desc_arrow'] lg:[grid-template-columns:1fr_64px]", |
| 35 | + section === "getting-started" && |
| 36 | + "bg-pri-lighter/10 dark:bg-pri-lighter/5", |
| 37 | + section === "best-practices" && |
| 38 | + "bg-sec-lighter/10 dark:bg-sec-lighter/5", |
| 39 | + )} |
37 | 40 | > |
38 | | - {description ? description : link.replace(/^https?:\/\//, "")} |
39 | | - </span> |
40 | | - </Card> |
| 41 | + <span className="flex flex-col gap-1 [grid-area:header]"> |
| 42 | + {numbered && ( |
| 43 | + <span className="typography-body-sm px-2 pt-2 text-neu-700 max-lg:typography-body-md lg:px-4 lg:pt-4"> |
| 44 | + Lesson {index + 1} |
| 45 | + </span> |
| 46 | + )} |
| 47 | + <span |
| 48 | + className={clsx( |
| 49 | + "typography-h3 flex items-center gap-2 border-neu-200 text-neu-900 dark:border-neu-100", |
| 50 | + item.icon ? "border-b" : "pl-2 lg:pl-4", |
| 51 | + )} |
| 52 | + > |
| 53 | + {item.icon && ( |
| 54 | + <span className="flex items-center justify-center border-r border-neu-200 p-2 lg:p-4"> |
| 55 | + {typeof item.icon === "function" ? <item.icon className="size-8 shrink-0" /> : item.icon} |
| 56 | + </span> |
| 57 | + )} |
| 58 | + {item.title} |
| 59 | + </span> |
| 60 | + </span> |
| 61 | + |
| 62 | + <p className="typography-body-sm text-pretty p-4 text-neu-900 [grid-area:desc] max-lg:typography-body-md max-lg:border-t max-lg:border-neu-200 dark:max-lg:border-neu-100"> |
| 63 | + {item.description |
| 64 | + ? item.description |
| 65 | + : item.link.replace(/^https?:\/\//, "")} |
| 66 | + </p> |
| 67 | + |
| 68 | + <span |
| 69 | + className={clsx( |
| 70 | + "hidden items-center justify-center place-self-end border-l border-neu-200 p-4 [grid-area:arrow] dark:border-neu-100 lg:flex", |
| 71 | + item.icon ? "h-full" : "border-t", |
| 72 | + )} |
| 73 | + > |
| 74 | + <ArrowDownIcon className="size-8 shrink-0 -rotate-90" /> |
| 75 | + </span> |
| 76 | + </a> |
| 77 | + </li> |
41 | 78 | ) |
42 | 79 | })} |
43 | | - </div> |
| 80 | + </ul> |
44 | 81 | ) |
45 | 82 | } |
0 commit comments