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): testimonials + bridge now sections #17

Merged
merged 25 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
12 changes: 11 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "pbs.twimg.com",
pathname: "**",
},
],
},
Comment on lines +4 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

};

export default nextConfig;
31 changes: 31 additions & 0 deletions src/app/(routes)/across-bridge/_components/bridge-now-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Image from "next/image";

import { Text } from "@/app/_components/text";
import { BridgeNowLink } from "@/app/_components/bridge-now-link";
import { Button } from "@/app/_components/button";
import bridgeHeroImage from "@/app/_assets/bridge-hero.png";

export function BridgeNowSection() {
return (
<section className="container mx-auto flex flex-col items-center gap-16 sm:gap-24">
<Image
src={bridgeHeroImage}
alt="screenshot of bridge ui"
className=" max-w-[357px]"
/>
<Text
variant="heading-1"
className="text-center capitalize text-light-100 md:tracking-tight-1"
>
experience the bridge
</Text>
<div className="flex flex-row items-center">
<BridgeNowLink>
<Button className="border-aqua-100 bg-aqua-100/[.05] text-aqua-100">
<Text variant="cap-case-sm">Bridge now</Text>
</Button>
</BridgeNowLink>
</div>
</section>
);
}
273 changes: 273 additions & 0 deletions src/app/(routes)/across-bridge/_components/testimonials-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
"use client";

import Image from "next/image";
import { useState } from "react";

import { TwitterIcon, VerifiedCheckmarkIcon } from "@/app/_components/icons";
import { Text } from "@/app/_components/text";
import { twMerge } from "@/app/_lib/tw-merge";

const mainTweet = {
title: (
<>
Lowest fees, Zero slippage,
<br />
professional team.
</>
),
body: (
<>
&apos;I&apos;ve tried every L2 bridge out there. @AcrossProtocol is undoubtedly the
best one.
<br />
<br />
Lowest fees, 0 slippage, professional team. Very under-appreciated, use it.&apos;
</>
),
username: "@aradtski",
};

const tweets = {
firstColumn: [
{
isVerified: true,
displayName: "pray.eth",
username: "@pray_eth",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1692052698307153920/WiHp_6vw_200x200.jpg",
tweet: (
<>
Yeah, I bridge a lot, noticed @BungeeExchange routes were giving me
@AcrossProtocol most of the time, so just started to use it as my default bridge
(minimizing risk is my primary concern when bridging).
<br />
<br />
Transfers are incredibly fast and cheap. Great work!
</>
),
Comment on lines +39 to +47
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'm not a huge fan of having markdown for each individual tweet. Not sure if there's a better solution, but it feels like it may be unwieldy if we increase the number of tweets.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I am also not a big fan of this. But that's the best I could come up with. Especially with the Twitter API being highly limited (free version at least)

tweetUrl: "https://x.com/pray_eth/status/1679328596261842944?s=20",
},
{
isVerified: false,
displayName: "David Goose",
username: "@davidjgoosey",
tweetUrl: "https://x.com/davidjgoosey/status/1649207665518690304?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1594113194397687816/l2RGYB8y_200x200.jpg",
tweet: (
<>
Across has one of the best UX of the bridges I&apos;ve tried to date, keep up
the good work
</>
),
},
{
isVerified: true,
displayName: "Scott BurkΞ",
username: "@scottburke777",
tweetUrl: "https://x.com/scottburke777/status/1656557680012476416?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1618111203586314240/obBfZyuv_200x200.jpg",
tweet: (
<>
Tried a few Arbitrum bridges over the last few months, just tried
@AcrossProtocol and it was the fastest yet, it was like 1 min Eth -&gt; Arb
</>
),
},
{
isVerified: true,
displayName: "kidponga.eth",
username: "@kidponga",
tweetUrl: "https://x.com/Infinity_1001/status/1749523278228521112?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1692052698307153920/WiHp_6vw_200x200.jpg",
tweet: (
<>
What&apos;s the best bridge in crypto?
<br />
<br />A bridge that focuses on what users want the most:
<br />- speed
<br />- cost
<br />- trust
<br />
<br />
@AcrossProtocol $ACX
</>
),
},
{
isVerified: true,
displayName: "Kisuke Urahara",
username: "@Ivan90403291",
tweetUrl: "https://x.com/Ivan90403291/status/1692120646602391671?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1255439408100265984/JjHosYHZ_200x200.jpg",
tweet: <>@AcrossProtocol is 100% the best bridge</>,
},
],
secondColumn: [
{
isVerified: false,
displayName: "maxlomu",
username: "@maxlomu",
tweetUrl: "https://x.com/maxlomu/status/1675975309835882502?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1620485487466094602/oAWikXJe_200x200.jpg",
tweet: (
<>
Honestly well done guys.
<br />
<br />
Not only Across liquidity model is very capital efficient (so you can be
cheaper), but the architecture (contrary to L0) is actually trust-minimized.
</>
),
},
{
isVerified: true,
displayName: "Andy",
username: "@ayyyeandy",
tweetUrl: "https://x.com/ayyyeandy/status/1726985723285553249?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1687521808331702272/Ky0QmeqD_200x200.jpg",
tweet: (
<>
Lol. One second to bridge from @arbitrum to @zksync using @AcrossProtocol
<br />
<br />
<Image
height={242}
width={302}
alt="Across bridge ui"
src="https://pbs.twimg.com/media/F_d8Rl1XoAA4N8S?format=jpg"
/>
</>
),
},
{
isVerified: false,
displayName: "Infinity",
username: "@Infinity_1001",
// TODO: update tweet url
tweetUrl: "https://x.com/kidponga/status/1750013537379111135?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1687521808331702272/Ky0QmeqD_200x200.jpg",
tweet: (
<>
Across is without a doubt the best bridge you can use today.
<br />
<br />
It is the fastest, most efficient and safest
<br />
<br />
Not because I say so, the statistics support it
</>
),
},
{
isVerified: false,
displayName: "jaeger 狼",
username: "@carlshuu",
tweetUrl: "https://x.com/carlshuu/status/1742052941480255592?s=20",
profileImageUrl:
"https://pbs.twimg.com/profile_images/1737090443962413056/aHv5T66J_200x200.jpg",
tweet: (
<>
@AcrossProtocol is so freaking good. It&apos;s insane how fast their bridge is.
</>
),
},
],
};

