Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bridge): hero + features sections #15

Merged
merged 24 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/app/(routes)/across-bridge/_components/features-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import Image from "next/image";

import {
CodeIcon,
ShieldLargeIcon,
DoubleChevronRightIcon,
DollarIcon,
} from "@/app/_components/icons";
import { Text } from "@/app/_components/text";
import { FeaturesGrid } from "@/app/_components/features-grid";
import bridge2Image from "@/app/_assets/bridge-2.png";

const features = [
{
Icon: <CodeIcon className="h-14 w-14" />,
title: "efficient",
body: "With Across, bridging your tokens at the fastest speed and lowest cost does not come with security tradeoffs. How? At Across, only bridge users or bridge LPs never shoulder the risks associated with cross-chain transfers.",
},
{
Icon: <ShieldLargeIcon className="h-14 w-14" />,
title: "Secure",
body: "Using canonical assets is the only trustless way to transfer value, which is why Across only circulates genuine tokens, never representative or synthetic assets. In every transfer facilitated by Across, user assets are never put at risk.",
},
{
Icon: <DoubleChevronRightIcon className="h-14 w-14" />,
title: "Fast",
body: "Intents architecture enables the fastest bridge experience. By using a network of third party relayers, incentivized to quickly fill transfers, fill times are usually completed in a few seconds.",
},
{
Icon: <DollarIcon className="h-14 w-14" />,
title: "Superior",
body: "Canonical assets are the only trustless way to transfer value, which is why Across only circulates canonical tokens, never representative or synthetic ones. In every transfer at Across, users always receive canonical assets.",
},
];

export function FeaturesSection() {
return (
<section className="container mx-auto -mt-32 flex flex-col gap-16 px-4 sm:gap-24 md:-mt-48">
<Image
src={bridge2Image}
alt="Across settlement layers graphic"
className="-mb-16 self-center sm:-mb-24 sm:max-w-[514px]"
/>
<div className="flex flex-col gap-4">
<Text variant="cap-case" className="text-center text-aqua-100">
built for safe travels
</Text>
<Text variant="heading-2" className="text-center capitalize text-light-200">
Engineered for best execution
</Text>
</div>
<FeaturesGrid features={features} />
</section>
);
}
42 changes: 42 additions & 0 deletions src/app/(routes)/across-bridge/_components/hero-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Image from "next/image";

import { Hero } from "@/app/_components/hero";
import { Text } from "@/app/_components/text";
import { BridgeNowLink } from "@/app/_components/bridge-now-link";
import { ArrowRightIcon } from "@/app/_components/icons/arrow-right";
import bridgeHeroImage from "@/app/_assets/bridge-hero.png";

export function HeroSection() {
return (
<Hero title="supported chains">
<div className="container mx-auto flex flex-col items-center gap-16 px-4 pb-16 pt-8 md:flex-row-reverse md:gap-8 md:pt-16">
<div className="flex max-w-80 flex-1 sm:max-w-100 md:max-w-full">
<Image src={bridgeHeroImage} alt="Across bridge ui" priority={true} />
</div>
<div className="flex flex-1 flex-col gap-6">
<Text
variant="heading-1"
className="text-center tracking-tight-5 sm:tracking-tight-2 md:text-left md:tracking-tight-1"
>
<span className="text-aqua-100">Bridge</span>{" "}
<span className="text-light-100">Without</span>{" "}
<br className="block sm:hidden md:block" />
<span className="text-aqua-100">Compromise</span>
</Text>
<div className="flex w-full flex-row justify-center md:justify-start">
<Text variant="body-nums" className="max-w-[430px] text-center md:text-left">
Experience extraordinarily fast and cost-effective cross-chain bridging,
secured by an intents-based architecture.
</Text>
</div>
<BridgeNowLink className="flex cursor-pointer flex-row items-center justify-center gap-2 text-aqua-100 md:justify-start">
<Text variant="cap-case">bridge now</Text>
<div className="flex h-5 w-5 items-center justify-center rounded-full bg-aqua-100">
<ArrowRightIcon />
</div>
</BridgeNowLink>
</div>
</div>
</Hero>
);
}
8 changes: 6 additions & 2 deletions src/app/(routes)/across-bridge/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { Metadata } from "next";

import { HeroSection } from "./_components/hero-section";
import { FeaturesSection } from "./_components/features-section";

export const metadata: Metadata = {
title: "Across Bridge",
description: "Interoperability powered by Intents.",
};

