From 313ef402e757de223801e314f511fc80c4e5f36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=9Fur=20Eren?= Date: Thu, 3 Oct 2024 14:10:03 +0300 Subject: [PATCH] feat: new swap page (#102) * feat: new swap page * feat: Account selection modal --------- Co-authored-by: Chqrles --- client/src/components/Button/index.tsx | 3 +- client/src/components/ChipButton/index.tsx | 24 +++ .../src/components/CurrencyButton/index.tsx | 8 +- client/src/components/Input/index.tsx | 18 ++- .../components/SelectAccountModal/index.tsx | 68 +++++++++ client/src/constants/currencies.ts | 2 + client/src/hooks/useModal.ts | 2 + client/src/pages/Swap.tsx | 142 +++++++++++------- client/src/state/application.ts | 1 + client/src/theme/components/icons.tsx | 20 +++ 10 files changed, 222 insertions(+), 66 deletions(-) create mode 100644 client/src/components/ChipButton/index.tsx create mode 100644 client/src/components/SelectAccountModal/index.tsx diff --git a/client/src/components/Button/index.tsx b/client/src/components/Button/index.tsx index a30e532..6db8cd7 100644 --- a/client/src/components/Button/index.tsx +++ b/client/src/components/Button/index.tsx @@ -18,7 +18,8 @@ export const PrimaryButton = styled.button` font-weight: 485; &:disabled { - background-color: ${({ theme }) => theme.surface}; + background-color: ${({ theme }) => theme.bg3}; + color: ${({ theme }) => theme.neutral2}; cursor: default; } ` diff --git a/client/src/components/ChipButton/index.tsx b/client/src/components/ChipButton/index.tsx new file mode 100644 index 0000000..c61fd3e --- /dev/null +++ b/client/src/components/ChipButton/index.tsx @@ -0,0 +1,24 @@ +import { ThemedText } from 'src/theme/components' +import styled from 'styled-components' + +const StyledChipButton = styled(ThemedText.BodySecondary)<{ active?: boolean }>` + background-color: ${({ theme }) => theme.bg3}; + color: ${({ theme, active }) => (active ? theme.neutral1 : theme.neutral2)}; + border: none; + border-radius: 99px; + padding: 8px 16px; + cursor: pointer; + transition: background-color 0.2s ease; + + &:hover { + background-color: ${({ theme }) => theme.bg2}; + } +` + +interface ChipButtonProps extends React.ButtonHTMLAttributes { + active?: boolean +} + +export function ChipButton({ active, ...props }: ChipButtonProps) { + return +} diff --git a/client/src/components/CurrencyButton/index.tsx b/client/src/components/CurrencyButton/index.tsx index 634aeda..6f3a38e 100644 --- a/client/src/components/CurrencyButton/index.tsx +++ b/client/src/components/CurrencyButton/index.tsx @@ -1,5 +1,6 @@ import { Currency } from 'src/constants/currencies' import { ThemedText } from 'src/theme/components' +import { ChevronDown } from 'src/theme/components/icons' import styled from 'styled-components' import { Row } from '../Flex' @@ -20,15 +21,18 @@ const CurrencyCard = styled(Row)` ` interface CurrencyButtonProps { + className?: string selectedCurrency: Currency } -export function CurrencyButton({ selectedCurrency }: CurrencyButtonProps) { +export function CurrencyButton({ className, selectedCurrency }: CurrencyButtonProps) { return ( - + {selectedCurrency.name} {selectedCurrency.name} + + ) } diff --git a/client/src/components/Input/index.tsx b/client/src/components/Input/index.tsx index 0499dc3..b44aabb 100644 --- a/client/src/components/Input/index.tsx +++ b/client/src/components/Input/index.tsx @@ -9,17 +9,21 @@ interface CurrencyInputProps { } const StyledInput = styled.input` + box-sizing: border-box; + width: 100%; padding: 2px; - border: none; background-color: transparent; + color: ${({ theme }) => theme.neutral1}; + border: none; border-radius: 4px; - font-size: 26px; - width: 100%; - box-sizing: border-box; - color: white; + font-family: 'Inter'; + font-size: 72px; + font-weight: 600; + text-align: center; + outline: none; - &:focus { - outline: none; + &::placeholder { + color: ${({ theme }) => theme.neutral2}; } ` diff --git a/client/src/components/SelectAccountModal/index.tsx b/client/src/components/SelectAccountModal/index.tsx new file mode 100644 index 0000000..7d3a98b --- /dev/null +++ b/client/src/components/SelectAccountModal/index.tsx @@ -0,0 +1,68 @@ +import { useCloseModal, useSelectAccountModal } from 'src/hooks/useModal' +import { ThemedText } from 'src/theme/components' +import { RevolutLogo, VenmoLogo } from 'src/theme/components/icons' +import styled from 'styled-components' + +import { PrimaryButton } from '../Button' +import { Column, Row } from '../Flex' +import Content from '../Modal/Content' +import Overlay from '../Modal/Overlay' +import Portal from '../Portal' + +const AccountButtons = styled(Column)` + width: 100%; +` + +const StyledAccountModal = styled(Row)` + width: 100%; + justify-content: space-between; + padding: 16px; + background-color: ${({ theme }) => theme.bg3}; + color: ${({ theme }) => theme.neutral1}; + border: none; + border-radius: 12px; + cursor: pointer; +` + +interface AccountButtonProps extends React.ButtonHTMLAttributes { + Logo: React.FC> + name: string + currencies: string[] +} + +const AccountButton = ({ Logo, name, currencies, ...props }: AccountButtonProps) => { + return ( + + + + + {name} + + + {currencies.join(', ')} + + ) +} + +export default function SelectAccountModal() { + // modal + const [isOpen] = useSelectAccountModal() + const close = useCloseModal() + + if (!isOpen) return null + + return ( + + + + + + + + Register new account + + + + + ) +} diff --git a/client/src/constants/currencies.ts b/client/src/constants/currencies.ts index ca4d04d..8662a00 100644 --- a/client/src/constants/currencies.ts +++ b/client/src/constants/currencies.ts @@ -10,6 +10,7 @@ export const FIAT_CURRENCIES = { EUR: { img: EURLogo, name: 'EUR', + symbol: '€', }, } @@ -17,5 +18,6 @@ export const TOKEN_CURRENCIES = { USDC: { img: USDCLogo, name: 'USDC', + symbol: 'USDC', }, } diff --git a/client/src/hooks/useModal.ts b/client/src/hooks/useModal.ts index ef3eb37..5bbe47e 100644 --- a/client/src/hooks/useModal.ts +++ b/client/src/hooks/useModal.ts @@ -27,3 +27,5 @@ export const useWalletConnectModal = () => useModal(ModalType.WALLET_CONNECT) export const useWalletOverviewModal = () => useModal(ModalType.WALLET_OVERVIEW) export const useProofGenerationModal = () => useModal(ModalType.PROOF_GENERATION) + +export const useSelectAccountModal = () => useModal(ModalType.SELECT_ACCOUNT) diff --git a/client/src/pages/Swap.tsx b/client/src/pages/Swap.tsx index 240aa47..5a741b9 100644 --- a/client/src/pages/Swap.tsx +++ b/client/src/pages/Swap.tsx @@ -1,70 +1,88 @@ import { ChangeEvent, useState } from 'react' import { PrimaryButton } from 'src/components/Button' +import { ChipButton } from 'src/components/ChipButton' import { CurrencyButton } from 'src/components/CurrencyButton' import { Column, Row } from 'src/components/Flex' import { CurrencyInput } from 'src/components/Input' +import SelectAccountModal from 'src/components/SelectAccountModal' import { FIAT_CURRENCIES, TOKEN_CURRENCIES } from 'src/constants/currencies' +import { useSelectAccountModal } from 'src/hooks/useModal' import { ThemedText } from 'src/theme/components' -import { ArrowDown } from 'src/theme/components/icons' +import { ChevronDown } from 'src/theme/components/icons' import { styled } from 'styled-components' const Content = styled(Column)` max-width: 460px; width: 100%; align-items: normal; - gap: 24px; margin: 0 auto; margin-top: 120px; ` -const SwapCard = styled(Row)` +const SwapCard = styled(Column)` width: 100%; - background-color: ${({ theme }) => theme.bg3}; - border-radius: 12px; padding: 12px 16px; + background-color: ${({ theme }) => theme.bg3}; + border-top-left-radius: 12px; + border-top-right-radius: 12px; +` + +const FiatCurrenyCard = styled(Row)` + width: 100%; + justify-content: space-between; ` const SwapCardContent = styled(Column)` flex: 1; - align-items: flex-start; - - input { - width: 100%; - padding-top: 12px; - padding-bottom: 24px; - font-size: 42px; - font-weight: 600; - color: ${({ theme }) => theme.neutral1}; - - &::placeholder { - color: ${({ theme }) => theme.neutral2}; - } + width: 100%; + padding: 34px 0 42px 0; +` + +const TokenCurrencyButton = styled(CurrencyButton)` + gap: 8px; + background-color: transparent; + border: none; + margin: 8px 0 12px 0; + + img { + width: 18px; + height: 18px; } ` -const SwitchButton = styled.button` - display: flex; - align-items: center; - justify-content: center; +const PresetAmountButton = styled(ChipButton)` + background-color: ${({ theme }) => theme.bg1}; color: ${({ theme }) => theme.neutral1}; + border: 1px solid ${({ theme }) => theme.border}; + padding: 6px 12px; +` + +const RampCard = styled(Row)` + justify-content: space-between; + width: 100%; + padding: 12px 16px; background-color: ${({ theme }) => theme.bg3}; - border: 4px solid ${({ theme }) => theme.bg1}; - border-radius: 6px; - cursor: pointer; - height: 32px; - width: 32px; - box-sizing: content-box; - margin: -18px 0; - z-index: 1; - padding: 0; + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; +` + +const AccountButton = styled(PrimaryButton)` + width: auto; + align-items: center; + gap: 4px; + padding: 8px; ` export default function SwapPage() { const [rampMode, setRampMode] = useState<'on' | 'off'>('on') + const [fiatCurrency, setFiatCurrency] = useState(FIAT_CURRENCIES['EUR']) + const [tokenCurrency, setTokenCurrency] = useState(TOKEN_CURRENCIES['USDC']) const [inputSendValue, setInputSendValue] = useState('') const [inputReceiveValue, setInputReceiveValue] = useState('') + const [, toggleSelectAccountModal] = useSelectAccountModal() + const handleReceiveChange = (event: ChangeEvent) => { const inputValue = event.target.value const numericValue = inputValue.replace(/[^0-9]/g, '') @@ -77,43 +95,55 @@ export default function SwapPage() { setInputSendValue(numericValue) } - const handleChangeClick = () => { - setRampMode((state) => (state == 'off' ? 'on' : 'off')) - setInputSendValue(inputReceiveValue) - setInputReceiveValue(inputSendValue) - } - return ( - - Swap + + + Buy + Sell + - + - - Send - - + + + You're buying + - - - - - - + + - - Receive - + + + + + + 100{fiatCurrency.symbol} + 300{fiatCurrency.symbol} + 1000{fiatCurrency.symbol} + - - + + + From + + + Select account + + + - Swap + Enter amount + + ) } diff --git a/client/src/state/application.ts b/client/src/state/application.ts index 73c8d98..2886889 100644 --- a/client/src/state/application.ts +++ b/client/src/state/application.ts @@ -6,6 +6,7 @@ export enum ModalType { WALLET_CONNECT, WALLET_OVERVIEW, PROOF_GENERATION, + SELECT_ACCOUNT, } export type ApplicationSlice = State & Actions diff --git a/client/src/theme/components/icons.tsx b/client/src/theme/components/icons.tsx index 93f9ae0..ea4304d 100644 --- a/client/src/theme/components/icons.tsx +++ b/client/src/theme/components/icons.tsx @@ -149,3 +149,23 @@ export const LockClosed = (props: SVGProps) => ( /> ) + +export const RevolutLogo = (props: SVGProps) => ( + + + +) + +export const VenmoLogo = (props: SVGProps) => ( + + + +)