diff --git a/client/src/components/Button/index.tsx b/client/src/components/Button/index.tsx index 644f595..a6fcef3 100644 --- a/client/src/components/Button/index.tsx +++ b/client/src/components/Button/index.tsx @@ -28,3 +28,11 @@ export const OutlineButton = styled.button` border: 1px solid ${({ theme }) => theme.white}; color: ${({ theme }) => theme.white}; ` + +export const ConnectButton = styled(PrimaryButton)` + width: auto; + padding: 14px 32px; + background: linear-gradient(360deg, #202a31 0%, #28353e 100%); + color: ${({ theme }) => theme.neutral1}; + font-size: 16px; +` diff --git a/client/src/components/ConnectWalletModal/index.tsx b/client/src/components/ConnectWalletModal/index.tsx new file mode 100644 index 0000000..ebceaa7 --- /dev/null +++ b/client/src/components/ConnectWalletModal/index.tsx @@ -0,0 +1,65 @@ +import { useConnect } from '@starknet-react/core' +import { ThemedText } from 'src/theme/components' +import styled from 'styled-components' + +import { Column, Row } from '../Flex' + +const Container = styled(Column)` + width: 300px; + align-items: flex-start; + padding: 16px; + background-color: ${({ theme }) => theme.bg2}; + border: 1px solid ${({ theme }) => theme.border}; + border-radius: 20px; + box-shadow: 0px 4px 4px 4px rgba(0, 0, 0, 0.3), 0px 8px 12px 10px rgba(0, 0, 0, 0.15); +` + +const ConnectorsList = styled(Column)` + width: 100%; + + :first-child { + border-top-left-radius: 12px; + border-top-right-radius: 12px; + } + + :last-child { + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; + } +` + +const ConnectorCard = styled(Row)` + width: 100%; + padding: 12px; + background-color: ${({ theme }) => theme.bg3}; + border: none; + outline: none; + cursor: pointer; + + img { + width: 32px; + height: 32px; + } +` + +export const ConnectWalletModal = (props: React.ComponentPropsWithoutRef) => { + const { connect, connectors } = useConnect() + + return ( + + Connect wallet + + + {connectors + .filter((connector) => connector.available()) + .map((connector) => ( + connect({ connector })}> + {connector.name} + + {connector.name} + + ))} + + + ) +} diff --git a/client/src/components/Header/index.tsx b/client/src/components/Header/index.tsx index 86609de..da4986b 100644 --- a/client/src/components/Header/index.tsx +++ b/client/src/components/Header/index.tsx @@ -1,3 +1,106 @@ +import { useAccount } from '@starknet-react/core' +import { useState } from 'react' +import { NavLink } from 'react-router-dom' +import { ThemedText } from 'src/theme/components' +import { Logo } from 'src/theme/components/icons' +import styled from 'styled-components' + +import { ConnectButton } from '../Button' +import { ConnectWalletModal } from '../ConnectWalletModal' +import { Row } from '../Flex' +import WalletSidebar from '../WalletSidebar' + +const Container = styled(Row)` + justify-content: space-between; + padding: 24px 32px; +` + +const Link = styled(ThemedText.BodyPrimary)` + color: rgba(255, 255, 255, 0.7); + font-weight: 500; + font-size: 18px; + text-decoration: none; + + &.active { + color: ${({ theme }) => theme.neutral1}; + } +` + +const ConnectContainer = styled(Row)` + position: relative; +` + +const ConnectWalletDropdown = styled(ConnectWalletModal)` + position: absolute; + top: calc(100% + 16px); + right: 0; +` + +const AccountChip = styled(Row)` + padding: 6px 8px; + background-color: ${({ theme }) => theme.bg3}; + border: none; + border-radius: 99px; + cursor: pointer; +` + +const AccountStatusIcon = styled.div` + width: 12px; + height: 12px; + background-color: ${({ theme }) => theme.green}; + border-radius: 12px; +` + export default function Header() { - return null + const [connectDropdownShown, setConnectDropdownShown] = useState(false) + const [walletSidebarShown, setWalletSidebarShown] = useState(false) + + const { address } = useAccount() + + const toggleConnectDropdown = () => { + setConnectDropdownShown((prev) => !prev) + } + + const showWalletSidebar = () => { + setWalletSidebarShown(true) + } + const hideWalletSidebar = () => { + setWalletSidebarShown(false) + } + + return ( + + + + + + + Swap + + + + Liquidity + + + + + {address ? ( + + + + + {address.slice(0, 6)}...{address.slice(-4)} + + + ) : ( + + Connect + + {connectDropdownShown && } + + )} + + {walletSidebarShown && } + + ) } diff --git a/client/src/components/WalletSidebar/index.tsx b/client/src/components/WalletSidebar/index.tsx new file mode 100644 index 0000000..76ddf6e --- /dev/null +++ b/client/src/components/WalletSidebar/index.tsx @@ -0,0 +1,104 @@ +import { useAccount, useDisconnect } from '@starknet-react/core' +import { Link } from 'react-router-dom' +import { ThemedText } from 'src/theme/components' +import { DoubleChevronRight, Logout, StarknetLogo, UserCheck } from 'src/theme/components/icons' +import styled from 'styled-components' + +import { Column, Row } from '../Flex' + +const Container = styled(Column)` + position: fixed; + top: 0; + right: 0; + width: 372px; + height: 100%; + padding: 8px; +` + +const Content = styled(Column)` + width: 100%; + height: 100%; + padding: 16px; + background-color: ${({ theme }) => theme.bg2}; + border: 1px solid ${({ theme }) => theme.border}; + border-radius: 20px; +` + +const WalletInfo = styled(Row)` + width: 100%; + justify-content: space-between; +` + +const CloseButton = styled.button` + color: rgba(240, 247, 244, 0.5); + background-color: transparent; + border: none; + cursor: pointer; +` + +const Links = styled(Column)` + width: 100%; +` + +const LinkItem = styled(Row)` + width: 100%; + gap: 10px; + padding: 12px 6px; + background-color: transparent; + border: none; + border-radius: 8px; + text-decoration: none; + cursor: pointer; + + &:hover { + background-color: ${({ theme }) => theme.bg3}; + box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15), + 0px 0.5px 0px 0px rgba(240, 247, 244, 0.1) inset; + } + + div { + color: ${({ theme }) => theme.neutral1}; + } +` + +type WalletSidebarProps = { + onClose?: () => void +} + +export default function WalletSidebar({ onClose }: WalletSidebarProps) { + const { address } = useAccount() + const { disconnect } = useDisconnect() + + if (!address) return + + return ( + + + + + + + {address.slice(0, 6)}...{address.slice(-4)} + + + + + + + + + + + + Registration + + + disconnect()}> + + Disconnect + + + + + ) +} diff --git a/client/src/pages/Swap.tsx b/client/src/pages/Swap.tsx index f28e7ce..8db6410 100644 --- a/client/src/pages/Swap.tsx +++ b/client/src/pages/Swap.tsx @@ -12,7 +12,7 @@ import { styled } from 'styled-components' const Layout = styled(Column)` margin: 0 auto; justify-content: center; - height: 100vh; + flex: 1; ` const Content = styled(Column)` diff --git a/client/src/theme/colors.ts b/client/src/theme/colors.ts index 9da0417..eeee35f 100644 --- a/client/src/theme/colors.ts +++ b/client/src/theme/colors.ts @@ -3,6 +3,7 @@ const colors = { white: '#FFFFFF', black: '#000000', + green: '#21C95E', neutral1_dark: '#ffffff', neutral2_dark: 'rgba(240, 247, 244, 0.5)', @@ -11,6 +12,7 @@ const colors = { const commonTheme = { white: colors.white, black: colors.black, + green: colors.green, accent1: '#FF3864', } @@ -19,7 +21,7 @@ export const darkTheme = { ...commonTheme, bg1: '#000000', - bg2: '#121216', + bg2: '#101519', bg3: '#181F25', surface: '#0D0D12', diff --git a/client/src/theme/components/icons.tsx b/client/src/theme/components/icons.tsx index a05f627..8ebcf9c 100644 --- a/client/src/theme/components/icons.tsx +++ b/client/src/theme/components/icons.tsx @@ -20,6 +20,55 @@ export const Starknet = (props: SVGProps) => ( ) +export const StarknetLogo = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + export const ChevronDown = (props: SVGProps) => ( ( /> ) + +export const DoubleChevronRight = (props: SVGProps) => ( + + + +) + +export const UserCheck = (props: SVGProps) => ( + + + +) + +export const Logout = (props: SVGProps) => ( + + + +) diff --git a/client/src/theme/index.tsx b/client/src/theme/index.tsx index c0bc459..e985703 100644 --- a/client/src/theme/index.tsx +++ b/client/src/theme/index.tsx @@ -94,6 +94,15 @@ export const ThemedGlobalStyle = createGlobalStyle` padding: 0; } + html, body, #root { + height: 100%; + } + + #root { + display: flex; + flex-direction: column; + } + * { box-sizing: border-box; font-family: 'Inter';