export default function BridgeLanding() {
return (
<main className="z-0 min-h-screen overflow-hidden">
<div className="py-10 text-center">Across Bridge</div>
<main className="z-0 mb-24 flex min-h-screen flex-col gap-24 overflow-hidden px-4 sm:gap-32 md:gap-48">
<HeroSection />
<FeaturesSection />
</main>
);
}
14 changes: 3 additions & 11 deletions src/app/(routes)/across-plus/_components/features-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ArrowUpRightThickIcon,
} from "@/app/_components/icons";
import { Text } from "@/app/_components/text";
import { FeaturesGrid } from "@/app/_components/features-grid";
import { INFORMATION_LINKS } from "@/app/_constants";

const features = [
Expand Down Expand Up @@ -42,16 +43,7 @@ export function FeaturesSection() {
Seamless Cross-chain Onboarding
</Text>
</div>
<div className="grid grid-cols-1 gap-12 sm:gap-y-16 md:grid-cols-2">
{features.map((feature) => (
<div key={feature.title}>
{feature.Icon}
<Text variant="heading-4" className="mb-4 mt-8 capitalize text-light-200">
{feature.title}
</Text>
<Text className="max-w-[520px] text-light-300">{feature.body}</Text>
</div>
))}
<FeaturesGrid features={features}>
<div className="flex flex-col items-center gap-8 rounded-2xl bg-teal-100/[.02] p-6 shadow-md sm:items-start">
<div className="flex flex-col items-center justify-center self-center rounded-lg bg-teal-100/[.05] p-2">
<Text variant="cap-case" className="text-teal-100">
Expand All @@ -78,7 +70,7 @@ export function FeaturesSection() {
</a>
</div>
</div>
</div>
</FeaturesGrid>
</section>
);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Image from "next/image";

import {
BlocksConnectedIcon,
ChecklistIcon,
CheckmarkIcon,
CrossChainIcon,
} from "@/app/_components/icons";
import { Text } from "@/app/_components/text";
import { FeaturesGrid } from "@/app/_components/features-grid";
import settlement2Image from "@/app/_assets/settlement-2.png";
import Image from "next/image";

const features = [
{
Expand Down Expand Up @@ -49,17 +51,7 @@ export function FeaturesSection() {
Best Execution
</Text>
</div>
<div className="grid grid-cols-1 gap-12 sm:gap-y-16 md:grid-cols-2">
{features.map((feature) => (
<div key={feature.title}>
{feature.Icon}
<Text variant="heading-4" className="mb-4 mt-8 capitalize text-light-200">
{feature.title}
</Text>
<Text className="max-w-100 text-light-300">{feature.body}</Text>
</div>
))}
</div>
<FeaturesGrid features={features} />
</section>
);
}
Binary file added src/app/_assets/bridge-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/app/_assets/bridge-hero.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions src/app/_components/bridge-now-link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import { useSearchParams } from "next/navigation";
import { Suspense } from "react";

type Props = React.ComponentProps<"a">;

const bridgeAppBaseUrl = "https://app.across.to";

export function BridgeNowLink(props: Props) {
return (
<Suspense>
<_BridgeNowLink {...props} />
</Suspense>
);
}

function _BridgeNowLink({ className, ...props }: Props) {
const searchParams = useSearchParams();

const refParams = searchParams.get("ref") || searchParams.get("referrer");
const bridgeNowLink = `${bridgeAppBaseUrl}/bridge${refParams ? `?ref=${refParams}` : ""}`;

return (
<a
className={className}
href={bridgeNowLink}
target="_blank"
rel="noopener noreferrer"
{...props}
/>
);
}
33 changes: 33 additions & 0 deletions src/app/_components/features-grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { twMerge } from "tailwind-merge";

import { Text } from "./text";

type Feature = {
title: string;
body: string;
Icon: React.ReactNode;
};

type Props = React.ComponentProps<"div"> & {
features: Feature[];
};

export function FeaturesGrid({ className, features, children, ...props }: Props) {
return (
<div
className={twMerge("grid grid-cols-1 gap-12 sm:gap-y-16 md:grid-cols-2", className)}
{...props}
>
{features.map((feature) => (
<div key={feature.title}>
{feature.Icon}
<Text variant="heading-4" className="mb-4 mt-8 capitalize text-light-200">
{feature.title}
</Text>
<Text className="max-w-100 text-light-300">{feature.body}</Text>
</div>
))}
{children}
</div>
);
}
2 changes: 1 addition & 1 deletion src/app/_components/get-started-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function GetStartedSection(props: {
target="_blank"
rel="noopener noreferrer"
className={twJoin(
"flex h-10 flex-col items-center justify-center rounded-full px-6 py-2 shadow-sm",
"flex flex-col items-center justify-center rounded-full px-6 py-2 shadow-sm",
variants[props.variant].opacityBgClassName,
)}
>
Expand Down
30 changes: 17 additions & 13 deletions src/app/_components/header-nav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState } from "react";

import { twMerge } from "@/app/_lib/tw-merge";
import { PRODUCT_LINKS, SOCIAL_LINKS } from "@/app/_constants";

import {
AcrossIcon,
Expand All @@ -18,7 +20,7 @@ import {
} from "../icons";
import { Button } from "../button";
import { Text } from "../text";
import { PRODUCT_LINKS, SOCIAL_LINKS } from "@/app/_constants";
import { BridgeNowLink } from "../bridge-now-link";

import { FlyoutMenu } from "./flyout-menu";
import { MobileMenu } from "./mobile-menu";
Expand Down Expand Up @@ -108,18 +110,20 @@ export function HeaderNav() {
</div>
</div>
<div className="flex flex-row gap-3">
<Button
className={twMerge(
"hidden transition md:block",
pathname === "/across-plus"
? "border-teal-100 bg-teal-100/[.05] text-teal-100"
: pathname === "/across-settlement"
? "border-purple-100 bg-purple-100/[.05] text-purple-100"
: "border-aqua-100 bg-aqua-100/[.05] text-aqua-100",
)}
>
<Text variant="cap-case-sm">Bridge now</Text>
</Button>
<BridgeNowLink>
<Button
className={twMerge(
"hidden transition md:block",
pathname === "/across-plus"
? "border-teal-100 bg-teal-100/[.05] text-teal-100"
: pathname === "/across-settlement"
? "border-purple-100 bg-purple-100/[.05] text-purple-100"
: "border-aqua-100 bg-aqua-100/[.05] text-aqua-100",
)}
>
<Text variant="cap-case-sm">Bridge now</Text>
</Button>
</BridgeNowLink>
{/* Only show menu button on mobile */}
<button
className="flex h-10 w-10 items-center justify-center rounded-full border border-grey-600 md:hidden"
Expand Down
28 changes: 16 additions & 12 deletions src/app/_components/header-nav/mobile-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Transition } from "@headlessui/react";
import { UmaIcon } from "../icons";
import { Button } from "../button";
import { IconBox } from "../icon-box";
import { BridgeNowLink } from "../bridge-now-link";
import { Text } from "../text";

import { NavItem } from "./types";

Expand All @@ -28,18 +30,20 @@ export function MobileMenu(props: {
show={props.isMenuOpen}
>
<div className="absolute flex min-h-screen w-full flex-col gap-6 bg-grey-dark p-4 md:hidden">
<Button
className={twMerge(
"md:hidden",
props.pathname === "/across-plus"
? "border-teal-100/[.05] bg-teal-100/[.05] text-teal-100"
: props.pathname === "/across-settlement"
? "border-purple-100/[.05] bg-purple-100/[.05] text-purple-100"
: "",
)}
>
Bridge now
</Button>
<BridgeNowLink className="flex w-full flex-row">
<Button
className={twMerge(
"w-full",
props.pathname === "/across-plus"
? "border-teal-100 bg-teal-100/[.05] text-teal-100"
: props.pathname === "/across-settlement"
? "border-purple-100 bg-purple-100/[.05] text-purple-100"
: "border-aqua-100 bg-aqua-100/[.05] text-aqua-100",
)}
>
<Text variant="cap-case-sm">Bridge now</Text>
</Button>
</BridgeNowLink>
{props.productsNavItems.map((item) => (
<span key={item.href} className="group">
<Link
Expand Down
7 changes: 4 additions & 3 deletions src/app/_components/icons/gradient/double-chevron-right.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { SVGProps } from "react";
import { twMerge } from "@/app/_lib/tw-merge";

export function DoubleChevronRightIcon(props: SVGProps<SVGSVGElement>) {
export function DoubleChevronRightIcon({ className, ...props }: SVGProps<SVGSVGElement>) {
return (
<svg
width="96"
height="96"
viewBox="0 0 96 96"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={twMerge("h-12 w-12", className)}
{...props}
>
<rect
opacity="0.5"
Expand Down
Loading