style: updating collection page for mobile (#5078)
* style: updating collection page for mobile * addressing comments * responding to comments
This commit is contained in:
parent
b1dc415fb5
commit
c233ba1175
@ -131,7 +131,7 @@ export const Activity = ({ contractAddress, rarityVerified, collectionName, chai
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Row gap="8" paddingTop="16">
|
||||
<Row gap="8" paddingTop={{ sm: '0', md: '16' }}>
|
||||
<Filter eventType={ActivityEventType.Listing} />
|
||||
<Filter eventType={ActivityEventType.Sale} />
|
||||
<Filter eventType={ActivityEventType.Transfer} />
|
||||
|
@ -18,7 +18,7 @@ export const ActivitySwitcher = ({
|
||||
const isLoading = useIsCollectionLoading((state) => state.isCollectionStatsLoading)
|
||||
|
||||
return (
|
||||
<Row gap="24" marginBottom="28">
|
||||
<Row gap="24" marginBottom={{ sm: '16', md: '28' }}>
|
||||
{isLoading ? (
|
||||
ActivitySwitcherLoading
|
||||
) : (
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
import { calc } from '@vanilla-extract/css-utils'
|
||||
import { breakpoints, sprinkles, themeVars, vars } from 'nft/css/sprinkles.css'
|
||||
import { sprinkles, themeVars } from 'nft/css/sprinkles.css'
|
||||
|
||||
export const card = style([
|
||||
sprinkles({
|
||||
@ -13,15 +13,6 @@ export const card = style([
|
||||
{
|
||||
boxSizing: 'border-box',
|
||||
WebkitBoxSizing: 'border-box',
|
||||
'@media': {
|
||||
[`(max-width: ${breakpoints.sm - 1}px)`]: {
|
||||
':hover': {
|
||||
borderColor: themeVars.colors.backgroundOutline,
|
||||
cursor: 'pointer',
|
||||
background: vars.color.lightGrayOverlay,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
|
@ -3,7 +3,6 @@ import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Row } from 'nft/components/Flex'
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
MinusIconLarge,
|
||||
PauseButtonIcon,
|
||||
PlayButtonIcon,
|
||||
@ -162,6 +161,8 @@ const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, childre
|
||||
position={'relative'}
|
||||
ref={assetRef}
|
||||
borderRadius={'20'}
|
||||
borderBottomLeftRadius={'12'}
|
||||
borderBottomRightRadius={'12'}
|
||||
className={selected ? styles.selectedCard : styles.notSelectedCard}
|
||||
draggable={false}
|
||||
onMouseEnter={() => toggleHovered()}
|
||||
@ -195,6 +196,7 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
|
||||
const { hovered, asset } = useCardContext()
|
||||
const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl)
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const isMobile = useIsMobile()
|
||||
|
||||
if (noContent) {
|
||||
return <NoContentContainer uniformHeight={uniformHeight} />
|
||||
@ -221,7 +223,7 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
|
||||
}
|
||||
setLoaded(true)
|
||||
}}
|
||||
className={clsx(hovered && styles.cardImageHover, !loaded && styles.loadingBackground)}
|
||||
className={clsx(hovered && !isMobile && styles.cardImageHover, !loaded && styles.loadingBackground)}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
@ -275,7 +277,7 @@ const Video = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
|
||||
setImageLoaded(true)
|
||||
}}
|
||||
visibility={shouldPlay ? 'hidden' : 'visible'}
|
||||
className={clsx(hovered && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
|
||||
className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
|
||||
/>
|
||||
</Box>
|
||||
{shouldPlay ? (
|
||||
@ -371,7 +373,7 @@ const Audio = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
|
||||
}
|
||||
setImageLoaded(true)
|
||||
}}
|
||||
className={clsx(hovered && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
|
||||
className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
|
||||
/>
|
||||
</Box>
|
||||
{shouldPlay ? (
|
||||
@ -569,7 +571,6 @@ const DetailsLink = () => {
|
||||
}}
|
||||
>
|
||||
Details
|
||||
<ChevronRightIcon width="20px" height="20px" />
|
||||
</DetailsLinkContainer>
|
||||
)
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ import InfiniteScroll from 'react-infinite-scroll-component'
|
||||
import { useInfiniteQuery } from 'react-query'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ThemedText } from 'theme'
|
||||
|
||||
import { CollectionAssetLoading } from './CollectionAssetLoading'
|
||||
import { MARKETPLACE_ITEMS } from './MarketplaceSelect'
|
||||
@ -59,9 +60,31 @@ const rarityIcon = <RarityIcon width="20" height="20" viewBox="2 2 24 24" color=
|
||||
|
||||
const ActionsContainer = styled.div`
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
`
|
||||
|
||||
const ActionsSubContainer = styled.div`
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex: 1;
|
||||
min-width: 0px;
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
|
||||
gap: 10px;
|
||||
}
|
||||
`
|
||||
|
||||
export const SortDropdownContainer = styled.div<{ isFiltersExpanded: boolean }>`
|
||||
width: max-content;
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.lg}px`}) {
|
||||
${({ isFiltersExpanded }) => isFiltersExpanded && `display: none;`}
|
||||
}
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
const EmptyCollectionWrapper = styled.div`
|
||||
display: block;
|
||||
textalign: center;
|
||||
@ -83,9 +106,9 @@ const SweepButton = styled.div<{ toggled: boolean; disabled?: boolean }>`
|
||||
gap: 8px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
padding: 10px 18px 10px 12px;
|
||||
padding: 12px 18px 12px 12px;
|
||||
cursor: ${({ disabled }) => (disabled ? 'auto' : 'pointer')};
|
||||
color: ${({ toggled, disabled, theme }) => (toggled && !disabled ? theme.white : theme.textPrimary)};
|
||||
color: ${({ toggled, disabled, theme }) => (toggled && !disabled ? theme.accentTextLightPrimary : theme.textPrimary)};
|
||||
background: ${({ theme, toggled, disabled }) =>
|
||||
!disabled && toggled
|
||||
? 'radial-gradient(101.8% 4091.31% at 0% 0%, #4673FA 0%, #9646FA 100%)'
|
||||
@ -99,6 +122,16 @@ const SweepButton = styled.div<{ toggled: boolean; disabled?: boolean }>`
|
||||
},
|
||||
}) => `${duration.fast} background-color ${timing.in}`};
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
|
||||
padding: 12px 12px 12px 12px;
|
||||
}
|
||||
`
|
||||
|
||||
const SweepText = styled(ThemedText.BodyPrimary)`
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
export const LoadingButton = styled.div`
|
||||
@ -424,10 +457,15 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
|
||||
|
||||
return (
|
||||
<>
|
||||
<AnimatedBox position="sticky" top="72" width="full" zIndex="3" marginBottom="20">
|
||||
<Box backgroundColor="backgroundBackdrop" width="full" padding="16">
|
||||
<AnimatedBox position="sticky" top="72" width="full" zIndex="3" marginBottom={{ sm: '8', md: '20' }}>
|
||||
<Box
|
||||
backgroundColor="backgroundBackdrop"
|
||||
width="full"
|
||||
paddingTop={{ sm: '12', md: '16' }}
|
||||
paddingBottom={{ sm: '12', md: '16' }}
|
||||
>
|
||||
<ActionsContainer>
|
||||
<Row gap="12">
|
||||
<ActionsSubContainer>
|
||||
<TraceEvent
|
||||
events={[Event.onClick]}
|
||||
element={ElementName.NFT_FILTER_BUTTON}
|
||||
@ -439,12 +477,13 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
|
||||
isMobile={isMobile}
|
||||
isFiltersExpanded={isFiltersExpanded}
|
||||
onClick={() => setFiltersExpanded(!isFiltersExpanded)}
|
||||
collectionCount={collectionNfts?.[0]?.totalCount ?? 0}
|
||||
/>
|
||||
</TraceEvent>
|
||||
<SortDropdown dropDownOptions={sortDropDownOptions} />
|
||||
<SortDropdownContainer isFiltersExpanded={isFiltersExpanded}>
|
||||
<SortDropdown dropDownOptions={sortDropDownOptions} />
|
||||
</SortDropdownContainer>
|
||||
<CollectionSearch />
|
||||
</Row>
|
||||
</ActionsSubContainer>
|
||||
{!hasErc1155s ? (
|
||||
isLoading ? (
|
||||
<LoadingButton />
|
||||
@ -463,7 +502,9 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
|
||||
}}
|
||||
>
|
||||
<SweepIcon viewBox="0 0 24 24" width="20px" height="20px" />
|
||||
Sweep
|
||||
<SweepText fontWeight={600} color="currentColor" lineHeight="20px">
|
||||
Sweep
|
||||
</SweepText>
|
||||
</SweepButton>
|
||||
)
|
||||
) : null}
|
||||
|
@ -13,13 +13,15 @@ export const CollectionSearch = () => {
|
||||
return (
|
||||
<Box
|
||||
as="input"
|
||||
flex="1"
|
||||
borderColor={{ default: 'backgroundOutline', focus: 'genieBlue' }}
|
||||
borderWidth="1.5px"
|
||||
borderStyle="solid"
|
||||
borderRadius="12"
|
||||
padding="12"
|
||||
backgroundColor="backgroundSurface"
|
||||
width="332"
|
||||
maxWidth="332"
|
||||
minWidth="0"
|
||||
fontSize="16"
|
||||
height="44"
|
||||
color={{ placeholder: 'textTertiary', default: 'textPrimary' }}
|
||||
|
@ -131,6 +131,7 @@ export const statsValue = style([
|
||||
}),
|
||||
{
|
||||
lineHeight: '24px',
|
||||
whiteSpace: 'nowrap',
|
||||
},
|
||||
])
|
||||
|
||||
|
@ -243,9 +243,9 @@ const CollectionDescription = ({ description }: { description: string }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const StatsItem = ({ children, label, isMobile }: { children: ReactNode; label: string; isMobile: boolean }) => {
|
||||
const StatsItem = ({ children, label, shouldHide }: { children: ReactNode; label: string; shouldHide: boolean }) => {
|
||||
return (
|
||||
<Box display="flex" flexDirection={'column'} alignItems="baseline" gap="2" height="min">
|
||||
<Box display={shouldHide ? 'none' : 'flex'} flexDirection={'column'} alignItems="baseline" gap="2" height="min">
|
||||
<span className={styles.statsValue}>{children}</span>
|
||||
<Box as="span" className={styles.statsLabel}>
|
||||
{label}
|
||||
@ -295,34 +295,34 @@ const StatsRow = ({ stats, isMobile, ...props }: { stats: GenieCollection; isMob
|
||||
) : (
|
||||
<>
|
||||
{stats.stats?.floor_price ? (
|
||||
<StatsItem label="Global floor" isMobile={isMobile ?? false}>
|
||||
<StatsItem label="Global floor" shouldHide={false}>
|
||||
{floorPriceStr} ETH
|
||||
</StatsItem>
|
||||
) : null}
|
||||
{stats.stats?.one_day_floor_change ? (
|
||||
<StatsItem label="24-Hour Floor" isMobile={isMobile ?? false}>
|
||||
<StatsItem label="24-Hour Floor" shouldHide={false}>
|
||||
<PercentChange>
|
||||
{floorChangeStr}% {arrow}
|
||||
</PercentChange>
|
||||
</StatsItem>
|
||||
) : null}
|
||||
{totalSupplyStr ? (
|
||||
<StatsItem label="Items" isMobile={isMobile ?? false}>
|
||||
<StatsItem label="Items" shouldHide={isMobile ?? false}>
|
||||
{totalSupplyStr}
|
||||
</StatsItem>
|
||||
) : null}
|
||||
{uniqueOwnersPercentage ? (
|
||||
<StatsItem label="Unique owners" isMobile={isMobile ?? false}>
|
||||
<StatsItem label="Unique owners" shouldHide={isMobile ?? false}>
|
||||
{uniqueOwnersPercentage}%
|
||||
</StatsItem>
|
||||
) : null}
|
||||
{stats.stats?.total_volume ? (
|
||||
<StatsItem label="Total Volume" isMobile={isMobile ?? false}>
|
||||
<StatsItem label="Total Volume" shouldHide={false}>
|
||||
{totalVolumeStr} ETH
|
||||
</StatsItem>
|
||||
) : null}
|
||||
{stats.stats?.total_listings && listedPercentageStr > 0 ? (
|
||||
<StatsItem label="Listed" isMobile={isMobile ?? false}>
|
||||
<StatsItem label="Listed" shouldHide={isMobile ?? false}>
|
||||
{listedPercentageStr}%
|
||||
</StatsItem>
|
||||
) : null}
|
||||
@ -394,23 +394,15 @@ export const CollectionStats = ({ stats, isMobile }: { stats: GenieCollection; i
|
||||
collectionSocialsIsOpen={collectionSocialsIsOpen}
|
||||
toggleCollectionSocials={toggleCollectionSocials}
|
||||
/>
|
||||
{!isMobile && (
|
||||
<>
|
||||
{(stats.description || isCollectionStatsLoading) && (
|
||||
<CollectionDescription description={stats.description ?? ''} />
|
||||
)}
|
||||
<StatsRow stats={stats} marginTop="20" />
|
||||
</>
|
||||
{(stats.description || isCollectionStatsLoading) && !isMobile && (
|
||||
<CollectionDescription description={stats.description ?? ''} />
|
||||
)}
|
||||
<StatsRow display={{ sm: 'none', md: 'flex' }} stats={stats} marginTop="20" />
|
||||
</Box>
|
||||
{isMobile && (
|
||||
<>
|
||||
<Box marginBottom="12">{stats.description && <CollectionDescription description={stats.description} />}</Box>
|
||||
<Marquee>
|
||||
<StatsRow stats={stats} marginLeft="6" marginRight="6" marginBottom="28" isMobile />
|
||||
</Marquee>
|
||||
</>
|
||||
{(stats.description || isCollectionStatsLoading) && isMobile && (
|
||||
<CollectionDescription description={stats.description ?? ''} />
|
||||
)}
|
||||
<StatsRow isMobile display={{ sm: 'flex', md: 'none' }} stats={stats} marginTop="20" marginBottom="12" />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
@ -1,43 +1,21 @@
|
||||
import clsx from 'clsx'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import * as styles from 'nft/components/collection/FilterButton.css'
|
||||
import { Row } from 'nft/components/Flex'
|
||||
import { FilterIcon } from 'nft/components/icons'
|
||||
import { buttonTextMedium } from 'nft/css/common.css'
|
||||
import { useCollectionFilters, useIsCollectionLoading, useWalletCollections } from 'nft/hooks'
|
||||
import { putCommas } from 'nft/utils/putCommas'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { useIsCollectionLoading } from 'nft/hooks'
|
||||
|
||||
export const FilterButton = ({
|
||||
onClick,
|
||||
isMobile,
|
||||
isFiltersExpanded,
|
||||
results,
|
||||
collectionCount = 0,
|
||||
}: {
|
||||
isMobile: boolean
|
||||
isFiltersExpanded: boolean
|
||||
results?: number
|
||||
onClick: () => void
|
||||
collectionCount?: number
|
||||
}) => {
|
||||
const { minPrice, maxPrice, minRarity, maxRarity, traits, markets, buyNow } = useCollectionFilters((state) => ({
|
||||
minPrice: state.minPrice,
|
||||
maxPrice: state.maxPrice,
|
||||
minRarity: state.minRarity,
|
||||
maxRarity: state.maxRarity,
|
||||
traits: state.traits,
|
||||
markets: state.markets,
|
||||
buyNow: state.buyNow,
|
||||
}))
|
||||
const collectionFilters = useWalletCollections((state) => state.collectionFilters)
|
||||
const { pathname } = useLocation()
|
||||
const isProfilePage = pathname.startsWith('/profile')
|
||||
const isCollectionNftsLoading = useIsCollectionLoading((state) => state.isCollectionNftsLoading)
|
||||
|
||||
const showFilterBadge = isProfilePage
|
||||
? collectionFilters.length > 0
|
||||
: minPrice || maxPrice || minRarity || maxRarity || traits.length || markets.length || buyNow
|
||||
return (
|
||||
<Box
|
||||
className={
|
||||
@ -45,51 +23,21 @@ export const FilterButton = ({
|
||||
? styles.filterButtonLoading
|
||||
: clsx(styles.filterButton, !isFiltersExpanded && styles.filterButtonExpanded)
|
||||
}
|
||||
display="flex"
|
||||
gap="8"
|
||||
borderRadius="12"
|
||||
fontSize="16"
|
||||
cursor="pointer"
|
||||
position="relative"
|
||||
onClick={onClick}
|
||||
paddingTop="12"
|
||||
paddingLeft="12"
|
||||
paddingBottom="12"
|
||||
paddingRight={isMobile ? '8' : '12'}
|
||||
padding="12"
|
||||
width={isMobile ? '44' : 'auto'}
|
||||
height="44"
|
||||
whiteSpace="nowrap"
|
||||
color="textPrimary"
|
||||
>
|
||||
{!isCollectionNftsLoading && (
|
||||
<>
|
||||
{showFilterBadge && (
|
||||
<Row className={styles.filterBadge} color={isFiltersExpanded ? 'grey700' : 'blue400'}>
|
||||
•
|
||||
</Row>
|
||||
)}
|
||||
|
||||
<FilterIcon
|
||||
style={{
|
||||
marginBottom: '-4px',
|
||||
color: 'textPrimary',
|
||||
paddingRight: `${!isFiltersExpanded || showFilterBadge ? '6px' : '0px'}`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<span className={buttonTextMedium}> {!isMobile && !isFiltersExpanded && 'Filter'}</span>
|
||||
|
||||
{showFilterBadge && !isMobile ? (
|
||||
<Box display="inline-block" position="relative">
|
||||
{!isFiltersExpanded && (
|
||||
<Box as="span" position="absolute" left="4" style={{ top: '5px', fontSize: '8px' }}>
|
||||
•
|
||||
</Box>
|
||||
)}
|
||||
<Box className={buttonTextMedium} paddingLeft={!isFiltersExpanded ? '12' : '2'}>
|
||||
{collectionCount > 0 ? putCommas(collectionCount) : 0} results
|
||||
</Box>
|
||||
</Box>
|
||||
) : null}
|
||||
<FilterIcon />
|
||||
{!isMobile && !isFiltersExpanded && <Box className={buttonTextMedium}> Filter</Box>}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
@ -193,7 +193,6 @@ export const ProfilePage = () => {
|
||||
<FilterButton
|
||||
isMobile={isMobile}
|
||||
isFiltersExpanded={isFiltersExpanded}
|
||||
results={displayAssets.length}
|
||||
onClick={() => setFiltersExpanded(!isFiltersExpanded)}
|
||||
/>
|
||||
<Row gap="8" flexWrap="nowrap">
|
||||
|
Loading…
Reference in New Issue
Block a user