diff --git a/apps/web/app/(base-org)/developers/verifications/page.tsx b/apps/web/app/(base-org)/developers/verifications/page.tsx new file mode 100644 index 00000000000..8bfafbd05be --- /dev/null +++ b/apps/web/app/(base-org)/developers/verifications/page.tsx @@ -0,0 +1,79 @@ +import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types'; +import Container from 'apps/web/src/components/base-org/Container'; +import Title from 'apps/web/src/components/base-org/typography/Title'; +import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types'; +import { ButtonWithLinkAndEventLogging } from 'apps/web/src/components/Button/ButtonWithLinkAndEventLogging'; +import { CtaBanner } from 'apps/web/src/components/Developers/Shared/CtaBanner'; +import { Customers } from 'apps/web/src/components/Developers/Verifications/Customers'; +import { InfoCards } from 'apps/web/src/components/Developers/Verifications/InfoCards'; +import { ValueProps } from 'apps/web/src/components/Developers/Verifications/ValueProps'; +import verification from 'apps/web/src/components/Developers/Verifications/verification.svg'; +import Image, { StaticImageData } from 'next/image'; + +export default async function Verifications() { + return ( + +
+ {/* Header */} +
+
+ verification + + Verifications + +
+ + Identify your high-quality users + + + Identify your high-quality users + + + Verifications is the link that lets you verify over 500,000+ connected wallets and + Coinbase accounts of specific attributes. + + +
+ + Start building + +
+
+ + + + + + Get started + + } + /> +
+
+ ); +} diff --git a/apps/web/src/components/Developers/Shared/Card.tsx b/apps/web/src/components/Developers/Shared/Card.tsx new file mode 100644 index 00000000000..737893495cb --- /dev/null +++ b/apps/web/src/components/Developers/Shared/Card.tsx @@ -0,0 +1,30 @@ +import Title from 'apps/web/src/components/base-org/typography/Title'; +import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types'; +import { ReactNode } from 'react'; + +type CardProps = { + icon: ReactNode; + title: string; + description: string; + iconClassName: string; + className?: string; +}; +export function Card({ + icon, + title, + description, + iconClassName = 'text-white', + className, +}: CardProps) { + return ( +
+
{icon}
+ + {title} + + + {description} + +
+ ); +} diff --git a/apps/web/src/components/Developers/Shared/CtaBanner.tsx b/apps/web/src/components/Developers/Shared/CtaBanner.tsx new file mode 100644 index 00000000000..f88d16b692a --- /dev/null +++ b/apps/web/src/components/Developers/Shared/CtaBanner.tsx @@ -0,0 +1,27 @@ +'use client'; + +import { ReactNode } from 'react'; +import Title from 'apps/web/src/components/base-org/typography/Title'; +import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types'; + +type CtaBannerProps = { + title: string; + description: string; + cta?: ReactNode; +}; + +export function CtaBanner({ title, description, cta }: CtaBannerProps) { + return ( +
+
+ + {title} + + + {description} + +
{cta}
+
+
+ ); +} diff --git a/apps/web/src/components/Developers/Shared/Marquee.tsx b/apps/web/src/components/Developers/Shared/Marquee.tsx new file mode 100644 index 00000000000..3b8a6b6aff8 --- /dev/null +++ b/apps/web/src/components/Developers/Shared/Marquee.tsx @@ -0,0 +1,73 @@ +import { cn } from 'base-ui/utils/cn'; +import { ComponentPropsWithoutRef } from 'react'; + +export type MarqueeProps = ComponentPropsWithoutRef<'div'> & { + /** + * Optional CSS class name to apply custom styles + */ + className?: string; + /** + * Whether to reverse the animation direction + * @default false + */ + reverse?: boolean; + /** + * Whether to pause the animation on hover + * @default false + */ + pauseOnHover?: boolean; + /** + * Content to be displayed in the marquee + */ + children: React.ReactNode; + /** + * Whether to animate vertically instead of horizontally + * @default false + */ + vertical?: boolean; + /** + * Number of times to repeat the content + * @default 4 + */ + repeat?: number; +}; + +export function Marquee({ + className, + reverse = false, + pauseOnHover = false, + children, + vertical = false, + repeat = 4, + ...props +}: MarqueeProps) { + return ( +
+ {Array(repeat) + .fill(0) + .map(() => ( +
+ {children} +
+ ))} +
+ ); +} diff --git a/apps/web/src/components/Developers/Shared/ValueProp.tsx b/apps/web/src/components/Developers/Shared/ValueProp.tsx new file mode 100644 index 00000000000..aebe6e8aee0 --- /dev/null +++ b/apps/web/src/components/Developers/Shared/ValueProp.tsx @@ -0,0 +1,39 @@ +import Title from 'apps/web/src/components/base-org/typography/Title'; +import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types'; +import Image, { type StaticImageData } from 'next/image'; + +export type ValuePropProps = { + title: string; + description: string; + icon: StaticImageData; +}; + +export function ValueProp({ title, description, icon }: ValuePropProps) { + return ( +
+
+ {title} +
+ + {title} + + + {description} + +
+
+ +
+ {title} +
+ + {title} + + + {description} + +
+
+
+ ); +} diff --git a/apps/web/src/components/Developers/Verifications/Customers.tsx b/apps/web/src/components/Developers/Verifications/Customers.tsx new file mode 100644 index 00000000000..629a56eebfa --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/Customers.tsx @@ -0,0 +1,39 @@ +import Title from 'apps/web/src/components/base-org/typography/Title'; +import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types'; +import { Marquee } from 'apps/web/src/components/Developers/Shared/Marquee'; +import icebreaker from 'apps/web/src/components/Developers/Verifications/icebreaker.svg'; +import deform from 'apps/web/src/components/Developers/Verifications/deform.svg'; +import gitcoin from 'apps/web/src/components/Developers/Verifications/gitcoin.svg'; +import talentProtocol from 'apps/web/src/components/Developers/Verifications/talent-protocol.svg'; +import Image, { StaticImageData } from 'next/image'; + +export function Customers() { + return ( +
+ + Powering the most consumer-friendly applications onchain. + +
+ +
+ icebreaker +
+ +
+ deform +
+
+ gitcoin +
+
+ talentProtocol +
+
+
+
+ ); +} diff --git a/apps/web/src/components/Developers/Verifications/InfoCards.tsx b/apps/web/src/components/Developers/Verifications/InfoCards.tsx new file mode 100644 index 00000000000..fa561a30a27 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/InfoCards.tsx @@ -0,0 +1,62 @@ +import { Card } from 'apps/web/src/components/Developers/Shared/Card'; +import key from 'apps/web/src/components/Developers/Verifications/key.svg'; +import identityCard from 'apps/web/src/components/Developers/Verifications/identityCard.svg'; +import complianceProduct from 'apps/web/src/components/Developers/Verifications/complianceProduct.svg'; +import Image, { StaticImageData } from 'next/image'; + +const INFO_CARDS = [ + { + icon: ( + key + ), + title: 'Access control', + description: + 'Implement granular access control using verified Coinbase attestations. Perfect for gating features, content, or entire applications.', + }, + { + icon: ( + identityCard + ), + title: 'Identity verification', + description: + 'Seamlessly verify user identities without handling sensitive data. Reduce fraud and enhance security in your DeFi applications.', + }, + { + icon: ( + complianceProduct + ), + title: 'Compliance & reporting', + description: + 'Build compliant applications with verifiable attestations. Perfect for KYC requirements and regulatory reporting.', + }, +]; + +export function InfoCards() { + return ( +
+ {INFO_CARDS.map((card) => { + return ( + + ); + })} +
+ ); +} diff --git a/apps/web/src/components/Developers/Verifications/ValueProps.tsx b/apps/web/src/components/Developers/Verifications/ValueProps.tsx new file mode 100644 index 00000000000..a2f4cbabb8e --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/ValueProps.tsx @@ -0,0 +1,51 @@ +import { ValueProp, ValuePropProps } from 'apps/web/src/components/Developers/Shared/ValueProp'; +import coinbase from 'apps/web/src/components/Developers/Verifications/coinbase.svg'; +import globe from 'apps/web/src/components/Developers/Verifications/globe.svg'; +import coinbaseOne from 'apps/web/src/components/Developers/Verifications/coinbaseOne.svg'; +import { StaticImageData } from 'next/image'; +import Title from 'apps/web/src/components/base-org/typography/Title'; +import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types'; + +const VALUE_PROPS: ValuePropProps[] = [ + { + title: 'Verified Account', + description: 'A Coinbase user with a valid Coinbase trading account. ', + icon: coinbase as StaticImageData, + }, + { + title: 'Verified Country', + description: 'The user’s verified country of residence on Coinbase.', + icon: globe as StaticImageData, + }, + { + title: 'Verified Coinbase One', + description: 'A Coinbase user with an active Coinbase One membership.', + icon: coinbaseOne as StaticImageData, + }, +]; +export function ValueProps() { + return ( +
+
+ + Supported attestations.{' '} + <Title level={TitleLevel.Title1} as="span" className="text-dark-palette-foregroundMuted"> + Coinbase trust with a few lines of code. + + +
+
+ {VALUE_PROPS.map((item: ValuePropProps) => { + return ( + + ); + })} +
+
+ ); +} diff --git a/apps/web/src/components/Developers/Verifications/coinbase.svg b/apps/web/src/components/Developers/Verifications/coinbase.svg new file mode 100644 index 00000000000..899ba157501 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/coinbase.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/components/Developers/Verifications/coinbaseOne.svg b/apps/web/src/components/Developers/Verifications/coinbaseOne.svg new file mode 100644 index 00000000000..8dc8b6236cc --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/coinbaseOne.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/components/Developers/Verifications/complianceProduct.svg b/apps/web/src/components/Developers/Verifications/complianceProduct.svg new file mode 100644 index 00000000000..c6c0e074231 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/complianceProduct.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/components/Developers/Verifications/deform.svg b/apps/web/src/components/Developers/Verifications/deform.svg new file mode 100644 index 00000000000..9d801225569 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/deform.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/web/src/components/Developers/Verifications/gitcoin.svg b/apps/web/src/components/Developers/Verifications/gitcoin.svg new file mode 100644 index 00000000000..71301711ae6 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/gitcoin.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/web/src/components/Developers/Verifications/globe.svg b/apps/web/src/components/Developers/Verifications/globe.svg new file mode 100644 index 00000000000..3d0bd932459 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/globe.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/web/src/components/Developers/Verifications/icebreaker.svg b/apps/web/src/components/Developers/Verifications/icebreaker.svg new file mode 100644 index 00000000000..8eb959758a9 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/icebreaker.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/src/components/Developers/Verifications/identityCard.svg b/apps/web/src/components/Developers/Verifications/identityCard.svg new file mode 100644 index 00000000000..06fc4ad1d9d --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/identityCard.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/components/Developers/Verifications/key.svg b/apps/web/src/components/Developers/Verifications/key.svg new file mode 100644 index 00000000000..89474680454 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/key.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/components/Developers/Verifications/talent-protocol.svg b/apps/web/src/components/Developers/Verifications/talent-protocol.svg new file mode 100644 index 00000000000..2f9371db715 --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/talent-protocol.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/src/components/Developers/Verifications/verification.svg b/apps/web/src/components/Developers/Verifications/verification.svg new file mode 100644 index 00000000000..c6851e11a9f --- /dev/null +++ b/apps/web/src/components/Developers/Verifications/verification.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/web/src/components/base-org/Button/index.tsx b/apps/web/src/components/base-org/Button/index.tsx index 928a4c1dff3..313c7b29681 100644 --- a/apps/web/src/components/base-org/Button/index.tsx +++ b/apps/web/src/components/base-org/Button/index.tsx @@ -10,6 +10,7 @@ export type ButtonProps = ButtonHTMLAttributes & { variant?: ButtonVariants; size?: ButtonSizes; iconName?: IconProps['name']; + iconSize?: IconProps['width']; roundedFull?: boolean; fullWidth?: boolean; }; @@ -26,6 +27,9 @@ const variantStyles: Record = { // White outlined [ButtonVariants.Outlined]: 'bg-transparent text-white border border-white hover:bg-white hover:text-black active:bg-[#E3E7E9]', + + // Secondary Outlined + [ButtonVariants.SecondaryOutline]: 'bg-transparent border border-gray-muted hover:border-white', }; const sizeStyles: Record = { @@ -51,6 +55,7 @@ export default function Button({ variant = ButtonVariants.Primary, size = ButtonSizes.Medium, iconName, + iconSize = sizeIconRatio[size], roundedFull = false, className, fullWidth = false, @@ -82,8 +87,6 @@ export default function Button({ className, ); - const iconSize = sizeIconRatio[size]; - return (