style: updating collection page for mobile (#5078)

* style: updating collection page for mobile

* addressing comments

* responding to comments
This commit is contained in:
Jack Short 2022-11-04 16:13:17 -04:00 committed by GitHub
parent b1dc415fb5
commit c233ba1175
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 84 additions and 109 deletions

@ -131,7 +131,7 @@ export const Activity = ({ contractAddress, rarityVerified, collectionName, chai
return ( return (
<Box> <Box>
<Row gap="8" paddingTop="16"> <Row gap="8" paddingTop={{ sm: '0', md: '16' }}>
<Filter eventType={ActivityEventType.Listing} /> <Filter eventType={ActivityEventType.Listing} />
<Filter eventType={ActivityEventType.Sale} /> <Filter eventType={ActivityEventType.Sale} />
<Filter eventType={ActivityEventType.Transfer} /> <Filter eventType={ActivityEventType.Transfer} />

@ -18,7 +18,7 @@ export const ActivitySwitcher = ({
const isLoading = useIsCollectionLoading((state) => state.isCollectionStatsLoading) const isLoading = useIsCollectionLoading((state) => state.isCollectionStatsLoading)
return ( return (
<Row gap="24" marginBottom="28"> <Row gap="24" marginBottom={{ sm: '16', md: '28' }}>
{isLoading ? ( {isLoading ? (
ActivitySwitcherLoading ActivitySwitcherLoading
) : ( ) : (

@ -1,6 +1,6 @@
import { style } from '@vanilla-extract/css' import { style } from '@vanilla-extract/css'
import { calc } from '@vanilla-extract/css-utils' 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([ export const card = style([
sprinkles({ sprinkles({
@ -13,15 +13,6 @@ export const card = style([
{ {
boxSizing: 'border-box', boxSizing: 'border-box',
WebkitBoxSizing: '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 { Box } from 'nft/components/Box'
import { Row } from 'nft/components/Flex' import { Row } from 'nft/components/Flex'
import { import {
ChevronRightIcon,
MinusIconLarge, MinusIconLarge,
PauseButtonIcon, PauseButtonIcon,
PlayButtonIcon, PlayButtonIcon,
@ -162,6 +161,8 @@ const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, childre
position={'relative'} position={'relative'}
ref={assetRef} ref={assetRef}
borderRadius={'20'} borderRadius={'20'}
borderBottomLeftRadius={'12'}
borderBottomRightRadius={'12'}
className={selected ? styles.selectedCard : styles.notSelectedCard} className={selected ? styles.selectedCard : styles.notSelectedCard}
draggable={false} draggable={false}
onMouseEnter={() => toggleHovered()} onMouseEnter={() => toggleHovered()}
@ -195,6 +196,7 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
const { hovered, asset } = useCardContext() const { hovered, asset } = useCardContext()
const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl) const [noContent, setNoContent] = useState(!asset.smallImageUrl && !asset.imageUrl)
const [loaded, setLoaded] = useState(false) const [loaded, setLoaded] = useState(false)
const isMobile = useIsMobile()
if (noContent) { if (noContent) {
return <NoContentContainer uniformHeight={uniformHeight} /> return <NoContentContainer uniformHeight={uniformHeight} />
@ -221,7 +223,7 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
} }
setLoaded(true) setLoaded(true)
}} }}
className={clsx(hovered && styles.cardImageHover, !loaded && styles.loadingBackground)} className={clsx(hovered && !isMobile && styles.cardImageHover, !loaded && styles.loadingBackground)}
/> />
</Box> </Box>
) )
@ -275,7 +277,7 @@ const Video = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
setImageLoaded(true) setImageLoaded(true)
}} }}
visibility={shouldPlay ? 'hidden' : 'visible'} visibility={shouldPlay ? 'hidden' : 'visible'}
className={clsx(hovered && styles.cardImageHover, !imageLoaded && styles.loadingBackground)} className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
/> />
</Box> </Box>
{shouldPlay ? ( {shouldPlay ? (
@ -371,7 +373,7 @@ const Audio = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
} }
setImageLoaded(true) setImageLoaded(true)
}} }}
className={clsx(hovered && styles.cardImageHover, !imageLoaded && styles.loadingBackground)} className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
/> />
</Box> </Box>
{shouldPlay ? ( {shouldPlay ? (
@ -569,7 +571,6 @@ const DetailsLink = () => {
}} }}
> >
Details Details
<ChevronRightIcon width="20px" height="20px" />
</DetailsLinkContainer> </DetailsLinkContainer>
) )
} }

@ -41,6 +41,7 @@ import InfiniteScroll from 'react-infinite-scroll-component'
import { useInfiniteQuery } from 'react-query' import { useInfiniteQuery } from 'react-query'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { CollectionAssetLoading } from './CollectionAssetLoading' import { CollectionAssetLoading } from './CollectionAssetLoading'
import { MARKETPLACE_ITEMS } from './MarketplaceSelect' 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` const ActionsContainer = styled.div`
display: flex; display: flex;
gap: 10px;
width: 100%;
justify-content: space-between; 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` const EmptyCollectionWrapper = styled.div`
display: block; display: block;
textalign: center; textalign: center;
@ -83,9 +106,9 @@ const SweepButton = styled.div<{ toggled: boolean; disabled?: boolean }>`
gap: 8px; gap: 8px;
border: none; border: none;
border-radius: 12px; border-radius: 12px;
padding: 10px 18px 10px 12px; padding: 12px 18px 12px 12px;
cursor: ${({ disabled }) => (disabled ? 'auto' : 'pointer')}; 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 }) => background: ${({ theme, toggled, disabled }) =>
!disabled && toggled !disabled && toggled
? 'radial-gradient(101.8% 4091.31% at 0% 0%, #4673FA 0%, #9646FA 100%)' ? '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}`}; }) => `${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` export const LoadingButton = styled.div`
@ -424,10 +457,15 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
return ( return (
<> <>
<AnimatedBox position="sticky" top="72" width="full" zIndex="3" marginBottom="20"> <AnimatedBox position="sticky" top="72" width="full" zIndex="3" marginBottom={{ sm: '8', md: '20' }}>
<Box backgroundColor="backgroundBackdrop" width="full" padding="16"> <Box
backgroundColor="backgroundBackdrop"
width="full"
paddingTop={{ sm: '12', md: '16' }}
paddingBottom={{ sm: '12', md: '16' }}
>
<ActionsContainer> <ActionsContainer>
<Row gap="12"> <ActionsSubContainer>
<TraceEvent <TraceEvent
events={[Event.onClick]} events={[Event.onClick]}
element={ElementName.NFT_FILTER_BUTTON} element={ElementName.NFT_FILTER_BUTTON}
@ -439,12 +477,13 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
isMobile={isMobile} isMobile={isMobile}
isFiltersExpanded={isFiltersExpanded} isFiltersExpanded={isFiltersExpanded}
onClick={() => setFiltersExpanded(!isFiltersExpanded)} onClick={() => setFiltersExpanded(!isFiltersExpanded)}
collectionCount={collectionNfts?.[0]?.totalCount ?? 0}
/> />
</TraceEvent> </TraceEvent>
<SortDropdown dropDownOptions={sortDropDownOptions} /> <SortDropdownContainer isFiltersExpanded={isFiltersExpanded}>
<SortDropdown dropDownOptions={sortDropDownOptions} />
</SortDropdownContainer>
<CollectionSearch /> <CollectionSearch />
</Row> </ActionsSubContainer>
{!hasErc1155s ? ( {!hasErc1155s ? (
isLoading ? ( isLoading ? (
<LoadingButton /> <LoadingButton />
@ -463,7 +502,9 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
}} }}
> >
<SweepIcon viewBox="0 0 24 24" width="20px" height="20px" /> <SweepIcon viewBox="0 0 24 24" width="20px" height="20px" />
Sweep <SweepText fontWeight={600} color="currentColor" lineHeight="20px">
Sweep
</SweepText>
</SweepButton> </SweepButton>
) )
) : null} ) : null}

@ -13,13 +13,15 @@ export const CollectionSearch = () => {
return ( return (
<Box <Box
as="input" as="input"
flex="1"
borderColor={{ default: 'backgroundOutline', focus: 'genieBlue' }} borderColor={{ default: 'backgroundOutline', focus: 'genieBlue' }}
borderWidth="1.5px" borderWidth="1.5px"
borderStyle="solid" borderStyle="solid"
borderRadius="12" borderRadius="12"
padding="12" padding="12"
backgroundColor="backgroundSurface" backgroundColor="backgroundSurface"
width="332" maxWidth="332"
minWidth="0"
fontSize="16" fontSize="16"
height="44" height="44"
color={{ placeholder: 'textTertiary', default: 'textPrimary' }} color={{ placeholder: 'textTertiary', default: 'textPrimary' }}

@ -131,6 +131,7 @@ export const statsValue = style([
}), }),
{ {
lineHeight: '24px', 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 ( 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> <span className={styles.statsValue}>{children}</span>
<Box as="span" className={styles.statsLabel}> <Box as="span" className={styles.statsLabel}>
{label} {label}
@ -295,34 +295,34 @@ const StatsRow = ({ stats, isMobile, ...props }: { stats: GenieCollection; isMob
) : ( ) : (
<> <>
{stats.stats?.floor_price ? ( {stats.stats?.floor_price ? (
<StatsItem label="Global floor" isMobile={isMobile ?? false}> <StatsItem label="Global floor" shouldHide={false}>
{floorPriceStr} ETH {floorPriceStr} ETH
</StatsItem> </StatsItem>
) : null} ) : null}
{stats.stats?.one_day_floor_change ? ( {stats.stats?.one_day_floor_change ? (
<StatsItem label="24-Hour Floor" isMobile={isMobile ?? false}> <StatsItem label="24-Hour Floor" shouldHide={false}>
<PercentChange> <PercentChange>
{floorChangeStr}% {arrow} {floorChangeStr}% {arrow}
</PercentChange> </PercentChange>
</StatsItem> </StatsItem>
) : null} ) : null}
{totalSupplyStr ? ( {totalSupplyStr ? (
<StatsItem label="Items" isMobile={isMobile ?? false}> <StatsItem label="Items" shouldHide={isMobile ?? false}>
{totalSupplyStr} {totalSupplyStr}
</StatsItem> </StatsItem>
) : null} ) : null}
{uniqueOwnersPercentage ? ( {uniqueOwnersPercentage ? (
<StatsItem label="Unique owners" isMobile={isMobile ?? false}> <StatsItem label="Unique owners" shouldHide={isMobile ?? false}>
{uniqueOwnersPercentage}% {uniqueOwnersPercentage}%
</StatsItem> </StatsItem>
) : null} ) : null}
{stats.stats?.total_volume ? ( {stats.stats?.total_volume ? (
<StatsItem label="Total Volume" isMobile={isMobile ?? false}> <StatsItem label="Total Volume" shouldHide={false}>
{totalVolumeStr} ETH {totalVolumeStr} ETH
</StatsItem> </StatsItem>
) : null} ) : null}
{stats.stats?.total_listings && listedPercentageStr > 0 ? ( {stats.stats?.total_listings && listedPercentageStr > 0 ? (
<StatsItem label="Listed" isMobile={isMobile ?? false}> <StatsItem label="Listed" shouldHide={isMobile ?? false}>
{listedPercentageStr}% {listedPercentageStr}%
</StatsItem> </StatsItem>
) : null} ) : null}
@ -394,23 +394,15 @@ export const CollectionStats = ({ stats, isMobile }: { stats: GenieCollection; i
collectionSocialsIsOpen={collectionSocialsIsOpen} collectionSocialsIsOpen={collectionSocialsIsOpen}
toggleCollectionSocials={toggleCollectionSocials} toggleCollectionSocials={toggleCollectionSocials}
/> />
{!isMobile && ( {(stats.description || isCollectionStatsLoading) && !isMobile && (
<> <CollectionDescription description={stats.description ?? ''} />
{(stats.description || isCollectionStatsLoading) && (
<CollectionDescription description={stats.description ?? ''} />
)}
<StatsRow stats={stats} marginTop="20" />
</>
)} )}
<StatsRow display={{ sm: 'none', md: 'flex' }} stats={stats} marginTop="20" />
</Box> </Box>
{isMobile && ( {(stats.description || isCollectionStatsLoading) && isMobile && (
<> <CollectionDescription description={stats.description ?? ''} />
<Box marginBottom="12">{stats.description && <CollectionDescription description={stats.description} />}</Box>
<Marquee>
<StatsRow stats={stats} marginLeft="6" marginRight="6" marginBottom="28" isMobile />
</Marquee>
</>
)} )}
<StatsRow isMobile display={{ sm: 'flex', md: 'none' }} stats={stats} marginTop="20" marginBottom="12" />
</Box> </Box>
) )
} }

@ -1,43 +1,21 @@
import clsx from 'clsx' import clsx from 'clsx'
import { Box } from 'nft/components/Box' import { Box } from 'nft/components/Box'
import * as styles from 'nft/components/collection/FilterButton.css' import * as styles from 'nft/components/collection/FilterButton.css'
import { Row } from 'nft/components/Flex'
import { FilterIcon } from 'nft/components/icons' import { FilterIcon } from 'nft/components/icons'
import { buttonTextMedium } from 'nft/css/common.css' import { buttonTextMedium } from 'nft/css/common.css'
import { useCollectionFilters, useIsCollectionLoading, useWalletCollections } from 'nft/hooks' import { useIsCollectionLoading } from 'nft/hooks'
import { putCommas } from 'nft/utils/putCommas'
import { useLocation } from 'react-router-dom'
export const FilterButton = ({ export const FilterButton = ({
onClick, onClick,
isMobile, isMobile,
isFiltersExpanded, isFiltersExpanded,
results,
collectionCount = 0,
}: { }: {
isMobile: boolean isMobile: boolean
isFiltersExpanded: boolean isFiltersExpanded: boolean
results?: number
onClick: () => void 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 isCollectionNftsLoading = useIsCollectionLoading((state) => state.isCollectionNftsLoading)
const showFilterBadge = isProfilePage
? collectionFilters.length > 0
: minPrice || maxPrice || minRarity || maxRarity || traits.length || markets.length || buyNow
return ( return (
<Box <Box
className={ className={
@ -45,51 +23,21 @@ export const FilterButton = ({
? styles.filterButtonLoading ? styles.filterButtonLoading
: clsx(styles.filterButton, !isFiltersExpanded && styles.filterButtonExpanded) : clsx(styles.filterButton, !isFiltersExpanded && styles.filterButtonExpanded)
} }
display="flex"
gap="8"
borderRadius="12" borderRadius="12"
fontSize="16" fontSize="16"
cursor="pointer" cursor="pointer"
position="relative" position="relative"
onClick={onClick} onClick={onClick}
paddingTop="12" padding="12"
paddingLeft="12"
paddingBottom="12"
paddingRight={isMobile ? '8' : '12'}
width={isMobile ? '44' : 'auto'} width={isMobile ? '44' : 'auto'}
height="44" height="44"
whiteSpace="nowrap" whiteSpace="nowrap"
color="textPrimary"
> >
{!isCollectionNftsLoading && ( <FilterIcon />
<> {!isMobile && !isFiltersExpanded && <Box className={buttonTextMedium}> Filter</Box>}
{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}
</Box> </Box>
) )
} }

@ -193,7 +193,6 @@ export const ProfilePage = () => {
<FilterButton <FilterButton
isMobile={isMobile} isMobile={isMobile}
isFiltersExpanded={isFiltersExpanded} isFiltersExpanded={isFiltersExpanded}
results={displayAssets.length}
onClick={() => setFiltersExpanded(!isFiltersExpanded)} onClick={() => setFiltersExpanded(!isFiltersExpanded)}
/> />
<Row gap="8" flexWrap="nowrap"> <Row gap="8" flexWrap="nowrap">