diff --git a/package-lock.json b/package-lock.json index acc9dd8..e49167d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "react-transition-group": "^4.4.5", "sass": "^1.67.0", "swiper": "^8.4.7", + "use-debounce": "^10.0.1", "yup": "^1.2.0" }, "devDependencies": { @@ -1837,6 +1838,17 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/use-debounce": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.2.tgz", + "integrity": "sha512-MwBiJK2dk+2qhMDVDCPRPeLuIekKfH2t1UYMnrW9pwcJJGFDbTLliSMBz2UKGmE1PJs8l3XoMqbIU1MemMAJ8g==", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", diff --git a/public/img/trailblazer/banner-lg.png b/public/img/trailblazer/banner-lg.png new file mode 100644 index 0000000..d6a325a Binary files /dev/null and b/public/img/trailblazer/banner-lg.png differ diff --git a/public/img/trailblazer/banner-md.png b/public/img/trailblazer/banner-md.png new file mode 100644 index 0000000..5b05f69 Binary files /dev/null and b/public/img/trailblazer/banner-md.png differ diff --git a/public/img/trailblazer/banner-sm.png b/public/img/trailblazer/banner-sm.png new file mode 100644 index 0000000..8b2f226 Binary files /dev/null and b/public/img/trailblazer/banner-sm.png differ diff --git a/public/img/trailblazer/banner-xl.png b/public/img/trailblazer/banner-xl.png new file mode 100644 index 0000000..3da80db Binary files /dev/null and b/public/img/trailblazer/banner-xl.png differ diff --git a/public/img/trailblazer/icon.svg b/public/img/trailblazer/icon.svg new file mode 100644 index 0000000..516d329 --- /dev/null +++ b/public/img/trailblazer/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/locales/en/home.json b/public/locales/en/home.json index 4869273..dafacc9 100644 --- a/public/locales/en/home.json +++ b/public/locales/en/home.json @@ -1,111 +1,122 @@ { - "hero": { - "title": "a based rollup", - "text": "Inspired, secured, and sequenced by Ethereum", - "taiko": { - "is": "Taiko is:", - "value": "Permissionless", - "labels": [ - "Permissionless", - "Ethereum-equivalent", - "Open-source", - "based" - ] - }, - "startBuilding": "Start building", - "bridgeToTaiko": "Bridge to Taiko", - "scrollToExplore": "Scroll to explore" + "hero": { + "title": "a based rollup", + "text": "Inspired, secured, and sequenced by Ethereum", + "taiko": { + "is": "Taiko is:", + "value": "Permissionless", + "labels": [ + "Permissionless", + "Ethereum-equivalent", + "Open-source", + "based" + ] }, - "blog": { - "title": "Blog" - }, - "advantages": [ - { - "id": "aicon-seamless", - "icon": "aicon:seamless", - "title": "seamless UX", - "text": "Taiko is an Ethereum-equivalent (Type 1) ZK-EVM, maximally compatible with Ethereum. No additional compiling, reaudits, or tooling needed. Everything works out of the box, guaranteed.", - "colors": { - "icon": "#E81899", - "text": "#0B101B", - "background": "#EFEFEF" - } - }, { - "id": "aicon-community", - "icon": "aicon:community", - "title": "community-aligned", - "text": "We build with the support of our community and fully open-source. Meaning it's free to use and modify Taiko's source code with the permissive license.", - "colors": { - "icon": "#E81899", - "text": "#0B101B", - "background": "#FFE2A0" - } - }, { - "id": "aicon-security", - "icon": "aicon:security", - "title": "security-first", - "text": "Taiko demands no additional trust assumptions to Ethereum. As a based rollup with a permissionless (& decentralized) proposer/prover network from Day 1, Taiko inherits Ethereum's level of decentralization.", - "colors": { - "icon": "#FFFFFF", - "text": "#FFFFFF", - "background": "#E81899" - } - }, { - "id": "aicon-based", - "icon": "aicon:based", - "title": "based", - "text": "Taiko is a based rollup: the transaction sequencing on Taiko is done by Ethereum validators. Based sequencing is maximally simple and inherits Ethereum's liveness and credible neutrality.", - "colors": { - "icon": "#FFFFFF", - "text": "#FFFFFF", - "background": "#6321B6" - } - } - ], - "about": { - "suptitle": "About us", - "title": "Getting started with Taiko", - "text": "Taiko is compatible with Ethereum at the bytecode-level, meaning everything works right out of the box.", - "startBuilding": "Start building", - "list": [ - { - "icon": "about:ethereum", - "title": "Bridge your ETH", - "text": "You can bridge your ETH to Taiko using our native bridge or another ecosystem bridge. For a walkthrough, start with the user guide’s setup page." - }, { - "icon": "about:link", - "title": "Change RPC provider", - "text": "To configure your Ethereum tools to Taiko you'll just need to point your favorite builder tools to a Taiko RPC Provider." - }, { - "icon": "about:settings", - "title": "Build with your usual developer tools", - "text": "Start building with your favorite developer toolkit." - } - ] + "startBuilding": "Start building", + "bridgeToTaiko": "Bridge to Taiko", + "scrollToExplore": "Scroll to explore" + }, + "blog": { + "title": "Blog" + }, + "advantages": [ + { + "id": "aicon-seamless", + "icon": "aicon:seamless", + "title": "seamless UX", + "text": "Taiko is an Ethereum-equivalent (Type 1) ZK-EVM, maximally compatible with Ethereum. No additional compiling, reaudits, or tooling needed. Everything works out of the box, guaranteed.", + "colors": { + "icon": "#E81899", + "text": "#0B101B", + "background": "#EFEFEF" + } }, - "solutions": { - "solutions": "Our solutions", - "list": [ { - "title": "Based Contestable Rollups — a modular, multi-proof design", - "extraTitle": "a modular, multi-proof design", - "title_short": "Based Contestable Rollup", - "text": "Combining the best of optimistic and ZK-rollups to maximally reduce costs and increase decentralization.", - "icon": "laptop", - "iconLottie": "/img/laptop.json" - },{ - "title": "Based Booster Rollups — scale natively, compose synchronously", - "extraTitle": "scale natively, compose synchronously", - "title_short": "Based Booster Rollup", - "text": "Deploy on Ethereum and scale natively across all L2s.", - "icon": "rocket", - "iconLottie": "/img/rocket.json" - } - ] + { + "id": "aicon-community", + "icon": "aicon:community", + "title": "community-aligned", + "text": "We build with the support of our community and fully open-source. Meaning it's free to use and modify Taiko's source code with the permissive license.", + "colors": { + "icon": "#E81899", + "text": "#0B101B", + "background": "#FFE2A0" + } }, - "ecosystem": { - "title": "Explore \nour ecosystem", - "text": "Become part of an accessible, open and inclusive ecosystem driven by a shared mission — nurturing Ethereum's Infinite Garden.", - "exploreButton": "Explore the ecosystem", - "dapps": "DAPPS" + { + "id": "aicon-security", + "icon": "aicon:security", + "title": "security-first", + "text": "Taiko demands no additional trust assumptions to Ethereum. As a based rollup with a permissionless (& decentralized) proposer/prover network from Day 1, Taiko inherits Ethereum's level of decentralization.", + "colors": { + "icon": "#FFFFFF", + "text": "#FFFFFF", + "background": "#E81899" + } + }, + { + "id": "aicon-based", + "icon": "aicon:based", + "title": "based", + "text": "Taiko is a based rollup: the transaction sequencing on Taiko is done by Ethereum validators. Based sequencing is maximally simple and inherits Ethereum's liveness and credible neutrality.", + "colors": { + "icon": "#FFFFFF", + "text": "#FFFFFF", + "background": "#6321B6" + } } -} \ No newline at end of file + ], + "about": { + "suptitle": "About us", + "title": "Getting started with Taiko", + "text": "Taiko is compatible with Ethereum at the bytecode-level, meaning everything works right out of the box.", + "startBuilding": "Start building", + "list": [ + { + "icon": "about:ethereum", + "title": "Bridge your ETH", + "text": "You can bridge your ETH to Taiko using our native bridge or another ecosystem bridge. For a walkthrough, start with the user guide’s setup page." + }, + { + "icon": "about:link", + "title": "Change RPC provider", + "text": "To configure your Ethereum tools to Taiko you'll just need to point your favorite builder tools to a Taiko RPC Provider." + }, + { + "icon": "about:settings", + "title": "Build with your usual developer tools", + "text": "Start building with your favorite developer toolkit." + } + ] + }, + "solutions": { + "solutions": "Our solutions", + "list": [ + { + "title": "Based Contestable Rollups — a modular, multi-proof design", + "extraTitle": "a modular, multi-proof design", + "title_short": "Based Contestable Rollup", + "text": "Combining the best of optimistic and ZK-rollups to maximally reduce costs and increase decentralization.", + "icon": "laptop", + "iconLottie": "/img/laptop.json" + }, + { + "title": "Based Booster Rollups — scale natively, compose synchronously", + "extraTitle": "scale natively, compose synchronously", + "title_short": "Based Booster Rollup", + "text": "Deploy on Ethereum and scale natively across all L2s.", + "icon": "rocket", + "iconLottie": "/img/rocket.json" + } + ] + }, + "ecosystem": { + "title": "Explore \nour ecosystem", + "text": "Become part of an accessible, open and inclusive ecosystem driven by a shared mission — nurturing Ethereum's Infinite Garden.", + "exploreButton": "Explore the ecosystem", + "dapps": "DAPPS" + }, + "trailblazerBanner": { + "button": "Start your journey", + "text": "Embark on the Trailblazers Journey: Unleash your potential in the Taiko universe!" + } +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index b553bd1..1190a2e 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -4,72 +4,72 @@ import clsx from "clsx"; import { useTranslation } from "react-i18next"; import { Footer } from "widgets/footer"; import { Header } from "widgets/header"; -import * as HomeScreens from 'widgets/01-home-screens'; +import * as HomeScreens from "widgets/01-home-screens"; import MainLayout from "widgets/layouts/main-layout"; import { dehydrate, QueryClient } from "@tanstack/react-query"; import { HomeApiKeys } from "widgets/01-home-screens/lib/types"; import { blogApi } from "shared/lib/api"; import { Menu } from "widgets/menu"; -import css from './home.module.scss'; +import css from "./home.module.scss"; import { useEffect, useState } from "react"; import { exucuteOnReadyPage } from "shared/lib/utils/browser"; function Home() { - const [complete, setComplete] = useState(false); - const { t } = useTranslation('home'); + const [complete, setComplete] = useState(false); + const { t } = useTranslation("home"); - useEffect(() => exucuteOnReadyPage(() => setComplete(true)), []); - - return ( - - -
-
- - - } - children={} - /> - - - - - -
-
- - ); -} + useEffect(() => exucuteOnReadyPage(() => setComplete(true)), []); + + return ( + + +
+
+ + + } + children={} + /> + + + + + + +
+
+ + ); +} export default Home; export const getServerSideProps: GetServerSideProps = withTranslation( - async (context) => { - const queryClient = new QueryClient(); + async (context) => { + const queryClient = new QueryClient(); - await queryClient.prefetchQuery({ - queryKey: [HomeApiKeys.BLOG], - queryFn: () => blogApi.getAll() - }); + await queryClient.prefetchQuery({ + queryKey: [HomeApiKeys.BLOG], + queryFn: () => blogApi.getAll(), + }); - return { - props: { - dehydratedState: dehydrate(queryClient) - }, - } - }, - ["home"] -) \ No newline at end of file + return { + props: { + dehydratedState: dehydrate(queryClient), + }, + }; + }, + ["home"] +); diff --git a/src/shared/components/trailblazer/index.tsx b/src/shared/components/trailblazer/index.tsx new file mode 100644 index 0000000..aa77dcb --- /dev/null +++ b/src/shared/components/trailblazer/index.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import css from "./trailblazer.module.scss"; + +interface Props { + text: string; + icon: string; + button: React.ReactNode; + fullwidth?: boolean; +} + +export const TrailblazerBanner: React.FC = ({ + button, + text, + icon, + fullwidth, +}) => { + return ( +
+
+
+
+ Trailblazer +

{text}

+
{button}
+
+
+
+
+ ); +}; diff --git a/src/shared/components/trailblazer/trailblazer.module.scss b/src/shared/components/trailblazer/trailblazer.module.scss new file mode 100644 index 0000000..1089c94 --- /dev/null +++ b/src/shared/components/trailblazer/trailblazer.module.scss @@ -0,0 +1,154 @@ +.wrapper { + padding: 33px 35px; + border-radius: 32px; + border-width: 3px; + + display: flex; + align-items: center; + justify-content: center; + gap: 35px; + background-image: url("/img/trailblazer/banner-sm.png"); + width: 100%; + height: 650px; + background-size: cover; + background-position: center; + + .group { + justify-self: center; + padding: 0px; + display: flex; + flex-direction: column; + gap: 15px; + height: fit-content; + text-align: center; + align-items: center; + max-width: 247px; + align-self: flex-end; + // margin-top: auto; // This will push the group to the bottom + } + + .text { + max-width: 350px; + font: 500 16px/24px $kFontPublicSans; + letter-spacing: -0.01em; + color: #f3f3f3; + } + + .icon { + width: 26px; + height: 26px; + } + + // Small screens + @media screen and (min-width: 350px) { + padding: 10px; + background-image: url("/img/trailblazer/banner-sm.png"); + height: 650px; + justify-content: center; + background-position: center; + + .group { + justify-self: center; + padding: 0px; + display: flex; + flex-direction: column; + gap: 15px; + height: fit-content; + text-align: center; + align-items: center; + max-width: 247px; + align-self: flex-end; + // margin-top: auto; // This will push the group to the bottom + } + } + + // Medium screens + @media screen and (min-width: 580px) { + padding: 15px; + padding-right: 72px; + + background-image: url("/img/trailblazer/banner-md.png"); + height: 427px; + justify-content: flex-end; + + .group { + padding-top: 20px; + display: flex; + flex-direction: column; + gap: 15px; + height: fit-content; + text-align: left; + align-items: flex-start; + max-width: 247px; + // align-self: flex-end; + justify-self: flex-end; + align-self: center; + } + } + + // Large screens + @media screen and (min-width: 874px) { + padding: 20px; + padding-right: 60px; + + background-image: url("/img/trailblazer/banner-lg.png"); + height: 296px; + + justify-content: flex-end; + + .group { + padding: 0px; + display: flex; + flex-direction: column; + gap: 15px; + height: fit-content; + text-align: left; + align-items: flex-start; + max-width: 247px; + // align-self: flex-end; + justify-self: flex-end; + align-self: center; + } + } + + // Extra large screens + @media screen and (min-width: 1472px) { + padding: 25px; + background-image: url("/img/trailblazer/banner-xl.png"); + height: 250px; + + align-items: center; + justify-content: flex-end; + + .group { + padding: 0px; + + display: flex; + flex-direction: column; + gap: 15px; + height: fit-content; + max-width: 247px; + align-self: center; + } + } + + // Extra large screens + @media screen and (min-width: $kLaptopM) { + padding: 25px; + padding-right: 89px; + background-image: url("/img/trailblazer/banner-xl.png"); + height: 250px; + + align-items: center; + justify-content: flex-end; + + .group { + padding: 0px; + display: flex; + flex-direction: column; + gap: 15px; + max-width: 247px; + align-self: center; + } + } +} diff --git a/src/widgets/01-home-screens/lib/types.ts b/src/widgets/01-home-screens/lib/types.ts index d5e8594..6416372 100644 --- a/src/widgets/01-home-screens/lib/types.ts +++ b/src/widgets/01-home-screens/lib/types.ts @@ -1,40 +1,41 @@ export enum HomeScreensEnum { - HERO = "hero", - ADVANTAGES = "advantages", - ABOUT = "about", - SOLUTIONS = "solutions", - ECOSYSTEM = "ecosystem", - COMMUNITY = "community", - BLOG = "blog", + HERO = "hero", + ADVANTAGES = "advantages", + ABOUT = "about", + SOLUTIONS = "solutions", + ECOSYSTEM = "ecosystem", + COMMUNITY = "community", + BLOG = "blog", + TRAILBLAZER = "trailblazer", } export enum HomeApiKeys { - BLOG = "blogs-list" + BLOG = "blogs-list", } export interface IHomeAdvantage { - id: string; + id: string; + icon: string; + title: string; + text: string; + colors: { icon: string; - title: string; text: string; - colors: { - icon: string; - text: string; - background: string; - } + background: string; + }; } export interface IHomeAbout { - icon: string; - title: string; - text: string; + icon: string; + title: string; + text: string; } export interface IHomeSolution { - title: string; - extraTitle: string; - title_short: string; - text: string; - icon: string; - iconLottie: string; -} \ No newline at end of file + title: string; + extraTitle: string; + title_short: string; + text: string; + icon: string; + iconLottie: string; +} diff --git a/src/widgets/01-home-screens/ui/04-solutions/index.tsx b/src/widgets/01-home-screens/ui/04-solutions/index.tsx index 536ae85..2c7decf 100644 --- a/src/widgets/01-home-screens/ui/04-solutions/index.tsx +++ b/src/widgets/01-home-screens/ui/04-solutions/index.tsx @@ -1,115 +1,112 @@ -import clsx from 'clsx'; -import { useTranslation } from 'next-i18next'; -import React, { useState } from 'react'; -import { Button } from 'shared/components/@buttons/button'; -import { useTranslationObject } from 'shared/lib/hooks/use-translation-object'; -import { MediaQuery } from 'shared/ui/media-query'; -import { HomeScreensEnum, IHomeSolution } from 'widgets/01-home-screens/lib/types'; -import css from './solutions.module.scss'; -import { Player } from '@lottiefiles/react-lottie-player'; +import clsx from "clsx"; +import { useTranslation } from "next-i18next"; +import React, { useState } from "react"; +import { Button } from "shared/components/@buttons/button"; +import { useTranslationObject } from "shared/lib/hooks/use-translation-object"; +import { MediaQuery } from "shared/ui/media-query"; +import { + HomeScreensEnum, + IHomeSolution, +} from "widgets/01-home-screens/lib/types"; +import css from "./solutions.module.scss"; +import { Player } from "@lottiefiles/react-lottie-player"; const Solutions: React.FC = () => { - const solutions = useTranslationObject('solutions.list', 'home'); - const { t } = useTranslation('home'); - const [activeSolution, setActiveSolution] = useState(solutions[0]); - - return ( -
-
-
+ const solutions = useTranslationObject( + "solutions.list", + "home" + ); + const { t } = useTranslation("home"); + const [activeSolution, setActiveSolution] = useState(solutions[0]); - -

- {t('solutions.solutions')} -

+ return ( +
+
+
+ +

{t("solutions.solutions")}

-

- {activeSolution.title_short} – {activeSolution.extraTitle} -

+

+ {activeSolution.title_short} –{" "} + {activeSolution.extraTitle} +

-
-

- {activeSolution.text} -

-
+
+

{activeSolution.text}

+
-
-
-
- } - /> +
+
+
+ } + /> -
    - {solutions.map((solution, id) => ( -
  • setActiveSolution(solution)} - key={solution.title} - > -
    -
    - +
      + {solutions.map((solution, id) => ( +
    • setActiveSolution(solution)} + key={solution.title} + > +
      +
      + -

      - {(id + 1).toString().padStart(2, '0')} -

      -
      +

      + {(id + 1).toString().padStart(2, "0")} +

      +
      -

      - {solution.title_short}} - /> - {solution.title_short} – {solution.extraTitle}} - /> -

      +

      + {solution.title_short}} + /> + + {solution.title_short} –{" "} + {solution.extraTitle} + + } + /> +

      - - - {solution.text} -

      - } - /> -
    -
  • - ))} -
