diff --git a/site-new/assets/icons/GoIcon.tsx b/site-new/assets/icons/GoIcon.tsx new file mode 100644 index 000000000..20561ec3c --- /dev/null +++ b/site-new/assets/icons/GoIcon.tsx @@ -0,0 +1,682 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const GoIcon = ({ + height = 60, + width = 44, + ...props +}: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default GoIcon; diff --git a/site-new/assets/icons/GoMobile.tsx b/site-new/assets/icons/GoMobile.tsx new file mode 100644 index 000000000..5b5b6ab3d --- /dev/null +++ b/site-new/assets/icons/GoMobile.tsx @@ -0,0 +1,678 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const GoMobile = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default GoMobile; diff --git a/site-new/assets/icons/JSIcon.tsx b/site-new/assets/icons/JSIcon.tsx new file mode 100644 index 000000000..37040b531 --- /dev/null +++ b/site-new/assets/icons/JSIcon.tsx @@ -0,0 +1,23 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const JSIcon = ({ + height = 60, + width = 60, + ...props +}: SVGProps) => ( + + + +); +export default JSIcon; diff --git a/site-new/assets/icons/JSMobile.tsx b/site-new/assets/icons/JSMobile.tsx new file mode 100644 index 000000000..52fe08acd --- /dev/null +++ b/site-new/assets/icons/JSMobile.tsx @@ -0,0 +1,19 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const JSMobile = (props: SVGProps) => ( + + + +); +export default JSMobile; diff --git a/site-new/assets/icons/Kotlin.tsx b/site-new/assets/icons/Kotlin.tsx new file mode 100644 index 000000000..736587fc7 --- /dev/null +++ b/site-new/assets/icons/Kotlin.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const Kotlin = (props: SVGProps) => ( + + + + + + + + + + + +); +export default Kotlin; diff --git a/site-new/assets/icons/KotlinMobile.tsx b/site-new/assets/icons/KotlinMobile.tsx new file mode 100644 index 000000000..ef4ead38e --- /dev/null +++ b/site-new/assets/icons/KotlinMobile.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const KotlinMobile = (props: SVGProps) => ( + + + + + + + + + + + +); +export default KotlinMobile; diff --git a/site-new/assets/icons/Swift.tsx b/site-new/assets/icons/Swift.tsx new file mode 100644 index 000000000..ac0578777 --- /dev/null +++ b/site-new/assets/icons/Swift.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const Swift = ({ + height = 60, + width = 60, + ...props +}: SVGProps) => ( + + + + +); +export default Swift; diff --git a/site-new/assets/icons/SwiftMobile.tsx b/site-new/assets/icons/SwiftMobile.tsx new file mode 100644 index 000000000..e491da94b --- /dev/null +++ b/site-new/assets/icons/SwiftMobile.tsx @@ -0,0 +1,21 @@ +import * as React from "react"; +import { SVGProps } from "react"; +const SwiftMobile = (props: SVGProps) => ( + + + + +); +export default SwiftMobile; diff --git a/site-new/src/components/IconButton/IconButton.tsx b/site-new/src/components/IconButton/IconButton.tsx new file mode 100644 index 000000000..b0a1c0ffb --- /dev/null +++ b/site-new/src/components/IconButton/IconButton.tsx @@ -0,0 +1,21 @@ +import { cn } from "@site/lib/utils"; +import React from "react"; + +type ButtonProps = Omit, "children"> & { + children: React.ReactNode; +}; + +export const iconButtonClasses = + "unset w-max cursor-pointer leading-[0] outline-none hover:opacity-50 focus-visible:ring-1 focus-visible:ring-white active:opacity-20 transition-opacity"; + +const IconButton = React.forwardRef( + ({ className, children, ...props }, ref) => { + return ( + + ); + }, +); + +export default IconButton; diff --git a/site-new/src/components/IconButton/IconButtonLink.tsx b/site-new/src/components/IconButton/IconButtonLink.tsx new file mode 100644 index 000000000..668fe2fb6 --- /dev/null +++ b/site-new/src/components/IconButton/IconButtonLink.tsx @@ -0,0 +1,18 @@ +import Link from "@docusaurus/Link"; +import { cn } from "@site/lib/utils"; +import React from "react"; +import { iconButtonClasses } from "./IconButton"; + +type LinkProps = React.ComponentProps; + +const IconButtonLink = React.forwardRef( + ({ className, children, ...props }, ref) => { + return ( + + {children} + + ); + }, +); + +export default IconButtonLink; diff --git a/site-new/src/components/IconButton/index.ts b/site-new/src/components/IconButton/index.ts new file mode 100644 index 000000000..c9a6ee82e --- /dev/null +++ b/site-new/src/components/IconButton/index.ts @@ -0,0 +1,2 @@ +export { default as IconButton } from "./IconButton"; +export { default as IconButtonLink } from "./IconButtonLink"; diff --git a/site-new/src/components/ImageCard.tsx b/site-new/src/components/ImageCard.tsx index fb55f5343..d941f455a 100644 --- a/site-new/src/components/ImageCard.tsx +++ b/site-new/src/components/ImageCard.tsx @@ -62,6 +62,7 @@ function ImageCard({ className={`${currentSize.image} object-cover`} /> >; +}; + +const ResponsiveIcon = ({ + mobileIcon, + desktopIcon, +}: { + mobileIcon: React.ReactNode; + desktopIcon: React.ReactNode; +}) => ( + <> + {desktopIcon} + {mobileIcon} + +); + +const languageIconMap: Record = { + swift: ( + } desktopIcon={} /> + ), + js: } desktopIcon={} />, + go: } desktopIcon={} />, + kotlin: ( + } desktopIcon={} /> + ), +}; + +type DefaultProps = { + type?: "default"; +}; type TextIconCardProps = { icon?: React.ComponentType<{ className: string; fill?: string }>; title: string; text: string; - url?: string; className?: string; theme?: Theme; - buttonText?: string; hasBorder?: boolean; +} & (ButtonProps | LanguageButtonProps | DefaultProps); + +const themeClasses: Record = { + yellow: "text-white ", + teal: "text-white ", + purple: "text-white ", + grey: "text-white ", + iconyellow: "fill-tbd-yellow ", + iconteal: "fill-tbd-teal ", + iconpurple: "fill-tbd-purple-tint-2 ", + icongrey: "fill-tbd-grey ", }; -const themeClasses = { - yellow: "text-white hover:bg-tbd-yellow hover:text-tbd-gray", - teal: "text-white hover:bg-tbd-teal hover:text-tbd-gray", - purple: "text-white hover:bg-tbd-purple hover:text-tbd-gray", - grey: "text-white hover:bg-dark-grey hover:text-tbd-gray", - iconyellow: "fill-tbd-yellow group-hover:fill-tbd-gray", - iconteal: "fill-tbd-teal group-hover:fill-tbd-gray", - iconpurple: "fill-tbd-purple-tint-2 group-hover:fill-tbd-gray", - icongrey: "fill-tbd-grey group-hover:fill-tbd-gray", +const themeClassesHover: Record = { + yellow: "hover:bg-tbd-yellow hover:text-tbd-gray", + teal: "hover:bg-tbd-teal hover:text-tbd-gray", + purple: "hover:bg-tbd-purple hover:text-tbd-gray", + grey: "hover:bg-dark-grey hover:text-tbd-gray", + iconyellow: "group-hover:fill-tbd-gray", + iconteal: "group-hover:fill-tbd-gray", + iconpurple: "group-hover:fill-tbd-gray", + icongrey: "group-hover:fill-tbd-gray", }; function TextIconCard({ icon: Icon, title, text, - url, className = "", theme = "grey", - buttonText, hasBorder = true, + ...props }: TextIconCardProps) { - const themeClass = themeClasses[theme]; + const isHoverEnabled = + props.type === "buttonText" || props.type === "default" || !props.type; + const themeClass = cn(themeClasses[theme], { + [themeClassesHover[theme]]: isHoverEnabled, + }); const iconClass = themeClasses[`icon${theme}`]; // Conditionally apply border styles based on `hasBorder` (only for TextIconCard) @@ -58,26 +129,54 @@ function TextIconCard({ )} {title}

{text}

- {url && buttonText && ( + {props.type === "buttonText" && ( - {buttonText} + {props.buttonText} )} + <> + {props.type === "languageButton" && + Object.keys(props.resources).some( + (key) => props.resources[key as Languages], + ) && ( +
+ {Object.keys(props.resources).map((key) => { + const value = props.resources[key as Languages]; + return ( + value && ( + + {languageIconMap[key as Languages]} + + ) + ); + })} +
+ )} + ); diff --git a/site-new/src/pages/component-guide/icon-button.mdx b/site-new/src/pages/component-guide/icon-button.mdx new file mode 100644 index 000000000..9f215cb6d --- /dev/null +++ b/site-new/src/pages/component-guide/icon-button.mdx @@ -0,0 +1,49 @@ +import React from "react"; +import { IconButton } from "@site/src/components/IconButton"; +import Swift from "@site/assets/icons/Swift"; +import Kotlin from "@site/assets/icons/Kotlin"; +import JSIcon from "@site/assets/icons/JSIcon"; +import GoIcon from "@site/assets/icons/GoIcon"; + +# Icon Component + +
+

The `IconButton` component is used to display a button with an icon and text.

+ +## Properties + +| Property | Type | Required | Default | Description | +| ---------- | ----------------- | -------- | ------- | ---------------------------------- | +| `children` | `React.ReactNode` | Yes | `""` | The icon to display on the button. | + +## Usage + +```jsx title="Icon Button Component" + + + +``` + +## Examples + +

Swift Icon

+ + + + +

Kotlin Icon

+ + + + +

JavaScript Icon

+ + + + +

Go Icon

+ + + + +
diff --git a/site-new/src/pages/component-guide/index.tsx b/site-new/src/pages/component-guide/index.tsx index 91e6dcbcc..b740239a6 100644 --- a/site-new/src/pages/component-guide/index.tsx +++ b/site-new/src/pages/component-guide/index.tsx @@ -15,6 +15,9 @@ function ComponentList() { { name: "Admonition", path: "/component-guide/admonition" }, { name: "ImageCard", path: "/component-guide/image-card" }, { name: "SpotLightCard", path: "/component-guide/spotlight-card" }, + { name: "IconButton", path: "/component-guide/icon-button" }, + { name: "CodeBlock", path: "/component-guide/code-block" }, + { name: "IconButton", path: "/component-guide/icon-button" }, { name: "CodeBlock", path: "/component-guide/code-block" }, ]; diff --git a/site-new/src/pages/component-guide/text-icon-card.mdx b/site-new/src/pages/component-guide/text-icon-card.mdx index 189817d73..d7abd3aae 100644 --- a/site-new/src/pages/component-guide/text-icon-card.mdx +++ b/site-new/src/pages/component-guide/text-icon-card.mdx @@ -1,6 +1,6 @@ -import React from 'react'; -import TextIconCard from '@site/src/components/TextIconCard'; -import tbdRex from '@site/static/img/tbd-rex'; +import React from "react"; +import TextIconCard from "@site/src/components/TextIconCard"; +import tbdRex from "@site/static/img/tbd-rex"; # TextIconCard Component @@ -11,15 +11,17 @@ This component displays an optional icon, title, text, and an optional button. I ## Properties -| Property | Type | Required | Default | Description | -|--------------|-----------------------------------------------------|----------|---------|-------------------------------------------------------------------------------------------------------| -| `icon` | `React.ComponentType<{ className: string; fill: string }>` | No | | The optional icon component to display in the card. | -| `title` | `string` | Yes | | The title text for the card. | -| `text` | `string` | Yes | | The description or text content for the card. | -| `url` | `string` | No | | The optional URL to navigate to when the button is clicked. | -| `className` | `string` | No | | Additional CSS classes to apply to the card. | -| `theme` | `"yellow" \| "teal" \| "purple" \| "grey"` | No | `grey` | The theme color of the card. | -| `buttonText` | `string` | No | | The optional text to display on the button. | +| Property | Type | Required | Default | Description | +| ------------ | ---------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------- | +| `icon` | `React.ComponentType<{ className: string; fill: string }>` | No | | The optional icon component to display in the card. | +| `title` | `string` | Yes | | The title text for the card. | +| `text` | `string` | Yes | | The description or text content for the card. | +| `url` | `string` | No | | The optional URL to navigate to when the button is clicked. | +| `className` | `string` | No | | Additional CSS classes to apply to the card. | +| `theme` | `"yellow" \| "teal" \| "purple" \| "grey"` | No | `grey` | The theme color of the card. | +| `buttonText` | `string` | No | | The optional text to display on the button. | +| `type` | `"buttonText" \| "languageButton"` | No | `buttonText` | The type of button to display. | +| `resources` | `{ [key: string]: string }` | No | | The resources to display when the type is `languageButton`. | ## Usage @@ -28,6 +30,7 @@ This component displays an optional icon, title, text, and an optional button. I icon={tbdRex} title="Rocket" text="An open source messaging service that enables wallet applications to communicate with financial institutions to discover and obtain liquidity." + type="buttonText" url="https://example.com" theme="yellow" buttonText="Talk Money To Me" @@ -37,49 +40,72 @@ This component displays an optional icon, title, text, and an optional button. I ## Examples Yellow Theme + Teal Theme + Purple Theme + Teal Theme without Icon + Purple Theme without Button and Icon + + + +Icon card with Language Button + - \ No newline at end of file +