export function TestimonialsSection() {
const [isExpanded, setIsExpanded] = useState(false);
return (
<section className="container mx-auto">
<div className="relative">
<div className="flex flex-col items-center gap-6">
<Text variant="cap-case" className="text-aqua-100">
across users say it all
</Text>
<Text variant="heading-2" className="text-center capitalize text-light-200">
&quot;{mainTweet.title}&quot;
</Text>
<Text
variant="body"
className="max-w-[336px] text-center text-md text-light-300 md:text-lg"
>
{mainTweet.body}
</Text>
<div className="flex h-10 w-40 flex-row items-center justify-between gap-2 rounded-full border border-aqua-100/[.05] bg-aqua-100/[.05] px-4 py-2">
<Text className="flex-1 text-center text-aqua-100">{mainTweet.username}</Text>
<TwitterIcon className="h-3 w-3 fill-aqua-100" />
</div>
<div
className={twMerge(
"flex flex-col gap-4 overflow-hidden sm:flex-row md:gap-8",
isExpanded ? "" : "h-[480px]",
)}
>
<div className="flex flex-1 flex-col gap-4">
{tweets.firstColumn.map((tweet, index) => (
<TweetCard key={index} tweet={tweet} />
))}
</div>
<div className="flex flex-1 flex-col gap-4">
{tweets.secondColumn.map((tweet, index) => (
<TweetCard key={index} tweet={tweet} />
))}
</div>
</div>
</div>
{!isExpanded && (
<div className="absolute bottom-0 h-24 w-full bg-gradient-to-t from-grey-dark to-transparent" />
)}
</div>
{!isExpanded && (
<div className="mt-4 flex flex-row justify-center">
<button
className="flex rounded-full bg-light-100/[.05] px-4 py-2 hover:opacity-75"
onClick={() => setIsExpanded(true)}
>
<Text variant="body-nums" className="text-grey-400">
View more Tweets
</Text>
</button>
</div>
)}
</section>
);
}

function TweetCard({ tweet }: { tweet: (typeof tweets.firstColumn)[0] }) {
return (
<a className="group" href={tweet.tweetUrl} target="_blank" rel="noopener noreferrer">
<div className="flex cursor-pointer flex-col gap-4 rounded-3xl border border-black-700 p-5 transition group-hover:border-aqua-100/[.05] group-hover:bg-aqua-100/[.05] sm:p-6">
<div className="flex flex-row items-center gap-3">
<div className="h-10 w-10 overflow-hidden rounded-full">
<Image
src={tweet.profileImageUrl}
alt={`${tweet.displayName} profile picture`}
width={40}
height={40}
/>
</div>
<div className="flex flex-col">
<div className="flex flex-row items-center gap-1">
<Text variant="body" className="text-aqua-100">
{tweet.displayName}
</Text>
{tweet.isVerified && <VerifiedCheckmarkIcon />}
</div>
<Text variant="body" className=" text-grey-400">
{tweet.username}
</Text>
</div>
</div>
<Text variant="body">{tweet.tweet}</Text>
</div>
</a>
);
}
4 changes: 4 additions & 0 deletions src/app/(routes)/across-bridge/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Metadata } from "next";

