diff --git a/src/assets/images/token/base.webp b/src/assets/images/token/base.webp new file mode 100644 index 00000000..1318ee88 Binary files /dev/null and b/src/assets/images/token/base.webp differ diff --git a/src/assets/images/token/dex-screener.png b/src/assets/images/token/dex-screener.png new file mode 100644 index 00000000..c35f05e8 Binary files /dev/null and b/src/assets/images/token/dex-screener.png differ diff --git a/src/assets/images/token/joystream.webp b/src/assets/images/token/joystream.webp new file mode 100644 index 00000000..98c54916 Binary files /dev/null and b/src/assets/images/token/joystream.webp differ diff --git a/src/assets/images/token/uniswap.webp b/src/assets/images/token/uniswap.webp new file mode 100644 index 00000000..4aa59b67 Binary files /dev/null and b/src/assets/images/token/uniswap.webp differ diff --git a/src/assets/svg/copy.svg b/src/assets/svg/copy.svg new file mode 100644 index 00000000..7bf1f4ea --- /dev/null +++ b/src/assets/svg/copy.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/components/token-page/Exchanges/index.js b/src/components/token-page/Exchanges/index.js index 36acab4e..033ac19c 100644 --- a/src/components/token-page/Exchanges/index.js +++ b/src/components/token-page/Exchanges/index.js @@ -13,6 +13,7 @@ import StealthEX from '../../../assets/images/token/stealthex.webp'; import SimpleSwap from '../../../assets/images/token/simpleswap.webp'; import CoinEx from '../../../assets/images/token/coinex.webp'; import CoinStore from '../../../assets/images/token/coinstore.webp'; +import Uniswap from '../../../assets/images/token/uniswap.webp'; import './style.scss'; @@ -122,6 +123,13 @@ const Exchanges = ({ t }) => { exchangeLink="https://www.coinstore.com/spot/JOYUSDT" t={t} /> + diff --git a/src/components/token-page/InstantSwap/index.js b/src/components/token-page/InstantSwap/index.js index ffc35b68..9f186def 100644 --- a/src/components/token-page/InstantSwap/index.js +++ b/src/components/token-page/InstantSwap/index.js @@ -1,22 +1,154 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useLayoutEffect, useState } from 'react'; +import cn from 'classnames'; + +import Uniswap from '../../../assets/images/token/uniswap.webp'; +import ChangeNow from '../../../assets/images/token/changenow.webp'; +import DEXScreener from '../../../assets/images/token/dex-screener.png'; +import Base from '../../../assets/images/token/base.webp'; +import Joystream from '../../../assets/images/token/joystream.webp'; import { ReactComponent as LockIcon } from '../../../assets/svg/token/lock.svg'; import { ReactComponent as InvisibilityIcon } from '../../../assets/svg/token/invisibility.svg'; import { ReactComponent as ClockIcon } from '../../../assets/svg/token/clock.svg'; import { ReactComponent as TokenIcon } from '../../../assets/svg/token/token.svg'; +import { ReactComponent as CopyIcon } from '../../../assets/svg/copy.svg'; +import { ReactComponent as ArrowIcon } from '../../../assets/svg/arrow-down-small.svg'; import './style.scss'; -const Benefit = ({ icon, text }) => { - return ( -
+const Benefit = ({ t, icon, text, link, copy }) => { + const [isTooltipVisible, setIsTooltipVisible] = useState(false); + const isCopyable = copy !== undefined; + + useEffect(() => { + if (isTooltipVisible) { + const timeoutId = setTimeout(() => { + setIsTooltipVisible(false); + }, 1500); + + return () => clearTimeout(timeoutId); + } + }, [isTooltipVisible]); + + const content = ( +
{ + if (isCopyable) { + navigator.clipboard.writeText(copy); + setIsTooltipVisible(true); + } + }} + className={cn('TokenPage__instant-swap__main__benefits__item', { + 'TokenPage__instant-swap__main__benefits__item--copy': isCopyable, + })} + >
{icon}
-

{text}

+

{text}

+ {link ? : null} + {isCopyable ? ( +
+ {t('token.instantSwap.benefits.addressTooltip')} +
+ ) : null} +
+ ); + + if (link) { + return ( + + {content} + + ); + } + + return content; +}; + +const ChangeNowSection = ({ t }) => { + return ( +
+
+ } text={t('token.instantSwap.benefits.noSignUp')} /> + } text={t('token.instantSwap.benefits.noKYC')} /> + } text={t('token.instantSwap.benefits.onlyFewMinutes')} /> + } text={t('token.instantSwap.benefits.nineHundredPlusCryptoSupported')} /> +
+
+ +
+
+ ); +}; + +const UniswapSection = ({ t }) => { + return ( +
+
+ + } + text={t('token.instantSwap.benefits.dexScreener')} + link="https://dexscreener.com/base/0xddbc56322277d3b116643470fb9c7c3b1b47b739" + t={t} + /> + } + text={t('token.instantSwap.benefits.joyBaseBridge')} + link="https://bridge.joystream.org/" + t={t} + /> + } + text={t('token.instantSwap.benefits.address')} + copy="0x8761155c814c807cD3CcD15B256D69D3C10f198C" + t={t} + /> +
+
+ +
); }; +const SWITCH_STATE_UNISWAP = 'uniswap'; +const SWITCH_STATE_CHANGENOW = 'changenow'; + const InstantSwap = ({ t }) => { + const [switchState, setSwitchState] = useState(SWITCH_STATE_CHANGENOW); + const [initialLoad, setInitialLoad] = useState(true); + + useLayoutEffect(() => { + if (typeof window !== 'undefined') { + const url = new URL(window.location.href); + const swap = url.searchParams.get('swap'); + + if (swap === 'base') { + setSwitchState(SWITCH_STATE_UNISWAP); + } + } + }, []); + return (
@@ -26,22 +158,61 @@ const InstantSwap = ({ t }) => {

{t('token.instantSwap.subtitle')}

-
-
- } text={t('token.instantSwap.benefits.noSignUp')} /> - } text={t('token.instantSwap.benefits.noKYC')} /> - } text={t('token.instantSwap.benefits.onlyFewMinutes')} /> - } text={t('token.instantSwap.benefits.nineHundredPlusCryptoSupported')} /> -
-
- +
+
+ +
+ + {switchState === SWITCH_STATE_CHANGENOW ? : }
); diff --git a/src/components/token-page/InstantSwap/style.scss b/src/components/token-page/InstantSwap/style.scss index b8bd05f2..2b05ae55 100644 --- a/src/components/token-page/InstantSwap/style.scss +++ b/src/components/token-page/InstantSwap/style.scss @@ -41,29 +41,143 @@ } } + &__switch-wrapper { + display: flex; + justify-content: center; + } + + &__switch { + display: flex; + margin: 48px auto 0; + border-radius: 8px; + gap: 8px; + + &__item { + display: flex; + align-items: center; + justify-content: center; + width: 200px; + padding: 20px; + cursor: pointer; + background-color: #111316; + transition: background-color .7s; + gap: 12px; + + &:hover { + background-color: #6c6cff; + transition: background-color .7s; + } + + &--inactive { + animation: activeButtonFade .3s ease-in; + } + + &--active { + cursor: unset; + background-color: $c_blue-ribbon; + transition: background-color .3s; + + &:hover { + background-color: $c_blue-ribbon; + } + } + + &--changenow { + border-bottom-left-radius: 8px; + border-top-left-radius: 8px; + } + + &--uniswap { + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; + } + + &__logo { + position: relative; + width: 45px; + height: 45px; + + &--with-background { + background-color: $c_white; + border-radius: 12px; + } + + &__image { + width: 45px; + height: 45px; + border-radius: 12px; + } + + &__sub-logo { + position: absolute; + right: -4px; + bottom: -4px; + width: 20px; + height: 20px; + border-radius: 50%; + } + } + + &__text-wrapper { + display: flex; + flex-direction: column; + // gap: 2px; + } + + &__main { + @include h8; + + color: $c_white; + } + + &__subtitle { + @include base-5; + + font-weight: 400; + color: $c_white; + } + } + } + &__main { display: grid; - height: 528px; - margin-top: 96px; + height: 615px; + margin-top: 48px; + animation: fadeIn .3s ease-in; gap: 24px; grid-template-columns: 1fr 1fr; &__benefits { - display: grid; + display: flex; + flex-direction: column; + justify-content: center; gap: 24px; - grid-template-rows: repeat(4, 1fr); &__item { + position: relative; display: flex; align-items: center; + height: 117px; + max-width: 588px; padding: 32px 24px; background-color: #111316; border-radius: 8px; + &--copy { + cursor: pointer; + } + + &__logo { + width: 25px; + height: 25px; + border-radius: 50%; + } + &__icon-wrapper { display: grid; width: 48px; height: 48px; + min-width: 48px; background-color: #1f252e; border-radius: 999px; place-items: center; @@ -75,6 +189,38 @@ margin-left: 24px; color: #fff; } + + &__arrow-icon { + position: absolute; + top: 0; + right: 24px; + bottom: 0; + margin: auto; + color: $c_white; + transform: rotate(-90deg); + } + + &__tooltip { + @include base-3; + + position: absolute; + right: 0; + bottom: calc(100% + 8px); + padding: 8px; + color: $c_white; + background-color: #343d44; + border-radius: 2px; + opacity: 0; + visibility: hidden; + box-shadow: 0 8px 16px 0 rgba(0, 0, 0, .12), 0 4px 4px 0 rgba(0, 0, 0, .1); + transition: visibility .3s linear, opacity .3s linear; + transition-delay: .1s; + + &--visible { + opacity: 1; + visibility: visible; + } + } } } @@ -89,12 +235,22 @@ @media #{$screen-max-md} { &__instant-swap { + &__switch { + margin-top: 32px; + } + &__main { display: flex; flex-direction: column; height: auto; max-width: 585px; - margin: 96px auto 0; + margin: 32px auto 0; + + &__benefits { + &__item { + max-width: 585px; + } + } } } } @@ -116,18 +272,19 @@ } &__main { - margin-top: 48px; gap: 12px; &__benefits { gap: 12px; &__item { + height: 80px; padding: 24px 16px; &__icon-wrapper { width: 32px; height: 32px; + min-width: 32px; & > svg { transform: scale(.8); @@ -139,9 +296,53 @@ margin-left: 12px; } + + &__tooltip { + @include base-4; + } } } } } } + + @media (max-width: 480px) { + &__instant-swap { + &__switch { + flex-direction: column; + + &__item { + &--changenow { + border-top-right-radius: 8px; + border-bottom-left-radius: 0; + } + + &--uniswap { + border-top-right-radius: 0; + border-bottom-left-radius: 8px; + } + } + } + } + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes activeButtonFade { + 0% { + background-color: #4038ff; + } + + 100% { + background-color: #111316; + } } diff --git a/src/locales/en/token.json b/src/locales/en/token.json index eaa1d72a..8ebab3e3 100644 --- a/src/locales/en/token.json +++ b/src/locales/en/token.json @@ -64,12 +64,22 @@ "instantSwap": { "sectionTitle": "INSTANT SWAP", "title": "Instantly buy or sell JOY", - "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW extension.", + "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW and Uniswap extensions.", + "switch": { + "changenow": "Changenow", + "joystream": "Joystream", + "uniswap": "Uniswap", + "base": "BASE" + }, "benefits": { "noSignUp": "No sign up", "noKYC": "No KYC", "onlyFewMinutes": "Only 2-3 minutes", - "nineHundredPlusCryptoSupported": "900+ cryptos supported" + "nineHundredPlusCryptoSupported": "900+ cryptos supported", + "dexScreener": "DEX Screener", + "joyBaseBridge": "JOY <> BASE Bridge", + "address": "0x8761...198C", + "addressTooltip": "Succesfully copied the address to clipboard." } }, "exchanges": { @@ -120,6 +130,10 @@ "name": "Coinstore", "description": "Coinstore is a Singapore-based cryptocurrency exchange founded in 2020." }, + "uniswap": { + "name": "Uniswap", + "description": "Uniswap is a decentralized cryptocurrency exchange initially released in 2018." + }, "visit": "Visit" }, "earn": { diff --git a/src/locales/es/token.json b/src/locales/es/token.json index eaa1d72a..8ebab3e3 100644 --- a/src/locales/es/token.json +++ b/src/locales/es/token.json @@ -64,12 +64,22 @@ "instantSwap": { "sectionTitle": "INSTANT SWAP", "title": "Instantly buy or sell JOY", - "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW extension.", + "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW and Uniswap extensions.", + "switch": { + "changenow": "Changenow", + "joystream": "Joystream", + "uniswap": "Uniswap", + "base": "BASE" + }, "benefits": { "noSignUp": "No sign up", "noKYC": "No KYC", "onlyFewMinutes": "Only 2-3 minutes", - "nineHundredPlusCryptoSupported": "900+ cryptos supported" + "nineHundredPlusCryptoSupported": "900+ cryptos supported", + "dexScreener": "DEX Screener", + "joyBaseBridge": "JOY <> BASE Bridge", + "address": "0x8761...198C", + "addressTooltip": "Succesfully copied the address to clipboard." } }, "exchanges": { @@ -120,6 +130,10 @@ "name": "Coinstore", "description": "Coinstore is a Singapore-based cryptocurrency exchange founded in 2020." }, + "uniswap": { + "name": "Uniswap", + "description": "Uniswap is a decentralized cryptocurrency exchange initially released in 2018." + }, "visit": "Visit" }, "earn": { diff --git a/src/locales/fr/token.json b/src/locales/fr/token.json index eaa1d72a..8ebab3e3 100644 --- a/src/locales/fr/token.json +++ b/src/locales/fr/token.json @@ -64,12 +64,22 @@ "instantSwap": { "sectionTitle": "INSTANT SWAP", "title": "Instantly buy or sell JOY", - "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW extension.", + "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW and Uniswap extensions.", + "switch": { + "changenow": "Changenow", + "joystream": "Joystream", + "uniswap": "Uniswap", + "base": "BASE" + }, "benefits": { "noSignUp": "No sign up", "noKYC": "No KYC", "onlyFewMinutes": "Only 2-3 minutes", - "nineHundredPlusCryptoSupported": "900+ cryptos supported" + "nineHundredPlusCryptoSupported": "900+ cryptos supported", + "dexScreener": "DEX Screener", + "joyBaseBridge": "JOY <> BASE Bridge", + "address": "0x8761...198C", + "addressTooltip": "Succesfully copied the address to clipboard." } }, "exchanges": { @@ -120,6 +130,10 @@ "name": "Coinstore", "description": "Coinstore is a Singapore-based cryptocurrency exchange founded in 2020." }, + "uniswap": { + "name": "Uniswap", + "description": "Uniswap is a decentralized cryptocurrency exchange initially released in 2018." + }, "visit": "Visit" }, "earn": { diff --git a/src/locales/ru/token.json b/src/locales/ru/token.json index eaa1d72a..8ebab3e3 100644 --- a/src/locales/ru/token.json +++ b/src/locales/ru/token.json @@ -64,12 +64,22 @@ "instantSwap": { "sectionTitle": "INSTANT SWAP", "title": "Instantly buy or sell JOY", - "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW extension.", + "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW and Uniswap extensions.", + "switch": { + "changenow": "Changenow", + "joystream": "Joystream", + "uniswap": "Uniswap", + "base": "BASE" + }, "benefits": { "noSignUp": "No sign up", "noKYC": "No KYC", "onlyFewMinutes": "Only 2-3 minutes", - "nineHundredPlusCryptoSupported": "900+ cryptos supported" + "nineHundredPlusCryptoSupported": "900+ cryptos supported", + "dexScreener": "DEX Screener", + "joyBaseBridge": "JOY <> BASE Bridge", + "address": "0x8761...198C", + "addressTooltip": "Succesfully copied the address to clipboard." } }, "exchanges": { @@ -120,6 +130,10 @@ "name": "Coinstore", "description": "Coinstore is a Singapore-based cryptocurrency exchange founded in 2020." }, + "uniswap": { + "name": "Uniswap", + "description": "Uniswap is a decentralized cryptocurrency exchange initially released in 2018." + }, "visit": "Visit" }, "earn": { diff --git a/src/locales/zh/token.json b/src/locales/zh/token.json index eaa1d72a..8ebab3e3 100644 --- a/src/locales/zh/token.json +++ b/src/locales/zh/token.json @@ -64,12 +64,22 @@ "instantSwap": { "sectionTitle": "INSTANT SWAP", "title": "Instantly buy or sell JOY", - "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW extension.", + "subtitle": "Buy or sell JOY tokens effortlessly using the ChangeNOW and Uniswap extensions.", + "switch": { + "changenow": "Changenow", + "joystream": "Joystream", + "uniswap": "Uniswap", + "base": "BASE" + }, "benefits": { "noSignUp": "No sign up", "noKYC": "No KYC", "onlyFewMinutes": "Only 2-3 minutes", - "nineHundredPlusCryptoSupported": "900+ cryptos supported" + "nineHundredPlusCryptoSupported": "900+ cryptos supported", + "dexScreener": "DEX Screener", + "joyBaseBridge": "JOY <> BASE Bridge", + "address": "0x8761...198C", + "addressTooltip": "Succesfully copied the address to clipboard." } }, "exchanges": { @@ -120,6 +130,10 @@ "name": "Coinstore", "description": "Coinstore is a Singapore-based cryptocurrency exchange founded in 2020." }, + "uniswap": { + "name": "Uniswap", + "description": "Uniswap is a decentralized cryptocurrency exchange initially released in 2018." + }, "visit": "Visit" }, "earn": { diff --git a/src/pages/token/index.js b/src/pages/token/index.js index a3348055..86125b73 100644 --- a/src/pages/token/index.js +++ b/src/pages/token/index.js @@ -8,18 +8,11 @@ import SiteMetadata from '../../components/SiteMetadata'; import BaseLayout from '../../components/_layouts/Base'; import Hero from '../../components/token-page/Hero'; import Wallets from '../../components/token-page/Wallets'; -import Faucets from '../../components/token-page/Faucets'; import Exchanges from '../../components/token-page/Exchanges'; import Earn from '../../components/token-page/Earn'; import Utility from '../../components/token-page/Utility'; import Supply from '../../components/token-page/Supply'; import InstantSwap from '../../components/token-page/InstantSwap'; -import TokenInformation from '../../components/token-page/TokenInformation'; - -import ArrowLink from '../../components/ArrowLink'; - -import { sharedData } from '../../data/pages'; -import tokenQuestions from '../../data/pages/token'; import './style.scss'; @@ -46,8 +39,6 @@ const TokensPage = () => { - {/* */} - @@ -57,14 +48,6 @@ const TokensPage = () => { - - {/* ({ - title: t(title), - text: text?.isModular ? : t(text), - }))} - t={t} - /> */} ); };