diff --git a/src/nft/components/collection/CollectionNfts.tsx b/src/nft/components/collection/CollectionNfts.tsx index 69acb720a4..900b9bcc48 100644 --- a/src/nft/components/collection/CollectionNfts.tsx +++ b/src/nft/components/collection/CollectionNfts.tsx @@ -98,6 +98,7 @@ const ActionsSubContainer = styled.div` export const SortDropdownContainer = styled.div<{ isFiltersExpanded: boolean }>` width: max-content; + height: 44px; @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.lg}px`}) { ${({ isFiltersExpanded }) => isFiltersExpanded && `display: none;`} } diff --git a/src/nft/components/common/SortDropdown/SortDropdown.tsx b/src/nft/components/common/SortDropdown/SortDropdown.tsx index f33fbd39bb..490c84a2ff 100644 --- a/src/nft/components/common/SortDropdown/SortDropdown.tsx +++ b/src/nft/components/common/SortDropdown/SortDropdown.tsx @@ -56,7 +56,6 @@ export const SortDropdown = ({ borderRadius="12" borderBottomLeftRadius={isOpen ? '0' : undefined} borderBottomRightRadius={isOpen ? '0' : undefined} - height="44" style={{ width }} > theme.breakpoint.sm}px) { - padding-bottom: 20px; - } -` - -const SelectMarketplacesModal = ({ - setSelectedMarkets, - selectedMarkets, -}: { - setSelectedMarkets: Dispatch - selectedMarkets: ListingMarket[] -}) => { - return ( - - Select marketplaces - - Increase the visibility of your listings by selecting multiple marketplaces. - - - {ListingMarkets.map((market) => { - return GlobalMarketplaceButton({ market, setSelectedMarkets, selectedMarkets }) - })} - - - ) -} - -interface GlobalMarketplaceButtonProps { - market: ListingMarket - setSelectedMarkets: Dispatch - selectedMarkets: ListingMarket[] -} - -const GlobalMarketplaceButton = ({ market, setSelectedMarkets, selectedMarkets }: GlobalMarketplaceButtonProps) => { - const isSelected = selectedMarkets.includes(market) - const toggleSelected = () => { - isSelected - ? setSelectedMarkets(selectedMarkets.filter((selected: ListingMarket) => selected !== market)) - : setSelectedMarkets([...selectedMarkets, market]) - } - return ( - - - {market.name} - - {market.fee}% fee - - - ) -} - enum SetPriceMethod { SAME_PRICE, FLOOR_PRICE, @@ -657,7 +583,7 @@ const MarketWrap = styled.section` export const ListPage = () => { const { setProfilePageState: setSellPageState } = useProfilePageState() const setGlobalMarketplaces = useSellAsset((state) => state.setGlobalMarketplaces) - const [selectedMarkets, setSelectedMarkets] = useState([ListingMarkets[2]]) // default marketplace: x2y2 + const [selectedMarkets, setSelectedMarkets] = useState([ListingMarkets[0]]) // default marketplace: x2y2 const toggleBag = useBag((s) => s.toggleBag) const listings = useNFTList((state) => state.listings) const collectionsRequiringApproval = useNFTList((state) => state.collectionsRequiringApproval) @@ -701,7 +627,7 @@ export const ListPage = () => { - + diff --git a/src/nft/components/profile/list/SelectMarketplacesDropdown.tsx b/src/nft/components/profile/list/SelectMarketplacesDropdown.tsx new file mode 100644 index 0000000000..1554ad61d7 --- /dev/null +++ b/src/nft/components/profile/list/SelectMarketplacesDropdown.tsx @@ -0,0 +1,171 @@ +import { useOnClickOutside } from 'hooks/useOnClickOutside' +import { Column, Row } from 'nft/components/Flex' +import { ChevronUpIcon } from 'nft/components/icons' +import { Checkbox } from 'nft/components/layout/Checkbox' +import { buttonTextMedium, caption } from 'nft/css/common.css' +import { ListingMarket } from 'nft/types' +import { ListingMarkets } from 'nft/utils/listNfts' +import { Dispatch, FormEvent, useMemo, useReducer, useRef } from 'react' +import styled from 'styled-components/macro' +import { ThemedText } from 'theme' +import { Z_INDEX } from 'theme/zIndex' + +const MarketplaceRowWrapper = styled(Row)` + gap: 6px; + height: 44px; + width: 100%; + cursor: pointer; + justify-content: space-between; + padding: 0px 16px; + &:hover { + background-color: ${({ theme }) => theme.backgroundInteractive}; + } + border-radius: 12px; +` + +const MarketplaceDropdownIcon = styled.img` + width: 24px; + height: 24px; + border-radius: 4px; + object-fit: cover; +` + +const FeeText = styled.div` + color: ${({ theme }) => theme.textSecondary}; +` + +interface MarketplaceRowProps { + market: ListingMarket + setSelectedMarkets: Dispatch + selectedMarkets: ListingMarket[] +} + +const MarketplaceRow = ({ market, setSelectedMarkets, selectedMarkets }: MarketplaceRowProps) => { + const isSelected = selectedMarkets.includes(market) + const [hovered, toggleHovered] = useReducer((s) => !s, false) + const toggleSelected = () => { + if (selectedMarkets.length === 1 && isSelected) return + isSelected + ? setSelectedMarkets(selectedMarkets.filter((selected: ListingMarket) => selected !== market)) + : setSelectedMarkets([...selectedMarkets, market]) + } + + const handleCheckbox = (e: FormEvent) => { + e.preventDefault() + e.stopPropagation() + } + return ( + + + + + {market.name} + {market.fee}% fee + + + + + + + + ) +} + +const HeaderButtonWrap = styled(Row)` + padding: 12px; + border-radius: 12px; + width: 220px; + justify-content: space-between; + background: ${({ theme }) => theme.backgroundModule}; + cursor: pointer; + &:hover { + background-color: ${({ theme }) => theme.backgroundInteractive}; + } +` + +const HeaderButtonContentWrapper = styled.div` + display: flex; +` + +const MarketIcon = styled.img<{ index: number; totalSelected: number }>` + height: 20px; + width: 20px; + margin-right: 8px; + border: 1px solid; + border-color: ${({ theme }) => theme.backgroundInteractive}; + border-radius: 4px; + z-index: ${({ index, totalSelected }) => totalSelected - index}; + margin-left: ${({ index }) => `${index === 0 ? 0 : -18}px`}; +` + +const Chevron = styled(ChevronUpIcon)<{ isOpen: boolean }>` + height: 20px; + width: 20px; + transition: ${({ + theme: { + transition: { duration }, + }, + }) => `${duration.fast} transform`}; + transform: ${({ isOpen }) => `rotate(${isOpen ? 0 : 180}deg)`}; +` + +const ModalWrapper = styled.div` + display: flex; + flex-direction: column; + position: relative; +` + +const DropdownWrapper = styled(Column)<{ isOpen: boolean }>` + padding: 16px 0px; + background-color: ${({ theme }) => theme.backgroundModule}; + display: ${({ isOpen }) => (isOpen ? 'flex' : 'none')}; + position: absolute; + top: 52px; + width: 220px; + border-radius: 12px; + gap: 12px; + z-index: ${Z_INDEX.modalBackdrop}; +` + +export const SelectMarketplacesDropdown = ({ + setSelectedMarkets, + selectedMarkets, +}: { + setSelectedMarkets: Dispatch + selectedMarkets: ListingMarket[] +}) => { + const [isOpen, toggleIsOpen] = useReducer((s) => !s, false) + const dropdownDisplayText = useMemo( + () => (selectedMarkets.length === 1 ? selectedMarkets[0].name : 'Multiple'), + [selectedMarkets] + ) + const ref = useRef(null) + useOnClickOutside(ref, () => isOpen && toggleIsOpen()) + return ( + + + + {selectedMarkets.map((market, index) => { + return ( + + ) + })} + {dropdownDisplayText} + + + + + + {ListingMarkets.map((market) => { + return MarketplaceRow({ market, setSelectedMarkets, selectedMarkets }) + })} + + + ) +} diff --git a/src/nft/components/profile/list/SetDurationModal.tsx b/src/nft/components/profile/list/SetDurationModal.tsx index bb13ada350..0941884d45 100644 --- a/src/nft/components/profile/list/SetDurationModal.tsx +++ b/src/nft/components/profile/list/SetDurationModal.tsx @@ -28,8 +28,13 @@ const DropdownWrapper = styled(ThemedText.BodyPrimary)` cursor: pointer; display: flex; justify-content: flex-end; - padding-top: 24px; + height: min-content; width: 80px; + &:hover { + background-color: ${({ theme }) => theme.backgroundInteractive}; + } + border-radius: 12px; + padding: 8px; ` const ErrorMessage = styled(Row)` diff --git a/src/nft/utils/listNfts.ts b/src/nft/utils/listNfts.ts index d292a4fa58..a57499c068 100644 --- a/src/nft/utils/listNfts.ts +++ b/src/nft/utils/listNfts.ts @@ -26,6 +26,11 @@ import { ListingMarket, ListingStatus, WalletAsset } from '../types' import { createSellOrder, encodeOrder, OfferItem, OrderPayload, signOrderData } from './x2y2' export const ListingMarkets: ListingMarket[] = [ + { + name: 'X2Y2', + fee: 0.5, + icon: '/nft/svgs/marketplaces/x2y2.svg', + }, { name: 'LooksRare', fee: 1.5, @@ -36,11 +41,6 @@ export const ListingMarkets: ListingMarket[] = [ fee: 2.5, icon: '/nft/svgs/marketplaces/opensea.svg', }, - { - name: 'X2Y2', - fee: 0.5, - icon: '/nft/svgs/marketplaces/x2y2.svg', - }, ] const createConsiderationItem = (basisPoints: string, recipient: string): ConsiderationInputItem => {