import { HeroSection } from "./_components/hero-section";
import { FeaturesSection } from "./_components/features-section";
import { TestimonialsSection } from "./_components/testimonials-section";
import { BridgeNowSection } from "./_components/bridge-now-section";

export const metadata: Metadata = {
title: "Across Bridge",
Expand All @@ -13,6 +15,8 @@ export default function BridgeLanding() {
<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 />
<TestimonialsSection />
<BridgeNowSection />
</main>
);
}
1 change: 1 addition & 0 deletions src/app/_components/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export { Partner1Icon } from "./partner-1";
export { ArrowRightIcon } from "./arrow-right";
export { ArrowUpRightIcon } from "./arrow-up-right";
export { ArrowUpRightThickIcon } from "./arrow-up-right-thick";
export { VerifiedCheckmarkIcon } from "./verified-checkmark";

// Gradient icons
export { ArrowUpIcon } from "./gradient/arrow-up";
Expand Down
10 changes: 5 additions & 5 deletions src/app/_components/icons/twitter.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { SVGProps } from "react";

export function TwitterIcon(props: SVGProps<SVGSVGElement>) {
import { twMerge } from "@/app/_lib/tw-merge";

export function TwitterIcon({ className, ...props }: SVGProps<SVGSVGElement>) {
return (
<svg
width="17"
height="16"
viewBox="0 0 17 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={twMerge("fill-light-100", className)}
{...props}
>
<g clipPath="url(#clip0_564_8220)">
<path
d="M10.0237 6.77615L15.9811 0.000488281H14.5699L9.39493 5.8825L5.2648 0.000488281H0.5L6.74693 8.89598L0.5 16.0004H1.9112L7.37253 9.7875L11.7352 16.0004H16.5M2.42053 1.04175H4.58853L14.5688 15.0103H12.4003"
fill="white"
/>
<path d="M10.0237 6.77615L15.9811 0.000488281H14.5699L9.39493 5.8825L5.2648 0.000488281H0.5L6.74693 8.89598L0.5 16.0004H1.9112L7.37253 9.7875L11.7352 16.0004H16.5M2.42053 1.04175H4.58853L14.5688 15.0103H12.4003" />
</g>
<defs>
<clipPath id="clip0_564_8220">
Expand Down
19 changes: 19 additions & 0 deletions src/app/_components/icons/verified-checkmark.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { SVGProps } from "react";

export function VerifiedCheckmarkIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M14.8346 8.00008C14.8346 7.04675 14.248 6.22008 13.3746 5.77341C13.6813 4.84675 13.508 3.84008 12.8346 3.16675C12.1613 2.49341 11.1546 2.32008 10.228 2.62675C9.78797 1.75341 8.95464 1.16675 8.0013 1.16675C7.04797 1.16675 6.2213 1.75341 5.7813 2.62675C4.84797 2.32008 3.8413 2.49341 3.16797 3.16675C2.49464 3.84008 2.32797 4.84675 2.63464 5.77341C1.7613 6.22008 1.16797 7.04675 1.16797 8.00008C1.16797 8.95341 1.7613 9.78008 2.63464 10.2267C2.32797 11.1534 2.49464 12.1601 3.16797 12.8334C3.8413 13.5067 4.84797 13.6734 5.77463 13.3734C6.2213 14.2467 7.04797 14.8334 8.0013 14.8334C8.95464 14.8334 9.78797 14.2467 10.228 13.3734C11.1546 13.6734 12.1613 13.5067 12.8346 12.8334C13.508 12.1601 13.6813 11.1534 13.3746 10.2267C14.248 9.78008 14.8346 8.95341 14.8346 8.00008ZM7.02797 10.8001L4.53464 8.30675L5.47464 7.36008L6.9813 8.86675L10.1813 5.38008L11.1613 6.28675L7.02797 10.8001Z"
fill="#6CF9D8"
/>
</svg>
);
}
Loading
Loading