+ {solution.text}

} + />
-
-
- ); -} + + ))} + + + + + ); +}; -export default Solutions; \ No newline at end of file +export default Solutions; diff --git a/src/widgets/01-home-screens/ui/08-trailblazer/index.tsx b/src/widgets/01-home-screens/ui/08-trailblazer/index.tsx new file mode 100644 index 0000000..4c59128 --- /dev/null +++ b/src/widgets/01-home-screens/ui/08-trailblazer/index.tsx @@ -0,0 +1,33 @@ +import { useTranslation } from "next-i18next"; +import React from "react"; +import { HomeScreensEnum } from "widgets/01-home-screens/lib/types"; +import css from "./trailblazer.module.scss"; +import { TrailblazerBanner } from "shared/components/trailblazer"; +import { Button } from "shared/components/@buttons/button"; + +const Trailblazer: React.FC = () => { + const { t } = useTranslation("home"); + + return ( +
+
+ + } + fullwidth + /> +
+
+ ); +}; + +export default Trailblazer; diff --git a/src/widgets/01-home-screens/ui/08-trailblazer/trailblazer.module.scss b/src/widgets/01-home-screens/ui/08-trailblazer/trailblazer.module.scss new file mode 100644 index 0000000..ef41d36 --- /dev/null +++ b/src/widgets/01-home-screens/ui/08-trailblazer/trailblazer.module.scss @@ -0,0 +1,10 @@ +.trailblazer { + // Default styles + padding: 20px; +} + +.group { + display: flex; + flex-direction: column; + gap: 20px; +} diff --git a/src/widgets/01-home-screens/ui/index.ts b/src/widgets/01-home-screens/ui/index.ts index 83079b0..8420c4a 100644 --- a/src/widgets/01-home-screens/ui/index.ts +++ b/src/widgets/01-home-screens/ui/index.ts @@ -1,9 +1,10 @@ -export { default as Hero } from './01-hero'; -export { default as Advantages } from './03-advantages'; -export { default as About } from './02-about'; -export { default as Solutions } from './04-solutions'; -export { default as Ecosystem } from './05-ecosystem'; -export { default as Community } from './06-community'; -export { default as Blog } from './07-blog'; -export { default as StickyContent } from './sticky-content'; -export { default as GradientFill } from './gradient-fill'; \ No newline at end of file +export { default as Hero } from "./01-hero"; +export { default as Advantages } from "./03-advantages"; +export { default as About } from "./02-about"; +export { default as Solutions } from "./04-solutions"; +export { default as Ecosystem } from "./05-ecosystem"; +export { default as Community } from "./06-community"; +export { default as Blog } from "./07-blog"; +export { default as Trailblazer } from "./08-trailblazer"; +export { default as StickyContent } from "./sticky-content"; +export { default as GradientFill } from "./gradient-fill";