From 2741c42ca3b7cbd87cb78b59910dc44cc562f1b4 Mon Sep 17 00:00:00 2001 From: khiemldk Date: Thu, 26 Oct 2023 13:28:04 +0700 Subject: [PATCH] [GSW-413] fix: Fix Wallet Improve UI --- packages/web/public/cosmos.svg | 4 + .../components/common/button/Button.styles.ts | 14 +- .../components/common/header/Header.styles.ts | 2 +- .../components/common/modal/Modal.styles.ts | 2 +- .../web/src/components/common/modal/Modal.tsx | 7 +- .../MyPositionCardList.tsx | 5 +- .../SearchMenuModal.styles.ts | 1 - .../SelectPairButton.styles.ts | 3 +- .../select-pair-button/SelectPairButton.tsx | 7 +- .../common/select-token/SelectToken.styles.ts | 50 ++-- .../common/select-token/SelectToken.tsx | 46 ++-- .../components/common/switch/Switch.styles.ts | 3 + .../common/tooltip/Tooltip.styles.ts | 10 +- .../src/components/common/tooltip/Tooltip.tsx | 6 +- .../pool-list-table/PoolListTable.styles.ts | 2 +- .../wallet/asset-info/AssetInfo.styles.ts | 11 +- .../wallet/asset-info/AssetInfo.tsx | 16 +- .../AssetListHeader.styles.ts | 18 +- .../asset-list-header/AssetListHeader.tsx | 18 +- .../asset-list-table/AssetListTable.styles.ts | 9 +- .../asset-list-table/AssetListTable.tsx | 4 +- .../wallet/asset-list/AssetList.styles.ts | 7 + .../wallet/asset-list/AssetList.tsx | 7 +- .../deposit-modal/DepositModal.spec.tsx | 61 +++++ .../deposit-modal/DepositModal.stories.tsx | 58 +++++ .../deposit-modal/DepositModal.styles.ts | 214 ++++++++++++++++++ .../wallet/deposit-modal/DepositModal.tsx | 154 +++++++++++++ .../WalletBalanceDetailInfo.styles.ts | 39 +++- .../WalletBalanceDetail.styles.ts | 8 +- .../WalletBalanceDetail.tsx | 9 +- .../WalletBalanceSummaryInfo.styles.ts | 18 +- .../WalletBalanceSummaryInfo.tsx | 14 +- .../WalletBalanceSummary.styles.ts | 2 +- .../WalletBalanceSummary.tsx | 10 +- .../WalletMyPositionsHeader.styles.ts | 5 + .../WalletMyPositionsHeader.tsx | 4 + .../withdraw-modal/WithDrawModal.spec.tsx | 61 +++++ .../withdraw-modal/WithDrawModal.stories.tsx | 58 +++++ .../withdraw-modal/WithDrawModal.styles.ts | 212 +++++++++++++++++ .../wallet/withdraw-modal/WithDrawModal.tsx | 155 +++++++++++++ .../web/src/constants/skeleton.constant.ts | 4 +- packages/web/src/constants/theme.constant.ts | 2 + .../AssetListContainer.tsx | 207 ++++++++++++++--- .../header-container/HeaderContainer.tsx | 9 +- .../modal-container/ModalContainer.tsx | 3 + .../SelectTokenContainer.tsx | 12 +- .../WalletBalanceContainer.tsx | 134 +++++++++-- .../WalletPositionCardListContainer.tsx | 2 +- .../src/hooks/common/use-click-outside.tsx | 36 +++ .../src/hooks/common/use-esc-close-modal.tsx | 19 ++ .../hooks/common/use-modal-close-event.tsx | 15 +- .../src/hooks/common/use-postion-modal.tsx | 23 ++ .../src/hooks/common/use-prevent-scroll.tsx | 11 + .../hooks/token/use-select-token-modal.tsx | 6 +- .../wallet-layout/WalletLayout.styles.ts | 60 ++++- .../layouts/wallet-layout/WalletLayout.tsx | 14 +- packages/web/src/styles/ThemeTypes.ts | 1 + 57 files changed, 1721 insertions(+), 171 deletions(-) create mode 100644 packages/web/public/cosmos.svg create mode 100644 packages/web/src/components/wallet/deposit-modal/DepositModal.spec.tsx create mode 100644 packages/web/src/components/wallet/deposit-modal/DepositModal.stories.tsx create mode 100644 packages/web/src/components/wallet/deposit-modal/DepositModal.styles.ts create mode 100644 packages/web/src/components/wallet/deposit-modal/DepositModal.tsx create mode 100644 packages/web/src/components/wallet/withdraw-modal/WithDrawModal.spec.tsx create mode 100644 packages/web/src/components/wallet/withdraw-modal/WithDrawModal.stories.tsx create mode 100644 packages/web/src/components/wallet/withdraw-modal/WithDrawModal.styles.ts create mode 100644 packages/web/src/components/wallet/withdraw-modal/WithDrawModal.tsx create mode 100644 packages/web/src/hooks/common/use-click-outside.tsx create mode 100644 packages/web/src/hooks/common/use-esc-close-modal.tsx create mode 100644 packages/web/src/hooks/common/use-postion-modal.tsx create mode 100644 packages/web/src/hooks/common/use-prevent-scroll.tsx diff --git a/packages/web/public/cosmos.svg b/packages/web/public/cosmos.svg new file mode 100644 index 000000000..e5bf29e21 --- /dev/null +++ b/packages/web/public/cosmos.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/web/src/components/common/button/Button.styles.ts b/packages/web/src/components/common/button/Button.styles.ts index d01c5ad6a..ca12c4cbb 100644 --- a/packages/web/src/components/common/button/Button.styles.ts +++ b/packages/web/src/components/common/button/Button.styles.ts @@ -19,6 +19,8 @@ export interface ButtonStyleProps { justify?: CSSProperties["justifyContent"]; padding?: CSSProperties["padding"]; minWidth?: CSSProperties["minWidth"]; + hoverColor?: ThemeColorKeyTypes; + disabledColor?: ThemeColorKeyTypes; } export const ButtonWrapper = styled.button` @@ -53,7 +55,10 @@ export const ButtonWrapper = styled.button` &.selected, &:hover { - background-color: ${({ hierarchy, theme }) => { + background-color: ${({ hierarchy, theme, hoverColor }) => { + if (hoverColor) { + return hoverColor; + } if (hierarchy === ButtonHierarchy.Primary) return theme.color.background04Hover; if (hierarchy === ButtonHierarchy.Dark) @@ -68,9 +73,12 @@ export const ButtonWrapper = styled.button` } } &:disabled { - background-color: ${({ hierarchy, theme }) => { + background-color: ${({ hierarchy, theme, disabledColor }) => { + if (disabledColor) { + return disabledColor; + } if (hierarchy === ButtonHierarchy.Primary) - return theme.color.background07; + return theme.color.background17; return; }}; } diff --git a/packages/web/src/components/common/header/Header.styles.ts b/packages/web/src/components/common/header/Header.styles.ts index 66cb08411..073791e6c 100644 --- a/packages/web/src/components/common/header/Header.styles.ts +++ b/packages/web/src/components/common/header/Header.styles.ts @@ -44,7 +44,7 @@ export const BottomNavItem = styled.div` color: ${({ theme }) => theme.color.text04}; &.selected, &:hover { - color: ${({ theme }) => theme.color.text03}; + color: ${({ theme }) => theme.color.text16}; } `; diff --git a/packages/web/src/components/common/modal/Modal.styles.ts b/packages/web/src/components/common/modal/Modal.styles.ts index 452b276f9..c836e75ea 100644 --- a/packages/web/src/components/common/modal/Modal.styles.ts +++ b/packages/web/src/components/common/modal/Modal.styles.ts @@ -58,7 +58,7 @@ export const Overlay = styled.div` right: 0px; width: 100%; height: 100%; - background-color: ${({ theme }) => theme.color.backgroundOpacity}; + background-color: rgba(10, 14, 23, 0.7); overflow: hidden; z-index: ${Z_INDEX.modalOverlay}; `; diff --git a/packages/web/src/components/common/modal/Modal.tsx b/packages/web/src/components/common/modal/Modal.tsx index 4d7bc8550..d91f364df 100644 --- a/packages/web/src/components/common/modal/Modal.tsx +++ b/packages/web/src/components/common/modal/Modal.tsx @@ -1,8 +1,10 @@ +import { usePositionModal } from "@hooks/common/use-postion-modal"; import { ModalStyleProps, ModalWrapper, Overlay, } from "./Modal.styles"; +import { useRef } from "react"; interface ModalProps { hasLeftArrow?: boolean; @@ -20,9 +22,12 @@ const Modal: React.FC = ({ style, children, }) => { + const modalRef = useRef(null); + usePositionModal(modalRef); + return ( <> - + {children} diff --git a/packages/web/src/components/common/my-position-card-list/MyPositionCardList.tsx b/packages/web/src/components/common/my-position-card-list/MyPositionCardList.tsx index 608b70d4c..69606891b 100644 --- a/packages/web/src/components/common/my-position-card-list/MyPositionCardList.tsx +++ b/packages/web/src/components/common/my-position-card-list/MyPositionCardList.tsx @@ -40,12 +40,13 @@ const MyPositionCardList: React.FC = ({ /> ))} - {!mobile ? ( + {!mobile && ( loadMore && onClickLoadMore && ( ) - ) : ( + )} + {(positions.length !== 0 && mobile &&
{currentIndex} / diff --git a/packages/web/src/components/common/search-menu-modal/SearchMenuModal.styles.ts b/packages/web/src/components/common/search-menu-modal/SearchMenuModal.styles.ts index 0d50b3158..33b2afac8 100644 --- a/packages/web/src/components/common/search-menu-modal/SearchMenuModal.styles.ts +++ b/packages/web/src/components/common/search-menu-modal/SearchMenuModal.styles.ts @@ -14,7 +14,6 @@ export const SearchModalBackground = styled.div` height: 100%; background: rgba(10, 14, 23, 0.7); z-index: ${Z_INDEX.modalOverlay}; - backdrop-filter: blur(10px); `; export const SearchContainer = styled.div` diff --git a/packages/web/src/components/common/select-pair-button/SelectPairButton.styles.ts b/packages/web/src/components/common/select-pair-button/SelectPairButton.styles.ts index f0e67d3f5..c9a1a8b43 100644 --- a/packages/web/src/components/common/select-pair-button/SelectPairButton.styles.ts +++ b/packages/web/src/components/common/select-pair-button/SelectPairButton.styles.ts @@ -16,7 +16,7 @@ export const wrapper = (hasToken: boolean, disabled?: boolean) => ( ${!disabled && ` transition: 0.2s; - &:hover { background-color: ${theme.color.hover01}; } + &:hover { background-color: ${theme.color.backgroundGradient}; } `}; span { @@ -30,6 +30,7 @@ export const wrapper = (hasToken: boolean, disabled?: boolean) => ( .token-logo { width: 24px; height: 24px; + border-radius: 50%; } .arrow-icon { width: 16px; diff --git a/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx b/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx index 4de8846d0..7f8f6dd4b 100644 --- a/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx +++ b/packages/web/src/components/common/select-pair-button/SelectPairButton.tsx @@ -9,6 +9,7 @@ interface SelectPairButtonProps { changeToken?: (token: TokenModel) => void; disabled?: boolean; hiddenModal?: boolean; + callback?: (value: boolean) => void; } const SelectPairButton: React.FC = ({ @@ -16,15 +17,17 @@ const SelectPairButton: React.FC = ({ changeToken, disabled, hiddenModal, + callback, }) => { - const { openModal } = useSelectTokenModal({ changeToken }); + const { openModal } = useSelectTokenModal({ changeToken, callback }); const onClickButton = useCallback(() => { if (disabled || hiddenModal) { return; } openModal(); - }, [disabled, openModal, hiddenModal]); + callback?.(false); + }, [disabled, openModal, hiddenModal, callback]); return (
theme.color.background06}; ${media.mobile} { width: 328px; @@ -46,6 +47,11 @@ export const SelectTokenWrapper = styled.div` * { fill: ${({ theme }) => theme.color.icon01}; } + &:hover { + * { + fill: ${({ theme }) => theme.color.icon07}; + } + } } } } @@ -65,15 +71,15 @@ export const SelectTokenWrapper = styled.div` border: 1px solid ${({ theme }) => theme.color.border03}; color: ${({ theme }) => theme.color.text01}; .search-icon * { - fill: ${({ theme }) => theme.color.icon03}; + fill: ${({ theme }) => theme.color.icon05}; } } &:not(:focus-within, .empty-status) { - border: 1px solid ${({ theme }) => theme.color.border11}; + border: 1px solid ${({ theme }) => theme.color.border02}; color: ${({ theme }) => theme.color.text01}; .search-icon * { - fill: ${({ theme }) => theme.color.icon05}; + fill: ${({ theme }) => theme.color.icon08}; } } @@ -91,31 +97,27 @@ export const SelectTokenWrapper = styled.div` height: 100%; margin-right: 16px; &::placeholder { - color: ${({ theme }) => theme.color.text04}; + color: ${({ theme }) => theme.color.text17}; } } .token-select { - display: grid; + ${mixins.flexbox("row", "flex-start", "flex-start")}; + gap: 8px; width: 100%; - grid-template-rows: auto; - col-gap: 8px; - row-gap: 8px; - grid-template-columns: repeat(4, 1fr); - + flex-wrap: wrap; ${media.mobile} { - grid-template-columns: repeat(3, 1fr); + gap: 4px; } .token-button { ${mixins.flexbox("row", "center", "flex-start")}; - margin: 0 auto; - padding: 6px 12px 6px 6px; + padding: 5px 12px 5px 6px; gap: 8px; border-radius: 36px; - border: 1px solid ${({ theme }) => theme.color.border02}; + border: 1px solid ${({ theme }) => theme.color.border12}; background-color: ${({ theme }) => theme.color.background02}; &:hover { - background-color: ${({ theme }) => theme.color.background09}; + background-color: ${({ theme }) => theme.color.hover02}; } cursor: pointer; span { @@ -129,6 +131,9 @@ export const SelectTokenWrapper = styled.div` width: 24px; height: 24px; } + &.border-button-none { + border-color: transparent; + } } } } @@ -137,12 +142,21 @@ export const SelectTokenWrapper = styled.div` ${mixins.flexbox("column", "flex-start", "flex-start")}; width: 100%; gap: 4px; - height: 292px; + max-height: 292px; + &.token-list-wrapper-auto-height { + height: auto; + } ${media.mobile} { height: 248px; } overflow-y: auto; - + .no-data-found { + ${mixins.flexbox("row", "center", "center")}; + color: ${({ theme }) => theme.color.text04}; + ${fonts.body12}; + width: 100%; + height: 120px; + } .list { ${mixins.flexbox("row", "center", "space-between")}; width: 100%; @@ -152,7 +166,7 @@ export const SelectTokenWrapper = styled.div` padding: 12px; } &:hover { - background-color: ${({ theme }) => theme.color.background09}; + background-color: ${({ theme }) => theme.color.hover02}; } cursor: pointer; .token-logo { diff --git a/packages/web/src/components/common/select-token/SelectToken.tsx b/packages/web/src/components/common/select-token/SelectToken.tsx index 8f66697d1..9d2578078 100644 --- a/packages/web/src/components/common/select-token/SelectToken.tsx +++ b/packages/web/src/components/common/select-token/SelectToken.tsx @@ -4,7 +4,6 @@ import IconSearch from "@components/common/icons/IconSearch"; import IconClose from "@components/common/icons/IconCancel"; import { TokenModel } from "@models/token/token-model"; import BigNumber from "bignumber.js"; - export interface SelectTokenProps { keyword: string; defaultTokens: TokenModel[]; @@ -13,6 +12,7 @@ export interface SelectTokenProps { changeKeyword: (keyword: string) => void; changeToken: (token: TokenModel) => void; close: () => void; + themeKey: "dark" | "light"; } const SelectToken: React.FC = ({ @@ -23,8 +23,8 @@ const SelectToken: React.FC = ({ changeKeyword, changeToken, close, + themeKey, }) => { - const getTokenPrice = useCallback((token: TokenModel) => { const tokenPrice = tokenPrices[token.priceId]; if (tokenPrice === null || Number.isNaN(tokenPrice)) { @@ -68,7 +68,9 @@ const SelectToken: React.FC = ({
{defaultTokens.map((token, index) => (
onClickToken(token)} > @@ -78,24 +80,32 @@ const SelectToken: React.FC = ({ ))}
-
- {tokens.map((token, index) => ( -
onClickToken(token)} - > -
- logo - {token.name} - {token.symbol} +
+ {tokens.length > 0 && + tokens.map((token, index) => ( +
onClickToken(token)} + > +
+ logo + {token.name} + {token.symbol} +
+ {getTokenPrice(token)}
- {getTokenPrice(token)} -
- ))} + ))} + {tokens.length === 0 && ( +
No data found
+ )}
); }; -export default SelectToken; \ No newline at end of file +export default SelectToken; diff --git a/packages/web/src/components/common/switch/Switch.styles.ts b/packages/web/src/components/common/switch/Switch.styles.ts index b0b24ea97..d553001bf 100644 --- a/packages/web/src/components/common/switch/Switch.styles.ts +++ b/packages/web/src/components/common/switch/Switch.styles.ts @@ -6,6 +6,9 @@ import mixins from "@styles/mixins"; export const SwitchWrapper = styled.div` ${mixins.flexbox("row", "center", "center", false)}; gap: 16px; + ${media.mobile} { + gap: 8px; + } `; export const SwitchLabel = styled.label` diff --git a/packages/web/src/components/common/tooltip/Tooltip.styles.ts b/packages/web/src/components/common/tooltip/Tooltip.styles.ts index d32aca95a..7d373a598 100644 --- a/packages/web/src/components/common/tooltip/Tooltip.styles.ts +++ b/packages/web/src/components/common/tooltip/Tooltip.styles.ts @@ -1,7 +1,11 @@ import styled from "@emotion/styled"; import { media } from "@styles/media"; -export const Content = styled.div` +interface ContentToolTipProps { + themeKey: "dark" | "light"; +} + +export const Content = styled.div` color: ${({ theme }) => theme.color.text02}; background-color: ${({ theme }) => theme.color.background02}; padding: 16px; @@ -9,7 +13,9 @@ export const Content = styled.div` box-sizing: border-box; width: max-content; max-width: calc(100vw - 10px); - box-shadow: 8px 8px 20px rgba(0, 0, 0, 0.2); + box-shadow: ${({ themeKey }) => { + return themeKey === "dark" ? "10px 14px 60px 0px rgba(0, 0, 0, 0.4)" : "10px 14px 48px 0px rgba(0, 0, 0, 0.12)"; + }}; ${media.mobile} { padding: 12px; gap: 4px; diff --git a/packages/web/src/components/common/tooltip/Tooltip.tsx b/packages/web/src/components/common/tooltip/Tooltip.tsx index a07e6c000..c70967c00 100644 --- a/packages/web/src/components/common/tooltip/Tooltip.tsx +++ b/packages/web/src/components/common/tooltip/Tooltip.tsx @@ -19,6 +19,8 @@ import { import { Content } from "./Tooltip.styles"; import { useTheme } from "@emotion/react"; import { Z_INDEX } from "@styles/zIndex"; +import { useAtomValue } from "jotai"; +import { ThemeState } from "@states/index"; function useTooltip({ placement }: { placement: Placement }) { const [open, setOpen] = useState(false); @@ -85,7 +87,7 @@ const Tooltip: React.FC> = ({ }); const childrenRef = useMergeRefs([refs.setReference]); const floatingRef = useMergeRefs([refs.setFloating]); - + const themeKey = useAtomValue(ThemeState.themeKey); const theme = useTheme(); return ( @@ -121,7 +123,7 @@ const Tooltip: React.FC> = ({ height={14} tipRadius={4} /> - {FloatingContent} + {FloatingContent}
)} diff --git a/packages/web/src/components/earn/pool-list-table/PoolListTable.styles.ts b/packages/web/src/components/earn/pool-list-table/PoolListTable.styles.ts index 0faaa74b5..72b4e05fb 100644 --- a/packages/web/src/components/earn/pool-list-table/PoolListTable.styles.ts +++ b/packages/web/src/components/earn/pool-list-table/PoolListTable.styles.ts @@ -63,5 +63,5 @@ export const noDataText = (theme: Theme) => css` color: ${theme.color.text04}; ${fonts.body12}; width: 100%; - height: 300px; + height: 120px; `; diff --git a/packages/web/src/components/wallet/asset-info/AssetInfo.styles.ts b/packages/web/src/components/wallet/asset-info/AssetInfo.styles.ts index 2f99edf41..c1dc67f4c 100644 --- a/packages/web/src/components/wallet/asset-info/AssetInfo.styles.ts +++ b/packages/web/src/components/wallet/asset-info/AssetInfo.styles.ts @@ -24,7 +24,7 @@ export const AssetInfoWrapper = styled.div` } .name { - margin: 0px 4px; + margin: 0px 8px; } .symbol { @@ -41,7 +41,11 @@ export const TableColumn = styled.div<{ tdWidth: number }>` .logo { margin-left: 16px; } - + .name, + .chain, + .balance { + color: ${({ theme }) => theme.color.text02}; + } .chain { padding: 16px; ${media.tablet} { @@ -64,6 +68,9 @@ export const LoadButton = styled.button` ${mixins.flexbox("row", "center", "center")}; color: ${({ theme }) => theme.color.text04}; gap: 4px; + &.withdraw-pd { + padding-right: 16px; + } &, svg * { transition: all 0.3s ease; diff --git a/packages/web/src/components/wallet/asset-info/AssetInfo.tsx b/packages/web/src/components/wallet/asset-info/AssetInfo.tsx index f72a71de4..deda3b9be 100644 --- a/packages/web/src/components/wallet/asset-info/AssetInfo.tsx +++ b/packages/web/src/components/wallet/asset-info/AssetInfo.tsx @@ -12,8 +12,8 @@ import { DEVICE_TYPE } from "@styles/media"; interface AssetInfoProps { asset: Asset; - deposit: (assetId: string) => void; - withdraw: (assetId: string) => void; + deposit: (asset: Asset) => void; + withdraw: (asset: Asset) => void; breakpoint: DEVICE_TYPE; } @@ -23,19 +23,19 @@ const AssetInfo: React.FC = ({ withdraw, breakpoint, }) => { - const { id, logoUri, name, symbol, chain, balance } = asset; + const { logoUri, name, symbol, chain, balance } = asset; const onClickItem = useCallback((symbol: string) => { location.href = "/tokens/" + symbol; }, []); const onClickDeposit = useCallback(() => { - deposit(id); - }, [deposit, id]); + deposit(asset); + }, [deposit, asset]); const onClickWithdraw = useCallback(() => { - withdraw(id); - }, [withdraw, id]); + withdraw(asset); + }, [withdraw, asset]); return breakpoint === DEVICE_TYPE.WEB ? ( @@ -132,7 +132,7 @@ export const WithdrawButton = ({ onClick: () => void; disabled?: boolean; }) => ( - + Withdraw diff --git a/packages/web/src/components/wallet/asset-list-header/AssetListHeader.styles.ts b/packages/web/src/components/wallet/asset-list-header/AssetListHeader.styles.ts index 350831a7a..6febedda3 100644 --- a/packages/web/src/components/wallet/asset-list-header/AssetListHeader.styles.ts +++ b/packages/web/src/components/wallet/asset-list-header/AssetListHeader.styles.ts @@ -6,19 +6,27 @@ import mixins from "@styles/mixins"; export const AssetListHeaderWrapper = styled.div` ${mixins.flexbox("row", "center", "space-between")}; width: 100%; + ${media.tabletMiddle} { + align-items: flex-start; + gap: 24px; + } ${media.mobile} { flex-direction: column; justify-content: center; align-items: flex-start; - gap: 8px; + gap: 24px; } .title-container { ${mixins.flexbox("row", "center", "flex-start")}; gap: 36px; + ${media.tabletMiddle} { + gap: 24px; + ${mixins.flexbox("column", "flex-start", "flex-start")}; + } ${media.mobile} { width: 100%; - justify-content: space-between; + ${mixins.flexbox("row", "center", "space-between")}; } } .mobile-title-container { @@ -27,6 +35,7 @@ export const AssetListHeaderWrapper = styled.div` } .icon-wrap { ${mixins.flexbox("row", "center", "center")}; + cursor: pointer; } .search-icon { width: 24px; @@ -55,5 +64,10 @@ export const AssetListHeaderWrapper = styled.div` gap: 36px; } .assets-search { + input { + &::placeholder { + color: ${({ theme }) => theme.color.text17}; + } + } } `; diff --git a/packages/web/src/components/wallet/asset-list-header/AssetListHeader.tsx b/packages/web/src/components/wallet/asset-list-header/AssetListHeader.tsx index 4c9ff285e..48b5d0096 100644 --- a/packages/web/src/components/wallet/asset-list-header/AssetListHeader.tsx +++ b/packages/web/src/components/wallet/asset-list-header/AssetListHeader.tsx @@ -17,6 +17,7 @@ interface AssetListHeaderProps { breakpoint: DEVICE_TYPE; searchIcon: boolean; onTogleSearch: () => void; + searchRef: React.RefObject; } const AssetListHeader: React.FC = ({ @@ -29,6 +30,7 @@ const AssetListHeader: React.FC = ({ breakpoint, searchIcon, onTogleSearch, + searchRef, }) => { return ( @@ -51,13 +53,15 @@ const AssetListHeader: React.FC = ({ /> )} {searchIcon ? ( - +
}> + +
) : ( <> theme.color.border01}; border-radius: 8px; color: ${({ theme }) => theme.color.text04}; + ${media.tabletMiddle} { + margin-bottom: 16px; + } ${fonts.body11}; overflow-x: auto; .asset-list-head { @@ -49,13 +52,13 @@ export const TableColumn = styled.div<{ tdWidth: number }>` } } .deposit { - padding: 16px; + padding: 16px 0 16px 16px; ${media.tablet} { - padding: 16px 16px 16px 12px; + padding: 16px 0 16px 12px; } } .withdraw { - padding: 16px; + padding: 16px 16px 16px 12px; ${media.tablet} { padding: 16px 16px 16px 12px; } diff --git a/packages/web/src/components/wallet/asset-list-table/AssetListTable.tsx b/packages/web/src/components/wallet/asset-list-table/AssetListTable.tsx index c4c4b6891..7cdcc5a01 100644 --- a/packages/web/src/components/wallet/asset-list-table/AssetListTable.tsx +++ b/packages/web/src/components/wallet/asset-list-table/AssetListTable.tsx @@ -22,8 +22,8 @@ import { DEVICE_TYPE } from "@styles/media"; interface AssetListTableProps { assets: Asset[]; isFetched: boolean; - deposit: (assetId: string) => void; - withdraw: (assetId: string) => void; + deposit: (asset: Asset) => void; + withdraw: (asset: Asset) => void; sortOption: AssetSortOption | undefined; sort: (head: ASSET_HEAD) => void; isSortOption: (head: ASSET_HEAD) => boolean; diff --git a/packages/web/src/components/wallet/asset-list/AssetList.styles.ts b/packages/web/src/components/wallet/asset-list/AssetList.styles.ts index 599504140..6e949fe76 100644 --- a/packages/web/src/components/wallet/asset-list/AssetList.styles.ts +++ b/packages/web/src/components/wallet/asset-list/AssetList.styles.ts @@ -1,8 +1,15 @@ import styled from "@emotion/styled"; +import { media } from "@styles/media"; import mixins from "@styles/mixins"; export const AssetListWrapper = styled.div` ${mixins.flexbox("column", "center", "center")}; width: 100%; gap: 24px; + ${media.tabletMiddle} { + gap: 8px; + } + ${media.mobile} { + gap: 8px; + } `; diff --git a/packages/web/src/components/wallet/asset-list/AssetList.tsx b/packages/web/src/components/wallet/asset-list/AssetList.tsx index e3d6914c4..7157b0dc4 100644 --- a/packages/web/src/components/wallet/asset-list/AssetList.tsx +++ b/packages/web/src/components/wallet/asset-list/AssetList.tsx @@ -22,14 +22,15 @@ interface AssetListProps { search: (e: React.ChangeEvent) => void; toggleInvisibleZeroBalance: () => void; toggleExtended: () => void; - deposit: (assetId: string) => void; - withdraw: (assetId: string) => void; + deposit: (asset: Asset) => void; + withdraw: (asset: Asset) => void; sortOption: AssetSortOption | undefined; sort: (item: ASSET_HEAD) => void; isSortOption: (item: ASSET_HEAD) => boolean; breakpoint: DEVICE_TYPE; searchIcon: boolean; onTogleSearch: () => void; + searchRef: React.RefObject; } const AssetList: React.FC = ({ @@ -52,6 +53,7 @@ const AssetList: React.FC = ({ breakpoint, searchIcon, onTogleSearch, + searchRef, }) => ( = ({ breakpoint={breakpoint} searchIcon={searchIcon} onTogleSearch={onTogleSearch} + searchRef={searchRef} /> { + it("DepositModal render", () => { + const mockProps = { + breakpoint: DEVICE_TYPE.WEB, + depositInfo: { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", + }, + fromToken: { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", + }, + toToken: { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", + }, + connected: true, + changeToken: () => null, + close: () => null, + }; + + render( + + + + + , + ); + }); +}); diff --git a/packages/web/src/components/wallet/deposit-modal/DepositModal.stories.tsx b/packages/web/src/components/wallet/deposit-modal/DepositModal.stories.tsx new file mode 100644 index 000000000..333cc7722 --- /dev/null +++ b/packages/web/src/components/wallet/deposit-modal/DepositModal.stories.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { ComponentStory, ComponentMeta } from "@storybook/react"; +import DepositModal from "./DepositModal"; +import { action } from "@storybook/addon-actions"; +import { DEVICE_TYPE } from "@styles/media"; + +export default { + title: "wallet/DepositModal", + component: DepositModal, +} as ComponentMeta; + +const Template: ComponentStory = args => ( + +); + +export const Default = Template.bind({}); +Default.args = { + breakpoint: DEVICE_TYPE.WEB, + depositInfo: { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", + }, + fromToken: { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", + }, + toToken: { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", + }, + connected: true, + changeToken: action("changeToken"), + close: action("close"), +}; diff --git a/packages/web/src/components/wallet/deposit-modal/DepositModal.styles.ts b/packages/web/src/components/wallet/deposit-modal/DepositModal.styles.ts new file mode 100644 index 000000000..f42a906e7 --- /dev/null +++ b/packages/web/src/components/wallet/deposit-modal/DepositModal.styles.ts @@ -0,0 +1,214 @@ +import { fonts } from "@constants/font.constant"; +import styled from "@emotion/styled"; +import { media } from "@styles/media"; +import mixins from "@styles/mixins"; +import { Z_INDEX } from "@styles/zIndex"; +export const DepositModalBackground = styled.div` + position: fixed; + overflow: scroll; + top: 0px; + bottom: 0px; + left: 0px; + right: 0px; + width: 100%; + height: 100lvh; + background: rgba(10, 14, 23, 0.7); + z-index: ${Z_INDEX.modalOverlay}; +`; + +export const DepositModalWrapper = styled.div` + ${mixins.flexbox("column", "flex-start", "flex-start")}; + position: absolute; + overflow: hidden; + width: 460px; + border-radius: 8px; + padding: 23px; + gap: 24px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + box-shadow: 10px 14px 60px 0px rgba(0, 0, 0, 0.4); + border: 1px solid ${({ theme }) => theme.color.border02}; + background-color: ${({ theme }) => theme.color.background06}; + ${media.mobile} { + width: 328px; + padding: 16px 11px; + transform: translate(-50%, -50%); + } + .modal-body { + ${mixins.flexbox("column", "flex-start", "flex-start")}; + width: 100%; + gap: 16px; + .header { + ${mixins.flexbox("row", "center", "space-between")}; + width: 100%; + > h6 { + ${fonts.h6} + color: ${({ theme }) => theme.color.text02}; + } + .close-wrap { + ${mixins.flexbox("row", "center", "center")}; + cursor: pointer; + width: 24px; + height: 24px; + .close-icon { + width: 24px; + height: 24px; + * { + fill: ${({ theme }) => theme.color.icon01}; + } + &:hover { + * { + fill: ${({ theme }) => theme.color.icon07}; + } + } + } + } + ${media.mobile} { + > h6 { + ${fonts.body9} + } + } + } + + ${media.mobile} { + padding: 0px; + } + } + .btn-deposit { + padding: 16px 0; + ${media.mobile} { + padding: 10px; + } + } +`; + +export const DepositContent = styled.div` + .deposit { + ${mixins.flexbox("row", "center", "space-between")}; + flex-wrap: wrap; + + width: 100%; + padding: 15px; + + background-color: ${({ theme }) => theme.color.background01}; + border: 1px solid ${({ theme }) => theme.color.border02}; + border-radius: 8px; + ${media.mobile} { + padding: 11px; + } + } + + .amount { + ${mixins.flexbox("row", "center", "space-between")}; + width: 100%; + margin-bottom: 8px; + } + + .token { + height: 32px; + cursor: pointer; + span { + ${fonts.body9} + height: auto !important; + line-height: 19px; + margin: 0px 8px !important; + } + } + + .info { + ${mixins.flexbox("row", "center", "space-between")}; + width: 100%; + } + + .amount-text { + width: 100%; + ${fonts.body1}; + color: ${({ theme }) => theme.color.text01}; + ${media.mobile} { + ${fonts.body5} + } + } + + .price-text, + .balance-text { + ${fonts.body12}; + color: ${({ theme }) => theme.color.text10}; + ${media.mobile} { + ${fonts.p2} + } + } +`; + +export const BoxFromTo = styled.div` + width: 100%; + ${mixins.flexbox("row", "center", "space-between")} + .to, + .from { + ${mixins.flexbox("column", "flex-start", "flex-start")} + gap: 8px; + background-color: ${({ theme }) => theme.color.background01}; + border: 1px solid ${({ theme }) => theme.color.border02}; + width: 184px; + padding: 15px; + ${media.mobile} { + padding: 11px; + } + border-radius: 8px; + h5 { + ${fonts.body12}; + color: ${({ theme }) => theme.color.text10}; + } + > div { + ${mixins.flexbox("row", "center", "flex-start")} + gap: 8px; + img { + width: 24px; + height: 24px; + } + .token-name { + ${fonts.body9} + color: ${({ theme }) => theme.color.text02}; + ${media.mobile} { + ${fonts.body11} + } + } + } + p { + ${fonts.body12}; + color: ${({ theme }) => theme.color.text04}; + } + } +`; + +export const IconButton = styled.div` + width: 28px; + height: 28px; + svg { + * { + fill: ${({ theme }) => theme.color.icon01}; + } + } +`; + +export const BoxDescription = styled.div` + padding: 12px 10px; + width: 100%; + border-radius: 8px; + ${mixins.flexbox("row", "center", "flex-start")} + gap: 6px; + svg { + width: 16px; + height: 16px; + } + .fail-icon { + * { + fill: #788feb; + } + } + p { + ${fonts.body12}; + } + background: ${({ theme }) => theme.color.background19}; + color: ${({ theme }) => theme.color.text08}; +`; diff --git a/packages/web/src/components/wallet/deposit-modal/DepositModal.tsx b/packages/web/src/components/wallet/deposit-modal/DepositModal.tsx new file mode 100644 index 000000000..c4f173340 --- /dev/null +++ b/packages/web/src/components/wallet/deposit-modal/DepositModal.tsx @@ -0,0 +1,154 @@ +import Button, { ButtonHierarchy } from "@components/common/button/Button"; +import IconClose from "@components/common/icons/IconCancel"; +import IconFailed from "@components/common/icons/IconFailed"; +import IconStrokeArrowRight from "@components/common/icons/IconStrokeArrowRight"; +import SelectPairButton from "@components/common/select-pair-button/SelectPairButton"; +import useModalCloseEvent from "@hooks/common/use-modal-close-event"; +import { usePositionModal } from "@hooks/common/use-postion-modal"; +import { TokenModel } from "@models/token/token-model"; +import { DEVICE_TYPE } from "@styles/media"; +import { formatAddress } from "@utils/string-utils"; +import React, { useCallback, useRef, useState } from "react"; +import { + BoxDescription, + BoxFromTo, + DepositContent, + DepositModalBackground, + DepositModalWrapper, + IconButton, +} from "./DepositModal.styles"; + +interface Props { + close: () => void; + breakpoint: DEVICE_TYPE; + depositInfo: TokenModel; + fromToken: TokenModel; + toToken: TokenModel; + connected: boolean; + changeToken: (token: TokenModel) => void; + callback?: (value: boolean) => void; +} + +function isAmount(str: string) { + const regex = /^\d+(\.\d*)?$/; + return regex.test(str); +} + +const DepositModal: React.FC = ({ + close, + breakpoint, + depositInfo, + fromToken, + toToken, + connected, + changeToken, + callback, +}) => { + const modalRef = useRef(null); + const [amount, setAmount] = useState("0"); + + useModalCloseEvent(modalRef, close); + usePositionModal(modalRef); + const onChangeAmount = useCallback( + (e: React.ChangeEvent) => { + const value = e.target.value; + + if (value !== "" && !isAmount(value)) return; + setAmount(value); + // TODO + // - mapT0AmountToT0Price + // - mapT0AmpuntT1Amount + // - mapT1AmpuntT1Price + }, + [], + ); + + return ( + + +
+
+
Deposit
+
+ +
+
+ +
+
+ +
+ +
+
+
+ {!Number(amount) ? "-" : `$${amount}`} + Available: 0 +
+
+
+ +
+
From
+
+ token logo + {fromToken.symbol} +
+

{formatAddress(fromToken.address)}

+
+ + + +
+
To
+
+ token logo + {toToken.symbol} +
+

{formatAddress(toToken.address)}

+
+
+ + +

This feature will be available once Gnoland enables IBC.

+
+
+
+
+ ); +}; + +export default DepositModal; diff --git a/packages/web/src/components/wallet/wallet-balance-detail-info/WalletBalanceDetailInfo.styles.ts b/packages/web/src/components/wallet/wallet-balance-detail-info/WalletBalanceDetailInfo.styles.ts index c197507c0..3d19c1de6 100644 --- a/packages/web/src/components/wallet/wallet-balance-detail-info/WalletBalanceDetailInfo.styles.ts +++ b/packages/web/src/components/wallet/wallet-balance-detail-info/WalletBalanceDetailInfo.styles.ts @@ -8,16 +8,31 @@ export const WalletBalanceDetailInfoWrapper = styled.div` width: 100%; padding: 24px 36px; gap: 16px; + &:last-of-type { + min-width: 284px; + @media (max-width: 1180px) and (min-width: 969px) { + min-width: 261px; + padding: 23px 24px; + } + } ${media.tablet} { padding: 24px; } + @media (max-width: 968px) { + ${mixins.flexbox("row", "center", "space-between")}; + padding: 12px; + } ${media.mobile} { + ${mixins.flexbox("column", "flex-start", "flex-start")}; padding: 12px; gap: 8px; } & + & { border-left: 1px solid ${({ theme }) => theme.color.border02}; + ${media.tabletMiddle} { + border-left: none; + } } .title-wrapper { @@ -32,8 +47,9 @@ export const WalletBalanceDetailInfoWrapper = styled.div` } svg { - width: 13px; - height: 13px; + cursor: pointer; + width: 16px; + height: 16px; } path { fill: ${({ theme }) => theme.color.icon03}; @@ -41,9 +57,12 @@ export const WalletBalanceDetailInfoWrapper = styled.div` } .value-wrapper { - ${mixins.flexbox("row", "flex-end", "center")}; + ${mixins.flexbox("row", "center", "center")}; width: 100%; - + @media (max-width: 968px) { + width: auto; + gap: 8px; + } ${media.mobile} { gap: 8px; } @@ -67,8 +86,14 @@ export const WalletBalanceDetailInfoWrapper = styled.div` export const WalletBalanceDetailInfoTooltipContent = styled.div` ${mixins.flexbox("column", "flex-start", "flex-start")}; - width: calc(300px - 32px); + max-width: 300px; ${fonts.body12}; - color: ${({ theme }) => theme.color.text15}; - background-color: ${({ theme }) => theme.color.background14}; + color: ${({ theme }) => theme.color.text02}; + background-color: ${({ theme }) => theme.color.background02}; + .dark-shadow { + box-shadow: 8px 8px 20px 0px rgba(0, 0, 0, 0.2); + } + .light-shadow { + box-shadow: 10px 14px 48px 0px rgba(0, 0, 0, 0.12); + } `; diff --git a/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.styles.ts b/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.styles.ts index d9f1cbdd6..c9700182a 100644 --- a/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.styles.ts +++ b/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.styles.ts @@ -9,6 +9,9 @@ export const WalletBalanceDetailWrapper = styled.div` border-radius: 8px; background-color: ${({ theme }) => theme.color.background03}; border: 1px solid ${({ theme }) => theme.color.border02}; + @media (max-width: 968px) { + flex-direction: column; + } ${media.mobile} { flex-direction: column; } @@ -30,6 +33,7 @@ export const InfoWrapper = styled.div` align-items: center; padding: 12px; height: auto; + border-left: none; } .column-batch { ${mixins.flexbox("column", "flex-start", "flex-start")}; @@ -48,8 +52,8 @@ export const InfoWrapper = styled.div` } svg { - width: 13px; - height: 13px; + width: 16px; + height: 16px; } path { fill: ${({ theme }) => theme.color.icon03}; diff --git a/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.tsx b/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.tsx index a8fcd5d5f..3eabe37d1 100644 --- a/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.tsx +++ b/packages/web/src/components/wallet/wallet-balance-detail/WalletBalanceDetail.tsx @@ -27,17 +27,18 @@ const WalletBalanceDetail: React.FC = ({ title={"Available Balance"} value={balanceDetailInfo.availableBalance} tooltip={ - "sum of assets not deposited in liquidity pools and unstaked lp tokens." + "Total sum of assets not deposited in liquidity pools." } /> {breakpoint === DEVICE_TYPE.MOBILE ? ( diff --git a/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.styles.ts b/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.styles.ts index 5b209f518..e444caf86 100644 --- a/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.styles.ts +++ b/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.styles.ts @@ -4,8 +4,8 @@ import { fonts } from "@constants/font.constant"; import { media } from "@styles/media"; export const WalletBalanceSummaryInfoWrapper = styled.div` - ${mixins.flexbox("row", "center", "flex-start")}; - gap: 16px; + ${mixins.flexbox("row", "baseline", "flex-start")}; + gap: 8px; ${media.mobile} { gap: 8px; } @@ -26,4 +26,18 @@ export const WalletBalanceSummaryInfoWrapper = styled.div` ${fonts.body7}; } } + .negative { + ${fonts.body3}; + color: ${({ theme }) => theme.color.red01}; + ${media.mobile} { + ${fonts.body7}; + } + } + .positive { + ${fonts.body3}; + color: ${({ theme }) => theme.color.green01}; + ${media.mobile} { + ${fonts.body7}; + } + } `; diff --git a/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.tsx b/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.tsx index 92dd415f8..5f94c4e40 100644 --- a/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.tsx +++ b/packages/web/src/components/wallet/wallet-balance-summary-info/WalletBalanceSummaryInfo.tsx @@ -7,10 +7,22 @@ interface WalletBalanceSummaryInfoProps { const WalletBalanceSummaryInfo: React.FC = ({ balanceSummaryInfo, }) => { + const changeRate = Number(balanceSummaryInfo.changeRate.slice(0, -1)) || 0; + return ( {balanceSummaryInfo.amount} - {balanceSummaryInfo.changeRate} + 0 + ? "positive" + : "negative" + }`} + > + {balanceSummaryInfo.changeRate} + ); }; diff --git a/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.styles.ts b/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.styles.ts index ddb2f0bea..e543a8c7c 100644 --- a/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.styles.ts +++ b/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.styles.ts @@ -19,7 +19,7 @@ export const WalletBalanceSummaryWrapper = styled.div` } .total-balance-title { ${fonts.body4}; - color: ${({ theme }) => theme.color.text05}; + color: ${({ theme }) => theme.color.text10}; ${media.tablet} { ${fonts.body6}; } diff --git a/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.tsx b/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.tsx index 4272db7d2..49ce4a5d8 100644 --- a/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.tsx +++ b/packages/web/src/components/wallet/wallet-balance-summary/WalletBalanceSummary.tsx @@ -4,6 +4,8 @@ import WalletBalanceSummaryInfo from "@components/wallet/wallet-balance-summary- import { ButtonHierarchy } from "@components/common/button/Button"; import { WalletBalanceSummaryWrapper } from "./WalletBalanceSummary.styles"; import { DEVICE_TYPE } from "@styles/media"; +import IconDownload from "@components/common/icons/IconDownload"; +import IconUpload from "@components/common/icons/IconUpload"; interface WalletBalanceSummaryProps { connected: boolean; @@ -26,22 +28,26 @@ const WalletBalanceSummary: React.FC = ({
+ + + ); +}; + +export default WithDrawModal; diff --git a/packages/web/src/constants/skeleton.constant.ts b/packages/web/src/constants/skeleton.constant.ts index 42b7a531f..03a723115 100644 --- a/packages/web/src/constants/skeleton.constant.ts +++ b/packages/web/src/constants/skeleton.constant.ts @@ -39,9 +39,9 @@ export const skeletonStyle = export const POOL_TD_WIDTH = [240, 190, 190, 190, 170, 180, 200]; export const TOKEN_SEARCH_WIDTH = [400]; -export const ASSET_TD_WIDTH = [360, 360, 360, 140, 140]; +export const ASSET_TD_WIDTH = [360, 360, 360, 140, 138]; export const TABLET_ASSET_TD_WIDTH = [273, 273, 273, 140, 140]; -export const MOBILE_ASSET_TD_WIDTH = [150, 160, 90, 80, 120]; +export const MOBILE_ASSET_TD_WIDTH = [178, 178, 178, 80, 120]; export const TOKEN_TD_WIDTH = [ 56, 199, 105, 85, 85, 85, 140, 140, 138, 201, 124, ]; diff --git a/packages/web/src/constants/theme.constant.ts b/packages/web/src/constants/theme.constant.ts index cdf01bf2d..d6c7d4f7b 100644 --- a/packages/web/src/constants/theme.constant.ts +++ b/packages/web/src/constants/theme.constant.ts @@ -125,6 +125,7 @@ export const DARK_THEME_COLORS: ThemeColorType = { background16: colors.dark.gray200BG, background17: colors.dark.gray400BG, background18: colors.global.brand900, + background19: colors.global.brand300Opacity03, backgroundOpacity: colors.dark.blackOpacity07BG, backgroundOpacity2: colors.dark.blackOpacity07BG, backgroundOpacity3: colors.global.gray600Opacity, @@ -216,6 +217,7 @@ export const LIGHT_THEME_COLORS: ThemeColorType = { background16: colors.white.gray200BG, background17: colors.white.gray400BG, background18: colors.global.gray100Opacity06, + background19: colors.global.brand300Opacity03, backgroundOpacity: colors.white.gray100Opacity05BG, backgroundOpacity2: colors.white.whiteOpacity07BG, backgroundOpacity3: colors.white.gray100Opacity05BG, diff --git a/packages/web/src/containers/asset-list-container/AssetListContainer.tsx b/packages/web/src/containers/asset-list-container/AssetListContainer.tsx index 19bf45dc3..ca3ff4551 100644 --- a/packages/web/src/containers/asset-list-container/AssetListContainer.tsx +++ b/packages/web/src/containers/asset-list-container/AssetListContainer.tsx @@ -1,11 +1,17 @@ // TODO : remove eslint-disable after work /* eslint-disable */ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState, useMemo } from "react"; import { ValuesType } from "utility-types"; import { useQuery } from "@tanstack/react-query"; import AssetList from "@components/wallet/asset-list/AssetList"; import BigNumber from "bignumber.js"; import { useWindowSize } from "@hooks/common/use-window-size"; +import useClickOutside from "@hooks/common/use-click-outside"; +import DepositModal from "@components/wallet/deposit-modal/DepositModal"; +import WithDrawModal from "@components/wallet/withdraw-modal/WithDrawModal"; +import { TokenModel } from "@models/token/token-model"; +import { useWallet } from "@hooks/wallet/use-wallet"; +import { usePreventScroll } from "@hooks/common/use-prevent-scroll"; interface AssetListResponse { hasNext: boolean; @@ -55,7 +61,6 @@ export type ASSET_TYPE = ValuesType; export const ASSET_FILTER_TYPE = { ALL: "All", GRC20: "GRC20", - NATIVE: "Native", } as const; export type ASSET_FILTER_TYPE = ValuesType; @@ -127,7 +132,48 @@ function filterKeyword(asset: Asset, keyword: string) { ); } +const DEPOSIT_TO = { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "Cosmos", + logoURI: + "/cosmos.svg", + priceId: "gno.land/r/gnos", +}; + +const DEPOSIT_FROM = { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "Gnoland", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", +}; +const DEPOSIT_INFO = { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", +}; + + const AssetListContainer: React.FC = () => { + const { connected } = useWallet(); + const [address, setAddress] = useState(""); const [assetType, setAssetType] = useState( ASSET_FILTER_TYPE.ALL, @@ -141,10 +187,35 @@ const AssetListContainer: React.FC = () => { const [sortOption, setTokenSortOption] = useState(); const { breakpoint } = useWindowSize(); const [searchIcon, setSearchIcon] = useState(false); + const [componentRef, isClickOutside, setIsInside] = useClickOutside(); + const [isShowDepositModal, setIsShowDepositModal] = useState(false); + const [isShowWithdrawModal, setIsShowWithDrawModal] = useState(false); + const [depositInfo, setDepositInfo] = useState(DEPOSIT_INFO); + const [withdrawInfo, setWithDrawInfo] = useState(DEPOSIT_INFO); + + const changeTokenDeposit = useCallback((token: TokenModel) => { + setDepositInfo(token); + setIsShowDepositModal(true); + }, []); + + const changeTokenWithdraw = useCallback((token: TokenModel) => { + setWithDrawInfo(token); + setIsShowWithDrawModal(true); + }, []); + const onTogleSearch = () => { setSearchIcon(prev => !prev); + setIsInside(true); }; + useEffect(() => { + if (!keyword) { + if (isClickOutside) { + setSearchIcon(false); + } + } + }, [isClickOutside, keyword]); + const { isFetched, error, @@ -161,7 +232,7 @@ const AssetListContainer: React.FC = () => { useEffect(() => { if (assets && assets.length > 0) { - const COLLAPSED_LENGTH = 10; + const COLLAPSED_LENGTH = 15; const filteredAssets = assets .filter( asset => invisibleZeroBalance === false || filterZeroBalance(asset), @@ -186,9 +257,6 @@ const AssetListContainer: React.FC = () => { case ASSET_FILTER_TYPE.ALL: setAssetType(ASSET_FILTER_TYPE.ALL); break; - case ASSET_FILTER_TYPE.NATIVE: - setAssetType(ASSET_FILTER_TYPE.NATIVE); - break; case ASSET_FILTER_TYPE.GRC20: setAssetType(ASSET_FILTER_TYPE.GRC20); break; @@ -210,19 +278,45 @@ const AssetListContainer: React.FC = () => { }, []); const deposit = useCallback( - (assetId: string) => { - console.debug("deposit", `address: ${address}`, `assetId: ${assetId}`); + (asset: Asset) => { + if (!connected) return; + setIsShowDepositModal(true); + setDepositInfo({ + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: asset.symbol, + logoURI: asset.logoUri, + priceId: "gno.land/r/gnos", + }); + // console.debug("deposit", `address: ${address}`, `assetId: ${assetId}`); if (!address) return; }, - [address], + [address, connected], ); const withdraw = useCallback( - (assetId: string) => { - console.debug("withdraw", `address: ${address}`, `assetId: ${assetId}`); + (asset: Asset) => { + if (!connected) return; + setIsShowWithDrawModal(true); + setWithDrawInfo({ + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: asset.symbol, + logoURI: asset.logoUri, + priceId: "gno.land/r/gnos", + }); + // console.debug("withdraw", `address: ${address}`, `assetId: ${assetId}`); if (!address) return; }, - [address], + [address, connected], ); const sort = useCallback( @@ -248,28 +342,75 @@ const AssetListContainer: React.FC = () => { return !disableItems.includes(head); }, []); + + const closeDeposit = () => { + setIsShowDepositModal(false) + } + + const closeWithdraw = () => { + setIsShowWithDrawModal(false) + } + + const callbackDeposit = (value: boolean) => { + setIsShowDepositModal(value); + } + + const callbackWithdraw = (value: boolean) => { + setIsShowWithDrawModal(value); + } + + usePreventScroll(isShowDepositModal || isShowWithdrawModal); + + return ( - + <> + + {isShowDepositModal && ( + + )} + {isShowWithdrawModal && ( + + )} + ); }; diff --git a/packages/web/src/containers/header-container/HeaderContainer.tsx b/packages/web/src/containers/header-container/HeaderContainer.tsx index c46b677c6..370caeb8f 100644 --- a/packages/web/src/containers/header-container/HeaderContainer.tsx +++ b/packages/web/src/containers/header-container/HeaderContainer.tsx @@ -10,6 +10,7 @@ import { useWindowSize } from "@hooks/common/use-window-size"; import { useWallet } from "@hooks/wallet/use-wallet"; import { useAtomValue } from "jotai"; import { ThemeState } from "@states/index"; +import { usePreventScroll } from "@hooks/common/use-prevent-scroll"; interface NegativeStatusType { status: MATH_NEGATIVE_TYPE; @@ -105,13 +106,7 @@ const HeaderContainer: React.FC = () => { setKeyword(e.target.value); }, []); - useEffect(() => { - if (searchMenuToggle) { - document.body.style.overflow = "hidden"; - } else { - document.body.style.overflow = "unset"; - } - }, [searchMenuToggle]); + usePreventScroll(searchMenuToggle); return (
{ const [openedModal, setOpendModal] = useAtom(CommonState.openedModal); @@ -11,6 +12,8 @@ const ModalContainer: React.FC = () => { return openedModal && modalContent !== null; }, [openedModal, modalContent]); + usePreventScroll(visible); + const closeModal = useCallback(() => { setOpendModal(false); }, [setOpendModal]); diff --git a/packages/web/src/containers/select-token-container/SelectTokenContainer.tsx b/packages/web/src/containers/select-token-container/SelectTokenContainer.tsx index 57bb00165..cba4c14bb 100644 --- a/packages/web/src/containers/select-token-container/SelectTokenContainer.tsx +++ b/packages/web/src/containers/select-token-container/SelectTokenContainer.tsx @@ -3,17 +3,23 @@ import SelectToken from "@components/common/select-token/SelectToken"; import { useClearModal } from "@hooks/common/use-clear-modal"; import { useTokenData } from "@hooks/token/use-token-data"; import { TokenModel } from "@models/token/token-model"; +import { useAtomValue } from "jotai"; +import { ThemeState } from "@states/index"; +import useEscCloseModal from "@hooks/common/use-esc-close-modal"; interface SelectTokenContainerProps { changeToken?: (token: TokenModel) => void; + callback?: (value: boolean) => void; } const SelectTokenContainer: React.FC = ({ changeToken, + callback, }) => { const { tokens, balances, updateTokens, updateBalances } = useTokenData(); const [keyword, setKeyword] = useState(""); const clearModal = useClearModal(); + const themeKey = useAtomValue(ThemeState.themeKey); useEffect(() => { updateTokens(); @@ -49,7 +55,10 @@ const SelectTokenContainer: React.FC = ({ const close = useCallback(() => { clearModal(); - }, [clearModal]); + callback?.(true); + }, [clearModal, callback]); + + useEscCloseModal(close); return ( = ({ changeKeyword={changeKeyword} changeToken={selectToken} close={close} + themeKey={themeKey} /> ); }; diff --git a/packages/web/src/containers/wallet-balance-container/WalletBalanceContainer.tsx b/packages/web/src/containers/wallet-balance-container/WalletBalanceContainer.tsx index 1bf05469c..12ee7fa8b 100644 --- a/packages/web/src/containers/wallet-balance-container/WalletBalanceContainer.tsx +++ b/packages/web/src/containers/wallet-balance-container/WalletBalanceContainer.tsx @@ -4,6 +4,11 @@ import React, { useCallback, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import WalletBalance from "@components/wallet/wallet-balance/WalletBalance"; import { useWindowSize } from "@hooks/common/use-window-size"; +import { useWallet } from "@hooks/wallet/use-wallet"; +import DepositModal from "@components/wallet/deposit-modal/DepositModal"; +import { TokenModel } from "@models/token/token-model"; +import WithDrawModal from "@components/wallet/withdraw-modal/WithDrawModal"; +import { usePreventScroll } from "@hooks/common/use-prevent-scroll"; export interface BalanceSummaryInfo { amount: string; @@ -26,7 +31,7 @@ async function fetchBalanceSummaryInfo( address: string, ): Promise { console.debug("fetchBalanceSummaryInfo", address); - return Promise.resolve({ amount: "1324.40", changeRate: "+14.3%" }); + return Promise.resolve({ amount: "$1,324.40", changeRate: "+14.3%" }); } const initialBalanceDetailInfo: BalanceDetailInfo = { @@ -41,25 +46,80 @@ async function fetchBalanceDetailInfo( ): Promise { console.debug("fetchBalanceDetailInfo", address); return Promise.resolve({ - availableBalance: "$1.1", - stakedLP: "$1.2", - unstakingLP: "$1.3", - claimableRewards: "$1.4", + availableBalance: "$1,234.1", + stakedLP: "$1,234.2", + unstakingLP: "$1,234.3", + claimableRewards: "$1,234.4", }); } + +const DEPOSIT_TO = { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "Cosmos", + logoURI: + "/cosmos.svg", + priceId: "gno.land/r/gnos", +}; + +const DEPOSIT_FROM = { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "Gnoland", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", +}; +const DEPOSIT_INFO = { + chainId: "dev", + createdAt: "2023-10-10T08:48:46+09:00", + name: "Gnoswap", + address: "g1sqaft388ruvsseu97r04w4rr4szxkh4nn6xpax", + path: "gno.land/r/gnos", + decimals: 4, + symbol: "GNOT", + logoURI: + "https://raw.githubusercontent.com/onbloc/gno-token-resource/main/gno-native/images/gnot.svg", + priceId: "gno.land/r/gnos", +}; + const WalletBalanceContainer: React.FC = () => { - const [connected, setConnected] = useState(true); + const { connected } = useWallet(); const [address, setAddress] = useState(""); const { breakpoint } = useWindowSize(); + const [isShowDepositModal, setIsShowDepositModal] = useState(false); + const [isShowWithdrawModal, setIsShowWithDrawModal] = useState(false); + const [depositInfo, setDepositInfo] = useState(DEPOSIT_INFO); + const [withdrawInfo, setWithDrawInfo] = useState(DEPOSIT_INFO); + + const changeTokenDeposit = useCallback((token: TokenModel) => { + setDepositInfo(token); + setIsShowDepositModal(true); + }, []); + + const changeTokenWithdraw = useCallback((token: TokenModel) => { + setWithDrawInfo(token); + setIsShowWithDrawModal(true); + }, []); const deposit = useCallback(() => { if (!connected) return; + setIsShowDepositModal(true); if (!address) return; }, [connected, address]); const withdraw = useCallback(() => { if (!connected) return; + setIsShowWithDrawModal(true); if (!address) return; }, [connected, address]); @@ -91,16 +151,60 @@ const WalletBalanceContainer: React.FC = () => { initialData: initialBalanceDetailInfo, }); + const closeDeposit = () => { + setIsShowDepositModal(false) + } + + const closeWithdraw = () => { + setIsShowWithDrawModal(false) + } + + const callbackDeposit = (value: boolean) => { + setIsShowDepositModal(value); + } + + const callbackWithdraw = (value: boolean) => { + setIsShowWithDrawModal(value); + } + + usePreventScroll(isShowDepositModal || isShowWithdrawModal); + return ( - + <> + + {isShowDepositModal && ( + + )} + {isShowWithdrawModal && ( + + )} + ); }; diff --git a/packages/web/src/containers/wallet-position-card-list-container/WalletPositionCardListContainer.tsx b/packages/web/src/containers/wallet-position-card-list-container/WalletPositionCardListContainer.tsx index 14d23fab3..83152d011 100644 --- a/packages/web/src/containers/wallet-position-card-list-container/WalletPositionCardListContainer.tsx +++ b/packages/web/src/containers/wallet-position-card-list-container/WalletPositionCardListContainer.tsx @@ -9,7 +9,7 @@ const WalletPositionCardListContainer: React.FC = () => { const [mobile, setMobile] = useState(false); const handleResize = () => { if (typeof window !== "undefined") { - window.innerWidth < 1000 ? setMobile(true) : setMobile(false); + window.innerWidth <= 1180 ? setMobile(true) : setMobile(false); } }; diff --git a/packages/web/src/hooks/common/use-click-outside.tsx b/packages/web/src/hooks/common/use-click-outside.tsx new file mode 100644 index 000000000..cf591dd34 --- /dev/null +++ b/packages/web/src/hooks/common/use-click-outside.tsx @@ -0,0 +1,36 @@ +import { useState, useEffect, useRef } from "react"; +import { Dispatch, SetStateAction } from "react"; + +function useClickOutside(): [ + React.RefObject, + boolean, + Dispatch>, +] { + const [isClickOutside, setIsClickOutside] = useState(true); + const [isInside, setIsInside] = useState(false); + const componentRef = useRef(null); + + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (isInside) { + setIsClickOutside(false); + setIsInside(false); + } else if ( + componentRef.current && + componentRef.current.contains(event.target as Node) + ) { + setIsClickOutside(false); + } else { + setIsClickOutside(true); + } + } + document.addEventListener("click", handleClickOutside); + return () => { + document.removeEventListener("click", handleClickOutside); + }; + }, [isInside]); + + return [componentRef, isClickOutside, setIsInside]; +} + +export default useClickOutside; diff --git a/packages/web/src/hooks/common/use-esc-close-modal.tsx b/packages/web/src/hooks/common/use-esc-close-modal.tsx new file mode 100644 index 000000000..ddce78017 --- /dev/null +++ b/packages/web/src/hooks/common/use-esc-close-modal.tsx @@ -0,0 +1,19 @@ +import { useEffect } from "react"; + +function useEscCloseModal(callback: () => void) { + const handleEsc = (event: KeyboardEvent) => { + if (event.key === "Escape") { + callback(); + } + }; + + useEffect(() => { + window.addEventListener("keydown", handleEsc); + + return () => { + window.addEventListener("keydown", handleEsc); + }; + }, []); +} + +export default useEscCloseModal; diff --git a/packages/web/src/hooks/common/use-modal-close-event.tsx b/packages/web/src/hooks/common/use-modal-close-event.tsx index e7dbf1761..d48742334 100644 --- a/packages/web/src/hooks/common/use-modal-close-event.tsx +++ b/packages/web/src/hooks/common/use-modal-close-event.tsx @@ -1,6 +1,14 @@ import { useEffect } from "react"; -function useModalCloseEvent(modal: React.RefObject, callback: () => void) { +function useModalCloseEvent( + modal: React.RefObject, + callback: () => void +) { + const handleEsc = (event: KeyboardEvent) => { + if (event.key === "Escape") { + callback(); + } + }; function onClickOutbound(event: MouseEvent) { if (!modal.current) { @@ -14,10 +22,13 @@ function useModalCloseEvent(modal: React.RefObject, callback useEffect(() => { window.addEventListener("click", onClickOutbound, true); + window.addEventListener("keydown", handleEsc); + return () => { window.removeEventListener("click", onClickOutbound, true); + window.addEventListener("keydown", handleEsc); }; - }); + }, []); } export default useModalCloseEvent; diff --git a/packages/web/src/hooks/common/use-postion-modal.tsx b/packages/web/src/hooks/common/use-postion-modal.tsx new file mode 100644 index 000000000..b8e76478a --- /dev/null +++ b/packages/web/src/hooks/common/use-postion-modal.tsx @@ -0,0 +1,23 @@ +import { useEffect } from "react"; + +export const usePositionModal = (ref: React.RefObject) => { + const handleResize = () => { + if (typeof window !== "undefined" && ref.current) { + const height = ref.current.getBoundingClientRect().height; + if (height >= window?.innerHeight) { + ref.current.style.top = "0"; + ref.current.style.transform = "translateX(-50%)"; + } else { + ref.current.style.top = "50%"; + ref.current.style.transform = "translate(-50%, -50%)"; + } + } + }; + useEffect(() => { + handleResize(); + window.addEventListener("resize", handleResize); + return () => { + window.removeEventListener("resize", handleResize); + }; + }, [ref]); +}; diff --git a/packages/web/src/hooks/common/use-prevent-scroll.tsx b/packages/web/src/hooks/common/use-prevent-scroll.tsx new file mode 100644 index 000000000..cff0538a9 --- /dev/null +++ b/packages/web/src/hooks/common/use-prevent-scroll.tsx @@ -0,0 +1,11 @@ +import { useEffect } from "react"; + +export const usePreventScroll = (value: boolean) => { + useEffect(() => { + if (value) { + document.body.style.overflow = "hidden"; + } else { + document.body.style.overflow = "unset"; + } + }, [value]); +}; diff --git a/packages/web/src/hooks/token/use-select-token-modal.tsx b/packages/web/src/hooks/token/use-select-token-modal.tsx index 696bdb944..5aad3b53f 100644 --- a/packages/web/src/hooks/token/use-select-token-modal.tsx +++ b/packages/web/src/hooks/token/use-select-token-modal.tsx @@ -6,12 +6,13 @@ import { useCallback } from "react"; export interface SelectTokenModalProps { changeToken?: (token: TokenModel) => void; + callback?: (value: boolean) => void; } export interface SelectTokenModalModel { openModal: () => void; } -export const useSelectTokenModal = ({ changeToken }: SelectTokenModalProps): SelectTokenModalModel => { +export const useSelectTokenModal = ({ changeToken, callback }: SelectTokenModalProps): SelectTokenModalModel => { const [, setOpenedModal] = useAtom(CommonState.openedModal); const [, setModalContent] = useAtom(CommonState.modalContent); @@ -20,9 +21,10 @@ export const useSelectTokenModal = ({ changeToken }: SelectTokenModalProps): Sel setModalContent( ); - }, [changeToken, setModalContent, setOpenedModal]); + }, [changeToken, setModalContent, setOpenedModal, callback]); return { openModal diff --git a/packages/web/src/layouts/wallet-layout/WalletLayout.styles.ts b/packages/web/src/layouts/wallet-layout/WalletLayout.styles.ts index f3a216999..96be62ad1 100644 --- a/packages/web/src/layouts/wallet-layout/WalletLayout.styles.ts +++ b/packages/web/src/layouts/wallet-layout/WalletLayout.styles.ts @@ -12,15 +12,15 @@ export const WalletLayoutWrapper = styled.div` ${mixins.flexbox("column", "center", "flex-start")}; max-width: ${ContainerWidth.WEB_SECTION_CONTAINER}; width: 100%; - padding: 100px 0px; + padding: 100px 0px 60px; ${media.tablet} { max-width: ${ContainerWidth.TABLET_CONTAINER}; - padding: 60px 0px; + padding: 60px 0px 40px; } ${media.mobile} { max-width: ${ContainerWidth.MOBILE_CONTAINER}; - width: 90%; - padding: 0px; + width: 100%; + padding: 0 16px 24px; } } @@ -30,11 +30,19 @@ export const WalletLayoutWrapper = styled.div` width: 100%; padding: 0px 40px; gap: 36px; + > div { + ${mixins.flexbox("column", "flex-start", "flex-start")}; + width: 100%; + gap: 22px; + } ${media.tablet} { gap: 24px; } ${media.mobile} { - padding: 24px 0px 48px 0px; + padding: 24px 0px 0px 0px; + > div { + gap: 16px; + } } } .assets, @@ -55,8 +63,8 @@ export const WalletLayoutWrapper = styled.div` } ${media.mobile} { max-width: ${ContainerWidth.MOBILE_CONTAINER}; - width: 90%; - padding: 48px 0px; + width: 100%; + padding: 48px 16px; } } @@ -65,7 +73,6 @@ export const WalletLayoutWrapper = styled.div` max-width: ${ContainerWidth.WEB_CONTAINER}; width: 100%; padding: 0px 40px; - gap: 24px; ${media.mobile} { padding: 0px; } @@ -80,6 +87,9 @@ export const WalletLayoutWrapper = styled.div` ${fonts.h5}; } color: ${({ theme }) => theme.color.text02}; + svg { + cursor: pointer; + } } .background-wrapper { @@ -102,3 +112,37 @@ export const WalletLayoutWrapper = styled.div` } } `; + +export const LinkButton = styled.div` + ${mixins.flexbox("row", "center", "center")}; + width: 100%; + ${fonts.body11}; + gap: 4px; + color: ${({ theme }) => theme.color.text04}; + ${media.mobile} { + ${fonts.p3}; + } + a { + ${mixins.flexbox("row", "center", "center")}; + color: ${({ theme }) => theme.color.text07}; + &:hover { + color: ${({ theme }) => theme.color.text08}; + svg { + * { + fill: ${({ theme }) => theme.color.icon14}; + } + } + } + } + svg { + width: 16px; + height: 16px; + * { + fill: ${({ theme }) => theme.color.text07}; + } + } + ${media.mobile} { + flex-wrap: wrap; + padding: 0 20px; + } +`; diff --git a/packages/web/src/layouts/wallet-layout/WalletLayout.tsx b/packages/web/src/layouts/wallet-layout/WalletLayout.tsx index a7e043a98..dae79edfe 100644 --- a/packages/web/src/layouts/wallet-layout/WalletLayout.tsx +++ b/packages/web/src/layouts/wallet-layout/WalletLayout.tsx @@ -1,5 +1,7 @@ +import IconStrokeArrowRight from "@components/common/icons/IconStrokeArrowRight"; import React from "react"; -import { WalletLayoutWrapper } from "./WalletLayout.styles"; +import { LinkButton, WalletLayoutWrapper } from "./WalletLayout.styles"; +import Link from "next/link"; interface WalletLayoutProps { header: React.ReactNode; @@ -21,7 +23,15 @@ const WalletLayout: React.FC = ({

Wallet

-
{balance}
+
+
{balance}
+ + Create a position to start earning rewards + + Click here + + +
diff --git a/packages/web/src/styles/ThemeTypes.ts b/packages/web/src/styles/ThemeTypes.ts index cc6ccb20b..09b8cbc46 100644 --- a/packages/web/src/styles/ThemeTypes.ts +++ b/packages/web/src/styles/ThemeTypes.ts @@ -19,6 +19,7 @@ export interface ThemeColorType { background16: string; background17: string; background18: string; + background19: string; backgroundOpacity: string; backgroundOpacity2: string; backgroundOpacity3: string;