diff --git a/src/components/CodeModal.tsx b/src/components/CodeModal.tsx index 399ee1e40b7..6f44d4e28e1 100644 --- a/src/components/CodeModal.tsx +++ b/src/components/CodeModal.tsx @@ -1,24 +1,26 @@ -import type { ReactNode } from "react" -import { - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalHeader, - ModalOverlay, - useColorModeValue, -} from "@chakra-ui/react" +import { Children, type ReactElement } from "react" +import { useTranslation } from "next-i18next" +import { IoMdCopy } from "react-icons/io" +import { MdCheck } from "react-icons/md" +import { Modal, ModalBody, ModalContent, ModalOverlay } from "@chakra-ui/react" + +import { Button } from "./ui/buttons/Button" + +import { useClipboard } from "@/hooks/useClipboard" type CodeModalProps = { title: string - children: ReactNode + children?: ReactElement isOpen: boolean setIsOpen: (isOpen: boolean) => void } const CodeModal = ({ children, isOpen, setIsOpen, title }: CodeModalProps) => { - const bgColor = useColorModeValue("rgb(247, 247, 247)", "rgb(25, 25, 25)") - const borderColor = useColorModeValue("rgb(51, 51, 51)", "rgb(242, 242, 242)") + const { t } = useTranslation() + const codeSnippet = (Children.toArray(children)[0] as ReactElement).props + .children.props.children + + const { onCopy, hasCopied } = useClipboard() return ( { scrollBehavior="inside" onClose={() => setIsOpen(false)} > - + { p={{ base: "0", md: "0" }} gap="0" > - - {title} - - +
+

{title}

+ +
{children} +
) diff --git a/src/components/Codeblock.tsx b/src/components/Codeblock.tsx index ead9c3ddb85..ef6b7b9ca55 100644 --- a/src/components/Codeblock.tsx +++ b/src/components/Codeblock.tsx @@ -202,11 +202,10 @@ const getValidChildrenForCodeblock = (child) => { } } -export type CodeblockProps = { +export type CodeblockProps = React.HTMLAttributes & { allowCollapse?: boolean codeLanguage: string fromHomepage?: boolean - children: React.ReactNode } const Codeblock = ({ @@ -214,6 +213,7 @@ const Codeblock = ({ allowCollapse = true, codeLanguage, fromHomepage = false, + className, }: CodeblockProps) => { const { t } = useTranslation("common") const selectedTheme = useColorModeValue(codeTheme.light, codeTheme.dark) @@ -227,14 +227,14 @@ const Codeblock = ({ const [isCollapsed, setIsCollapsed] = useState(allowCollapse) - let className: string + let langClass: string if (React.isValidElement(children)) { - className = children?.props?.className + langClass = children?.props?.className } else { - className = codeLanguage || "" + langClass = codeLanguage || "" } - const matches = className?.match(/language-(.*)/) + const matches = langClass?.match(/language-(.*)/) const language = matches?.[1] || "" const shouldShowCopyWidget = ["js", "json", "python", "solidity"].includes( @@ -249,12 +249,9 @@ const Codeblock = ({ return ( /* Overwrites codeblocks inheriting RTL styling in Right-To-Left script languages (e.g. Arabic) */ /* Context: https://github.com/ethereum/ethereum-org-website/issues/6202 */ -
+
( - + ))}
) diff --git a/src/data/CreateWallet.ts b/src/data/CreateWallet.ts index 4711e6ccf98..4931a7c7af6 100644 --- a/src/data/CreateWallet.ts +++ b/src/data/CreateWallet.ts @@ -6,11 +6,9 @@ const mnemonic = const walletMnemonic = ethers.Wallet.fromMnemonic(mnemonic) // ...or from a private key -// eslint-disable-next-line unused-imports/no-unused-vars const walletPrivateKey = new ethers.Wallet(walletMnemonic.privateKey) // ...or create a wallet from a random private key -// eslint-disable-next-line unused-imports/no-unused-vars const randomWallet = ethers.Wallet.createRandom() walletMnemonic.address @@ -32,7 +30,6 @@ walletMnemonic.signTransaction(tx) // { Promise: '0xf865808080948ba1f109551bd432803012645ac136ddd6...dfc' } // Connect to the Ethereum network using a provider -// eslint-disable-next-line no-undef const wallet = walletMnemonic.connect(provider) // Query the network diff --git a/src/data/SimpleDomainRegistry.sol b/src/data/SimpleDomainRegistry.sol index 2a5088e4e0b..a14ae8b228a 100644 --- a/src/data/SimpleDomainRegistry.sol +++ b/src/data/SimpleDomainRegistry.sol @@ -1,4 +1,4 @@ - // SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; // This is a smart contract - a program that can be deployed to the Ethereum blockchain. diff --git a/src/hooks/useClipboard.ts b/src/hooks/useClipboard.ts new file mode 100644 index 00000000000..86d02146635 --- /dev/null +++ b/src/hooks/useClipboard.ts @@ -0,0 +1,29 @@ +import { useState } from "react" +import { useCopyToClipboard } from "usehooks-ts" + +export type UseClipboardOptions = { + /** + * timeout delay (in ms) to switch back to initial state once copied. + */ + timeout?: number +} + +export const useClipboard = ({ timeout = 1500 }: UseClipboardOptions = {}) => { + const [hasCopied, setHasCopied] = useState(false) + const [_, copy] = useCopyToClipboard() + + const onCopy = async (value: string) => { + try { + await copy(value) + + setHasCopied(true) + setTimeout(() => { + setHasCopied(false) + }, timeout) + } catch (error) { + console.error("Failed to copy!", error) + } + } + + return { onCopy, hasCopied } +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 6fef241461d..b22e3356af6 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,6 +2,8 @@ import { Fragment, lazy, Suspense } from "react" import type { GetStaticProps, InferGetStaticPropsType } from "next" import { serverSideTranslations } from "next-i18next/serverSideTranslations" import { FaDiscord, FaGithub } from "react-icons/fa6" +import { IoMdCopy } from "react-icons/io" +import { MdCheck } from "react-icons/md" import type { AllMetricData, @@ -25,7 +27,7 @@ import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import Swiper from "@/components/Swiper" import { TranslatathonBanner } from "@/components/Translatathon/TranslatathonBanner" -import { ButtonLink } from "@/components/ui/buttons/Button" +import { Button, ButtonLink } from "@/components/ui/buttons/Button" import { Card, CardBanner, @@ -64,6 +66,14 @@ import { RSS_DISPLAY_COUNT, } from "@/lib/constants" +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "../../tailwind/ui/accordion" + +import { useClipboard } from "@/hooks/useClipboard" import { fetchCommunityEvents } from "@/lib/api/calendarEvents" import { fetchEthPrice } from "@/lib/api/fetchEthPrice" import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie" @@ -181,6 +191,8 @@ const HomePage = ({ bentoItems, } = useHome() + const { onCopy, hasCopied } = useClipboard() + return ( - + @@ -382,10 +394,16 @@ const HomePage = ({ title={t("page-index:page-index-developers-code-examples")} Svg={AngleBrackets} > + {/* Desktop */} {codeExamples.map(({ title, description }, idx) => ( ))} + {/* Mobile */} + + {codeExamples.map( + ({ title, description, code, codeLanguage }) => ( + + +
+

+ {title} +

+

+ {description} +

+
+
+ + }> +
+ + {code} + + +
+
+
+
+ ) + )} +
+ {isModalOpen && ( + // TODO: Migrate CodeModal, CodeBlock from Chakra-UI to tailwind/shad-cn + + }> + + {codeExamples[activeCode].code} + + + + )}
- - {isModalOpen && ( - // TODO: Migrate CodeModal, CodeBlock from Chakra-UI to tailwind/shad-cn - - }> - - {codeExamples[activeCode].code} - - - - )}