diff --git a/src/components/MdComponents.tsx b/src/components/MdComponents.tsx deleted file mode 100644 index 9affa173a57..00000000000 --- a/src/components/MdComponents.tsx +++ /dev/null @@ -1,253 +0,0 @@ -import { ComponentProps } from "react" -import { - Badge, - Box, - type BoxProps, - chakra, - Divider as ChakraDivider, - Flex, - type FlexProps, - type HeadingProps, - ListItem, - OrderedList, - Text, - UnorderedList, - useToken, -} from "@chakra-ui/react" - -import type { ChildOnlyProp } from "@/lib/types" - -import ButtonDropdown, { - type ButtonDropdownProps, -} from "@/components/ButtonDropdown" -import { ButtonLink } from "@/components/Buttons" -import Contributors from "@/components/Contributors" -import MarkdownImage from "@/components/MarkdownImage" -import OldHeading from "@/components/OldHeading" -import { mdxTableComponents } from "@/components/Table" -import TooltipLink from "@/components/TooltipLink" -import YouTube from "@/components/YouTube" - -import ContributorsQuizBanner from "./Banners/ContributorsQuizBanner" -import GlossaryTooltip from "./Glossary/GlossaryTooltip" -import { StandaloneQuizWidget } from "./Quiz/QuizWidget" -import Card from "./Card" -import DocLink from "./DocLink" -import Emoji from "./Emoji" -import ExpandableCard from "./ExpandableCard" -import FeaturedText from "./FeaturedText" -import IdAnchor from "./IdAnchor" -import InfoBanner from "./InfoBanner" -import IssuesList from "./IssuesList" -import LocaleDateTime from "./LocaleDateTime" -import MainArticle from "./MainArticle" - -/** - * Base HTML elements - */ -const headingPropsForAnchor = (id?: string): HeadingProps => { - if (!id) return {} - return { - scrollMarginTop: 28, - id, - "data-group": true, - position: "relative", - } as HeadingProps -} - -export const commonHeadingProps = (id?: string): HeadingProps => ({ - fontWeight: 700, - lineHeight: 1.4, - ...headingPropsForAnchor(id), -}) - -export const Heading1 = ({ children, ...rest }: HeadingProps) => ( - - {children} - -) - -export const Heading2 = ({ id, children, ...rest }: HeadingProps) => ( - - - {children} - -) - -export const Heading3 = ({ id, children, ...rest }: HeadingProps) => ( - - - {children} - -) - -export const Heading4 = ({ id, children, ...rest }: HeadingProps) => ( - - - {children} - -) - -export const Pre = (props: ChildOnlyProp) => ( - -) - -export const Paragraph = (props: ChildOnlyProp) => ( - -) - -export const HR = () => ( - -) - -// All base html element components -export const htmlElements = { - a: TooltipLink, - div: Box, - h1: Heading1, - h2: Heading2, - h3: Heading3, - h4: Heading4, - hr: HR, - img: MarkdownImage, - li: ListItem, - ol: OrderedList, - p: Paragraph, - pre: Pre, - time: LocaleDateTime, - ul: UnorderedList, - ...mdxTableComponents, -} - -/** - * Custom React components - */ -export const Page = (props: FlexProps) => ( - -) - -export const Title = (props: ChildOnlyProp) => - -export const ContentContainer = (props: Pick) => { - const lgBp = useToken("breakpoints", "lg") - - return ( - - ) -} - -export const MobileButton = (props: ChildOnlyProp) => { - const borderColor = useToken("colors", "border") - return ( - - ) -} - -export const StyledButtonDropdown = ({ - list, - ...rest -}: FlexProps & Pick) => ( - - - -) - -export const MobileButtonDropdown = ( - props: ComponentProps -) => - -export const Divider = () => - -// All custom React components -export const reactComponents = { - Badge, - ButtonLink, - Card, - ContentContainer, - Contributors, - ContributorsQuizBanner, - Divider, - DocLink, - Emoji, - ExpandableCard, - FeaturedText, - GlossaryTooltip, - InfoBanner, - MobileButton, - MobileButtonDropdown, - Page, - QuizWidget: StandaloneQuizWidget, - StyledButtonDropdown, - IssuesList, - Title, - YouTube, -} - -/** - * All base markdown components as default export - */ -const MdComponents = { - ...htmlElements, - ...reactComponents, -} - -export default MdComponents diff --git a/src/components/MdComponents/MdComponents.stories.tsx b/src/components/MdComponents/MdComponents.stories.tsx new file mode 100644 index 00000000000..9d101a7334d --- /dev/null +++ b/src/components/MdComponents/MdComponents.stories.tsx @@ -0,0 +1,129 @@ +import pickBy from "lodash/pickBy" +import type { Meta, StoryObj } from "@storybook/react/*" + +import type { List as ButtonDropdownList } from "@/components/ButtonDropdown" + +import { viewportModes } from "../../../.storybook/modes" + +import MdComponentSet from "." + +const meta = { + title: "Molecules / Display Content / MdComponents", + parameters: { + layout: "none", + chromatic: { + modes: pickBy(viewportModes, (args) => + ["md", "lg"].includes(args.viewport) + ), + }, + }, +} satisfies Meta + +export default meta + +const { + ContentContainer, + h1: Heading1, + h2: Heading2, + h3: Heading3, + h4: Heading4, + Title, + p: Paragraph, + FeaturedText, + Divider, + hr: HR, + pre: Pre, + Page, + MobileButton, + MobileButtonDropdown, +} = MdComponentSet + +const Para = () => ( + + Ether (also known by its ticker symbol, ETH) is the native currency + transacted on Ethereum. ETH is needed to pay for usage of the Ethereum + network (in the form of transaction fees). ETH is also used to secure the + network with staking. When people talk about the price of Ethereum, + they're referring to ETH the asset. + +) + +export const MdComponents: StoryObj = { + render: () => ( +
+ + + + + + Heading1 + + Heading2 + + Heading3 + + Heading4 + + Title + + +
Lots of coding here
+
+ Feature Text +
+
+
+ ), +} + +const roadmapDropdownLinks: ButtonDropdownList = { + text: "nav-roadmap-options", + ariaLabel: "nav-roadmap-options-alt", + items: [ + { + text: "nav-roadmap-home", + href: "/roadmap/", + matomo: { + eventCategory: `Roadmap dropdown`, + eventAction: `Clicked`, + eventName: "clicked roadmap home", + }, + }, + { + text: "nav-roadmap-security", + href: "/roadmap/security", + matomo: { + eventCategory: `Roadmap security dropdown`, + eventAction: `Clicked`, + eventName: "clicked roadmap security", + }, + }, + { + text: "nav-roadmap-scaling", + href: "/roadmap/scaling", + matomo: { + eventCategory: `Roadmap scaling dropdown`, + eventAction: `Clicked`, + eventName: "clicked roadmap scaling home", + }, + }, + { + text: "nav-roadmap-user-experience", + href: "/roadmap/user-experience/", + matomo: { + eventCategory: `Roadmap user experience dropdown`, + eventAction: `Clicked`, + eventName: "clicked roadmap user experience home", + }, + }, + { + text: "nav-roadmap-future-proofing", + href: "/roadmap/future-proofing", + matomo: { + eventCategory: `Roadmap future-proofing dropdown`, + eventAction: `Clicked`, + eventName: "clicked roadmap future-proofing home", + }, + }, + ], +} diff --git a/src/components/MdComponents/index.tsx b/src/components/MdComponents/index.tsx new file mode 100644 index 00000000000..a58550e47c5 --- /dev/null +++ b/src/components/MdComponents/index.tsx @@ -0,0 +1,220 @@ +import { ComponentProps, type HTMLAttributes } from "react" +import { Badge, Box, type BoxProps } from "@chakra-ui/react" + +import type { ChildOnlyProp } from "@/lib/types" + +import ButtonDropdown, { + type ButtonDropdownProps, +} from "@/components/ButtonDropdown" +import Contributors from "@/components/Contributors" +import MarkdownImage from "@/components/MarkdownImage" +import { mdxTableComponents } from "@/components/Table" +import TooltipLink from "@/components/TooltipLink" +import YouTube from "@/components/YouTube" + +import { cn } from "@/lib/utils/cn" + +import ContributorsQuizBanner from "../Banners/ContributorsQuizBanner" +import Card from "../Card" +import DocLink from "../DocLink" +import Emoji from "../Emoji" +import ExpandableCard from "../ExpandableCard" +import FeaturedText from "../FeaturedText" +import GlossaryTooltip from "../Glossary/GlossaryTooltip" +import IdAnchor from "../IdAnchor" +import InfoBanner from "../InfoBanner" +import IssuesList from "../IssuesList" +import LocaleDateTime from "../LocaleDateTime" +import MainArticle from "../MainArticle" +import { StandaloneQuizWidget } from "../Quiz/QuizWidget" +import { ButtonLink } from "../ui/buttons/Button" +import { Flex } from "../ui/flex" +import { ListItem, OrderedList, UnorderedList } from "../ui/list" + +export const commonHeadingAttributes = (className: string, id?: string) => ({ + id, + className: cn( + "font-bold leading-xs my-8", + id && "scroll-mt-28 relative", + className + ), + "data-group": !!id || undefined, +}) + +type HeadingProps = HTMLAttributes + +export const Heading1 = ({ children, className, ...rest }: HeadingProps) => ( +

+ {children} +

+) + +export const Heading2 = ({ + id, + children, + className, + ...rest +}: HeadingProps) => ( +

+ + {children} +

+) + +export const Heading3 = ({ + id, + children, + className, + ...rest +}: HeadingProps) => ( +

+ + {children} +

+) + +export const Heading4 = ({ + id, + children, + className, + ...rest +}: HeadingProps) => ( +

+ + {children} +

+) + +export const Pre = (props: ChildOnlyProp) => ( +
+)
+
+export const Paragraph = (props: ChildOnlyProp) => (
+  

+) + +export const HR = () => ( +


+) + +// All base html element components +export const htmlElements = { + a: TooltipLink, + div: Box, + h1: Heading1, + h2: Heading2, + h3: Heading3, + h4: Heading4, + hr: HR, + img: MarkdownImage, + li: ListItem, + ol: OrderedList, + p: Paragraph, + pre: Pre, + time: LocaleDateTime, + ul: UnorderedList, + ...mdxTableComponents, +} + +/** + * Custom React components + */ +export const Page = ({ + className, + ...props +}: HTMLAttributes) => ( + +) + +export const Title = (props: ChildOnlyProp) => ( + +) + +export const ContentContainer = (props: Pick) => { + return ( + + ) +} + +export const MobileButton = (props: ChildOnlyProp) => { + return ( +
+ ) +} + +export const StyledButtonDropdown = ({ + list, + className, + ...rest +}: HTMLAttributes & Pick) => ( + + + +) + +export const MobileButtonDropdown = ({ + className, + ...props +}: ComponentProps) => ( + +) + +export const Divider = () => ( +
+) + +// All custom React components +export const reactComponents = { + Badge, + ButtonLink, + Card, + ContentContainer, + Contributors, + ContributorsQuizBanner, + Divider, + DocLink, + Emoji, + ExpandableCard, + FeaturedText, + GlossaryTooltip, + InfoBanner, + MobileButton, + MobileButtonDropdown, + Page, + QuizWidget: StandaloneQuizWidget, + StyledButtonDropdown, + IssuesList, + Title, + YouTube, +} + +/** + * All base markdown components as default export + */ +const MdComponents = { + ...htmlElements, + ...reactComponents, +} + +export default MdComponents diff --git a/src/layouts/Docs.tsx b/src/layouts/Docs.tsx index 7d6fc32ddf7..925b60310c8 100644 --- a/src/layouts/Docs.tsx +++ b/src/layouts/Docs.tsx @@ -1,4 +1,5 @@ import { useRouter } from "next/router" +import type { HTMLAttributes } from "react" import { Badge, Box, @@ -6,7 +7,6 @@ import { Divider as ChakraDivider, Flex, type FlexProps, - type HeadingProps, type ListProps, OrderedList as ChakraOrderedList, UnorderedList as ChakraUnorderedList, @@ -45,6 +45,7 @@ import TableOfContents from "@/components/TableOfContents" import Translation from "@/components/Translation" import YouTube from "@/components/YouTube" +import { cn } from "@/lib/utils/cn" import { getEditPath } from "@/lib/utils/editPath" const Page = (props: ChildOnlyProp & Pick) => ( @@ -80,47 +81,33 @@ const ContentContainer = (props: ContentContainerProps) => ( /> ) -const baseHeadingStyle: HeadingProps = { - fontFamily: "mono", - textTransform: "uppercase", - fontWeight: "bold", - scrollMarginTop: 40, -} +const baseHeadingClasses = "font-mono uppercase font-bold scroll-mt-40" -const H1 = (props: HeadingProps) => ( +const H1 = (props: HTMLAttributes) => ( ) -const H2 = (props: HeadingProps) => ( +const H2 = (props: HTMLAttributes) => ( ) -const baseSubHeadingStyles: HeadingProps = { - lineHeight: 1.4, - fontWeight: "semibold", -} +const baseSubHeadingClasses = "leading-xs font-semibold" -const H3 = (props: HeadingProps) => ( - +const H3 = (props: HTMLAttributes) => ( + ) -const H4 = (props: HeadingProps) => ( - +const H4 = (props: HTMLAttributes) => ( + ) const UnorderedList = (props: ListProps) => ( diff --git a/src/layouts/Staking.tsx b/src/layouts/Staking.tsx index aabe7c501c2..9236ac5e740 100644 --- a/src/layouts/Staking.tsx +++ b/src/layouts/Staking.tsx @@ -1,11 +1,11 @@ import { useTranslation } from "next-i18next" +import type { HTMLAttributes } from "react" import { Box, type BoxProps, chakra, Flex, Grid, - type HeadingProps, SimpleGrid, Text, UnorderedList, @@ -43,16 +43,12 @@ import WithdrawalsTabComparison from "@/components/Staking/WithdrawalsTabCompari import TableOfContents from "@/components/TableOfContents" import UpgradeStatus from "@/components/UpgradeStatus" -const Heading1 = (props: HeadingProps) => ( - +const Heading1 = (props: HTMLAttributes) => ( + ) -const Heading4 = (props: HeadingProps) => ( - +const Heading4 = (props: HTMLAttributes) => ( + ) const Paragraph = (props: ChildOnlyProp) => ( diff --git a/src/layouts/Static.tsx b/src/layouts/Static.tsx index 0f0fa18b64b..3b39613413e 100644 --- a/src/layouts/Static.tsx +++ b/src/layouts/Static.tsx @@ -1,5 +1,5 @@ import { useRouter } from "next/router" -import { type HeadingProps } from "@chakra-ui/react" +import type { HTMLAttributes } from "react" import type { ChildOnlyProp, Lang } from "@/lib/types" import type { MdPageContent, StaticFrontmatter } from "@/lib/interfaces" @@ -38,17 +38,17 @@ import { isLangRightToLeft } from "@/lib/utils/translations" import GuideHeroImage from "@/public/images/heroes/guides-hub-hero.jpg" -const Heading1 = (props: HeadingProps) => ( - +const Heading1 = (props: HTMLAttributes) => ( + ) -const Heading2 = (props: HeadingProps) => ( - +const Heading2 = (props: HTMLAttributes) => ( + ) -const Heading3 = (props: HeadingProps) => ( - +const Heading3 = (props: HTMLAttributes) => ( + ) -const Heading4 = (props: HeadingProps) => ( - +const Heading4 = (props: HTMLAttributes) => ( + ) // Static layout components diff --git a/src/layouts/Tutorial.tsx b/src/layouts/Tutorial.tsx index 4c5a54a0a95..aa599d44653 100644 --- a/src/layouts/Tutorial.tsx +++ b/src/layouts/Tutorial.tsx @@ -1,11 +1,11 @@ import { useRouter } from "next/router" +import type { HTMLAttributes } from "react" import { Badge, Box, type BoxProps, Divider, Flex, - type HeadingProps, Kbd, Text, type TextProps, @@ -65,40 +65,30 @@ const ContentContainer = (props: ContentContainerProps) => { ) } -const Heading1 = (props: HeadingProps) => ( +const Heading1 = (props: HTMLAttributes) => ( ) -const Heading2 = (props: HeadingProps) => ( +const Heading2 = (props: HTMLAttributes) => ( ) -const Heading3 = (props: HeadingProps) => ( +const Heading3 = (props: HTMLAttributes) => ( ) -const Heading4 = (props: HeadingProps) => ( +const Heading4 = (props: HTMLAttributes) => ( ) diff --git a/src/layouts/Upgrade.tsx b/src/layouts/Upgrade.tsx index 8978dc5f8e3..c227863f5e3 100644 --- a/src/layouts/Upgrade.tsx +++ b/src/layouts/Upgrade.tsx @@ -1,8 +1,8 @@ import { useTranslation } from "next-i18next" +import type { HTMLAttributes } from "react" import { Box, type BoxProps, - type FlexProps, List, ListItem, Text, @@ -29,7 +29,9 @@ import UpgradeStatus from "@/components/UpgradeStatus" import { getSummaryPoints } from "@/lib/utils/getSummaryPoints" -const Page = (props: FlexProps) => +const Page = (props: HTMLAttributes) => ( + +) type ContainerProps = Pick