diff --git a/src/nft/components/collection/CollectionNfts.tsx b/src/nft/components/collection/CollectionNfts.tsx index 04ed28d89f..ae8f6c61b0 100644 --- a/src/nft/components/collection/CollectionNfts.tsx +++ b/src/nft/components/collection/CollectionNfts.tsx @@ -4,6 +4,7 @@ import { CollectionAsset } from 'nft/components/collection/CollectionAsset' import * as styles from 'nft/components/collection/CollectionNfts.css' import { Center } from 'nft/components/Flex' import { bodySmall, buttonTextMedium, header2 } from 'nft/css/common.css' +import { useCollectionFilters } from 'nft/hooks' import { AssetsFetcher } from 'nft/queries' import { useMemo } from 'react' import InfiniteScroll from 'react-infinite-scroll-component' @@ -14,6 +15,8 @@ interface CollectionNftsProps { } export const CollectionNfts = ({ contractAddress }: CollectionNftsProps) => { + const buyNow = useCollectionFilters((state) => state.buyNow) + const { data: collectionAssets, isSuccess: AssetsFetchSuccess, @@ -24,11 +27,13 @@ export const CollectionNfts = ({ contractAddress }: CollectionNftsProps) => { 'collectionNfts', { contractAddress, + notForSale: !buyNow, }, ], async ({ pageParam = 0 }) => { return await AssetsFetcher({ contractAddress, + notForSale: !buyNow, pageParam, }) }, diff --git a/src/nft/components/collection/FilterButton.css.ts b/src/nft/components/collection/FilterButton.css.ts new file mode 100644 index 0000000000..02ea134ddf --- /dev/null +++ b/src/nft/components/collection/FilterButton.css.ts @@ -0,0 +1,23 @@ +import { style } from '@vanilla-extract/css' +import { sprinkles, themeVars, vars } from 'nft/css/sprinkles.css' + +export const filterButton = sprinkles({ + backgroundColor: 'blue400', + color: 'explicitWhite', +}) + +export const filterButtonExpanded = style({ + background: vars.color.lightGrayButton, + color: themeVars.colors.blackBlue, +}) + +export const filterBadge = style([ + sprinkles({ + position: 'absolute', + left: '18', + fontSize: '28', + }), + { + top: '-3px', + }, +]) diff --git a/src/nft/components/collection/FilterButton.tsx b/src/nft/components/collection/FilterButton.tsx new file mode 100644 index 0000000000..04a3e7d0ff --- /dev/null +++ b/src/nft/components/collection/FilterButton.tsx @@ -0,0 +1,69 @@ +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 { useCollectionFilters } from 'nft/hooks' +import { putCommas } from 'nft/utils/putCommas' + +export const FilterButton = ({ + onClick, + isMobile, + isFiltersExpanded, + results, +}: { + isMobile: boolean + isFiltersExpanded: boolean + results?: number + onClick: () => void +}) => { + 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 showFilterBadge = minPrice || maxPrice || minRarity || maxRarity || traits.length || markets.length || buyNow + return ( + + {showFilterBadge && ( + + • + + )} + + {!isMobile && !isFiltersExpanded && 'Filter'} + + {showFilterBadge && !isMobile ? ( + + {!isFiltersExpanded && ( + + • + + )} + {results ? putCommas(results) : 0} results + + ) : null} + + ) +} diff --git a/src/nft/components/collection/Filters.css.ts b/src/nft/components/collection/Filters.css.ts new file mode 100644 index 0000000000..119b67281f --- /dev/null +++ b/src/nft/components/collection/Filters.css.ts @@ -0,0 +1,82 @@ +import { style } from '@vanilla-extract/css' +import { breakpoints, sprinkles, themeVars } from 'nft/css/sprinkles.css' + +export const container = style([ + sprinkles({ + overflow: 'auto', + height: 'viewHeight', + paddingTop: '24', + }), + { + width: '300px', + paddingBottom: '96px', + '@media': { + [`(max-width: ${breakpoints.sm - 1}px)`]: { + width: 'auto', + height: 'auto', + paddingBottom: '0px', + }, + }, + selectors: { + '&::-webkit-scrollbar': { + display: 'none', + }, + }, + }, +]) + +export const rowHover = style([ + sprinkles({ + borderRadius: '12', + }), + { + ':hover': { + background: themeVars.colors.lightGray, + }, + }, +]) + +export const rowHoverOpen = style([ + sprinkles({ + borderTopLeftRadius: '12', + borderTopRightRadius: '12', + borderBottomLeftRadius: '0', + borderBottomRightRadius: '0', + }), + { + ':hover': { + background: themeVars.colors.medGray, + }, + }, +]) + +export const subRowHover = style({ + ':hover': { + background: themeVars.colors.medGray, + }, +}) + +export const detailsOpen = sprinkles({ + background: 'darkGray10', + overflow: 'hidden', + borderStyle: 'solid', + borderWidth: '1px', + borderColor: 'medGray', +}) + +export const summaryOpen = sprinkles({ + borderStyle: 'solid', + borderWidth: '1px', + borderColor: 'medGray', +}) + +export const filterDropDowns = style([ + sprinkles({ + overflowY: 'scroll', + }), + { + maxHeight: '190px', + '::-webkit-scrollbar': { display: 'none' }, + scrollbarWidth: 'none', + }, +]) diff --git a/src/nft/components/collection/Filters.tsx b/src/nft/components/collection/Filters.tsx new file mode 100644 index 0000000000..ce5dce238a --- /dev/null +++ b/src/nft/components/collection/Filters.tsx @@ -0,0 +1,51 @@ +import { Box } from 'nft/components/Box' +import * as styles from 'nft/components/collection/Filters.css' +import { Column, Row } from 'nft/components/Flex' +import { Radio } from 'nft/components/layout/Radio' +import { useCollectionFilters } from 'nft/hooks' +import { useReducer } from 'react' + +export const Filters = () => { + const { buyNow, setBuyNow } = useCollectionFilters((state) => ({ + buyNow: state.buyNow, + setBuyNow: state.setBuyNow, + })) + const [buyNowHovered, toggleBuyNowHover] = useReducer((state) => !state, false) + + const handleBuyNowToggle = () => { + setBuyNow(!buyNow) + } + + return ( + + + + Filters + + + + { + e.preventDefault() + handleBuyNowToggle() + }} + onMouseEnter={toggleBuyNowHover} + onMouseLeave={toggleBuyNowHover} + > + + Buy now + + + + + + ) +} diff --git a/src/nft/components/collection/index.ts b/src/nft/components/collection/index.ts new file mode 100644 index 0000000000..6d254dddb1 --- /dev/null +++ b/src/nft/components/collection/index.ts @@ -0,0 +1,4 @@ +export { CollectionNfts } from './CollectionNfts' +export { CollectionStats } from './CollectionStats' +export { FilterButton } from './FilterButton' +export { Filters } from './Filters' diff --git a/src/nft/components/layout/Radio.css.ts b/src/nft/components/layout/Radio.css.ts new file mode 100644 index 0000000000..9afcb1b686 --- /dev/null +++ b/src/nft/components/layout/Radio.css.ts @@ -0,0 +1,53 @@ +import { style } from '@vanilla-extract/css' +import { sprinkles, vars } from 'nft/css/sprinkles.css' + +export const radio = style([ + sprinkles({ + position: 'relative', + display: 'inline-block', + height: '24', + width: '24', + cursor: 'pointer', + background: 'transparent', + borderRadius: { default: 'round', before: 'round' }, + borderStyle: 'solid', + borderWidth: '2px', + top: '0', + left: '0', + right: '0', + bottom: '0', + transition: { + default: '250', + before: '250', + }, + }), +]) + +export const greyBorderRadio = style([ + radio, + sprinkles({ + borderColor: 'grey400', + }), +]) + +export const blueBorderRadio = style([ + radio, + sprinkles({ + borderColor: 'blue400', + }), +]) + +export const selectedRadio = style([ + blueBorderRadio, + { + ':before': { + position: 'absolute', + backgroundColor: vars.color.blue400, + content: '', + height: '14px', + width: '14px', + top: 3, + left: 3, + }, + }, +]) diff --git a/src/nft/components/layout/Radio.tsx b/src/nft/components/layout/Radio.tsx new file mode 100644 index 0000000000..3bc530d39e --- /dev/null +++ b/src/nft/components/layout/Radio.tsx @@ -0,0 +1,21 @@ +import { Box } from 'nft/components/Box' +import * as styles from 'nft/components/layout/Radio.css' +import { MouseEvent } from 'react' + +interface RadioProps { + hovered: boolean + checked: boolean + onClick: (e: MouseEvent) => void +} + +export const Radio = ({ hovered, checked, onClick }: RadioProps) => { + return ( + + ) +} + +Radio.displayName = 'Radio' diff --git a/src/nft/pages/collection/index.tsx b/src/nft/pages/collection/index.tsx index 839186f2cd..fc36d82659 100644 --- a/src/nft/pages/collection/index.tsx +++ b/src/nft/pages/collection/index.tsx @@ -1,22 +1,31 @@ import { AnimatedBox, Box } from 'nft/components/Box' -import { CollectionNfts } from 'nft/components/collection/CollectionNfts' -import { CollectionStats } from 'nft/components/collection/CollectionStats' +import { CollectionNfts, CollectionStats, FilterButton, Filters } from 'nft/components/collection' import { Column, Row } from 'nft/components/Flex' -import { useIsMobile } from 'nft/hooks/useIsMobile' +import { useFiltersExpanded, useIsMobile } from 'nft/hooks' import * as styles from 'nft/pages/collection/index.css' import { CollectionStatsFetcher } from 'nft/queries' import { useQuery } from 'react-query' import { useParams } from 'react-router-dom' +import { useSpring } from 'react-spring/web' + +const FILTER_WIDTH = 332 const Collection = () => { const { contractAddress } = useParams() const isMobile = useIsMobile() + const [isFiltersExpanded, setFiltersExpanded] = useFiltersExpanded() const { data: collectionStats } = useQuery(['collectionStats', contractAddress], () => CollectionStatsFetcher(contractAddress as string) ) + /// @reviewer these look the same now but will be diff later + const { gridX, gridWidthOffset } = useSpring({ + gridX: isFiltersExpanded ? FILTER_WIDTH : 0, + gridWidthOffset: isFiltersExpanded ? FILTER_WIDTH : 0, + }) + return ( @@ -34,8 +43,30 @@ const Collection = () => { )} - - + + + {isFiltersExpanded && } + + + {/* @ts-ignore: https://github.com/microsoft/TypeScript/issues/34933 */} + `translate(${x as number}px)`), + width: gridWidthOffset.interpolate((x) => `calc(100% - ${x as number}px)`), + }} + > + + + + setFiltersExpanded(!isFiltersExpanded)} + /> + + + + {contractAddress && } diff --git a/src/nft/utils/index.ts b/src/nft/utils/index.ts new file mode 100644 index 0000000000..7e38dd39ed --- /dev/null +++ b/src/nft/utils/index.ts @@ -0,0 +1,5 @@ +export * from './buildActivityAsset' +export * from './buildSellObject' +export * from './calcPoolPrice' +export * from './currency' +export * from './listNfts'