style: Phase1 search polish (#5350)

* Polish search bar

* Additional search bar polish

* Polish styles and breakpoints

* Address comments

* Address comments

* Add useMemo

* Remove transitions
This commit is contained in:
Callil Capuozzo 2022-11-28 09:35:05 -05:00 committed by GitHub
parent b1fd484894
commit 448090b534
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 167 additions and 137 deletions

@ -3,11 +3,11 @@ import { buttonTextSmall, subhead, subheadSmall } from 'nft/css/common.css'
import { breakpoints, sprinkles, vars } from '../../nft/css/sprinkles.css' import { breakpoints, sprinkles, vars } from '../../nft/css/sprinkles.css'
const DESKTOP_NAVBAR_WIDTH = 360 const DESKTOP_NAVBAR_WIDTH = 330
const DESKTOP_NAVBAR_WIDTH_L = 440 const DESKTOP_NAVBAR_WIDTH_MD = 360
const DESKTOP_NAVBAR_WIDTH_XL = 540 const DESKTOP_NAVBAR_WIDTH_L = 480
const DESKTOP_NAVBAR_WIDTH_XL = 520
const DESKTOP_NAVBAR_WIDTH_XXL = 640 const DESKTOP_NAVBAR_WIDTH_XXL = 640
const MAGNIFYING_GLASS_ICON_WIDTH = 28
const baseSearchStyle = style([ const baseSearchStyle = style([
sprinkles({ sprinkles({
@ -15,12 +15,13 @@ const baseSearchStyle = style([
width: { sm: 'viewWidth' }, width: { sm: 'viewWidth' },
borderStyle: 'solid', borderStyle: 'solid',
borderWidth: '1px', borderWidth: '1px',
borderColor: 'backgroundOutline', borderColor: 'searchOutline',
}), }),
{ {
backdropFilter: 'blur(60px)',
'@media': { '@media': {
[`screen and (min-width: ${breakpoints.sm}px)`]: { [`screen and (min-width: ${breakpoints.sm}px)`]: {
width: `${DESKTOP_NAVBAR_WIDTH}px`, width: `${DESKTOP_NAVBAR_WIDTH_MD}px`,
}, },
}, },
}, },
@ -29,18 +30,20 @@ const baseSearchStyle = style([
const baseSearchNftStyle = style([ const baseSearchNftStyle = style([
baseSearchStyle, baseSearchStyle,
{ {
borderWidth: '2px',
'@media': { '@media': {
[`screen and (min-width: 1024px) and (max-width: 1080px)`]: { [`screen and (min-width: ${breakpoints.md}px)`]: {
width: `${330}px`, width: `${DESKTOP_NAVBAR_WIDTH}px`,
}, },
[`screen and (min-width: 1190px) and (max-width: 1380px)`]: { [`screen and (min-width: ${breakpoints.lg}px)`]: {
width: `${DESKTOP_NAVBAR_WIDTH_MD}px`,
},
[`screen and (min-width: ${breakpoints.xl}px)`]: {
width: `${DESKTOP_NAVBAR_WIDTH_L}px`, width: `${DESKTOP_NAVBAR_WIDTH_L}px`,
}, },
[`screen and (min-width: 1380px) and (max-width: 1479px)`]: { [`screen and (min-width: ${breakpoints.xxl}px)`]: {
width: `${DESKTOP_NAVBAR_WIDTH_XL}px`, width: `${DESKTOP_NAVBAR_WIDTH_XL}px`,
}, },
[`screen and (min-width: ${1480}px)`]: { [`screen and (min-width: ${breakpoints.xxxl}px)`]: {
width: `${DESKTOP_NAVBAR_WIDTH_XXL}px`, width: `${DESKTOP_NAVBAR_WIDTH_XXL}px`,
}, },
}, },
@ -54,14 +57,6 @@ export const searchBarContainer = style([
zIndex: '3', zIndex: '3',
display: 'inline-block', display: 'inline-block',
}), }),
{
'@media': {
[`screen and (min-width: ${breakpoints.lg}px)`]: {
right: `-${DESKTOP_NAVBAR_WIDTH / 2 - MAGNIFYING_GLASS_ICON_WIDTH}px`,
top: '-3px',
},
},
},
]) ])
export const searchBarContainerNft = style([ export const searchBarContainerNft = style([
@ -72,43 +67,35 @@ export const searchBarContainerNft = style([
display: 'inline-block', display: 'inline-block',
}), }),
{ {
'@media': { backdropFilter: 'blur(60px)',
[`screen and (min-width: ${breakpoints.lg}px)`]: { borderRadius: '12px',
right: `-${DESKTOP_NAVBAR_WIDTH / 2}px`, },
top: '-6px', ])
},
[`screen and (min-width: 1024px) and (max-width: 1080px)`]: { export const searchBarContainerNftOpen = style([
right: `-${300 / 2}px`, searchBarContainerNft,
}, {
[`screen and (min-width: 1190px) and (max-width: 1380px)`]: { boxShadow: vars.color.cardDropShadow,
right: `-${DESKTOP_NAVBAR_WIDTH_L / 2}px`,
},
[`screen and (min-width: 1380px) and (max-width: 1479px)`]: {
right: `-${DESKTOP_NAVBAR_WIDTH_XL / 2}px`,
},
[`screen and (min-width: ${1480}px)`]: {
right: `-${DESKTOP_NAVBAR_WIDTH_XXL / 2}px`,
},
},
}, },
]) ])
export const searchBar = style([ export const searchBar = style([
baseSearchStyle, baseSearchStyle,
sprinkles({ sprinkles({
color: 'textTertiary', color: 'textSecondary',
paddingX: '16', paddingX: '16',
background: 'backgroundSurface',
}), }),
]) ])
export const nftSearchBar = style([ export const nftSearchBar = style([
baseSearchNftStyle, baseSearchNftStyle,
sprinkles({ sprinkles({
color: 'textTertiary', color: 'textSecondary',
paddingX: '16', paddingX: '16',
background: 'backgroundSurface',
}), }),
{
backdropFilter: 'blur(60px)',
},
]) ])
export const searchBarInput = style([ export const searchBarInput = style([
@ -116,7 +103,7 @@ export const searchBarInput = style([
padding: '0', padding: '0',
fontWeight: 'normal', fontWeight: 'normal',
fontSize: '16', fontSize: '16',
color: { default: 'textPrimary', placeholder: 'textTertiary' }, color: { default: 'textPrimary', placeholder: 'textSecondary' },
border: 'none', border: 'none',
background: 'none', background: 'none',
lineHeight: '24', lineHeight: '24',
@ -129,12 +116,9 @@ export const searchBarDropdown = style([
sprinkles({ sprinkles({
borderBottomLeftRadius: '12', borderBottomLeftRadius: '12',
borderBottomRightRadius: '12', borderBottomRightRadius: '12',
background: 'backgroundSurface',
height: { sm: 'viewHeight', md: 'auto' }, height: { sm: 'viewHeight', md: 'auto' },
}),
{
borderTop: 'none', borderTop: 'none',
}, }),
]) ])
export const searchBarDropdownNft = style([ export const searchBarDropdownNft = style([
@ -142,10 +126,11 @@ export const searchBarDropdownNft = style([
sprinkles({ sprinkles({
borderBottomLeftRadius: '12', borderBottomLeftRadius: '12',
borderBottomRightRadius: '12', borderBottomRightRadius: '12',
background: 'backgroundSurface',
height: { sm: 'viewHeight', md: 'auto' }, height: { sm: 'viewHeight', md: 'auto' },
backgroundColor: 'backgroundSurface',
}), }),
{ {
backdropFilter: 'blur(60px)',
borderTop: 'none', borderTop: 'none',
}, },
]) ])
@ -243,9 +228,6 @@ export const notFoundContainer = style([
}), }),
]) ])
const visibilityTransition = `visibility ${vars.time[125]}, opacity ${vars.time[125]}`
const delayedTransitionProperties = `padding 0s ${vars.time[125]}, height 0s ${vars.time[125]}`
export const hidden = style([ export const hidden = style([
sprinkles({ sprinkles({
visibility: 'hidden', visibility: 'hidden',
@ -253,10 +235,6 @@ export const hidden = style([
padding: '0', padding: '0',
height: '0', height: '0',
}), }),
{
transition: `${visibilityTransition}, ${delayedTransitionProperties}`,
transitionTimingFunction: 'ease-in',
},
]) ])
export const visible = style([ export const visible = style([
sprinkles({ sprinkles({
@ -264,10 +242,6 @@ export const visible = style([
opacity: '1', opacity: '1',
height: 'full', height: 'full',
}), }),
{
transition: `${visibilityTransition}`,
transitionTimingFunction: 'ease-out',
},
]) ])
export const searchContentCentered = style({ export const searchContentCentered = style({

@ -14,15 +14,32 @@ import { magicalGradientOnHover } from 'nft/css/common.css'
import { useIsMobile, useIsTablet } from 'nft/hooks' import { useIsMobile, useIsTablet } from 'nft/hooks'
import { fetchSearchCollections } from 'nft/queries' import { fetchSearchCollections } from 'nft/queries'
import { fetchSearchTokens } from 'nft/queries/genie/SearchTokensFetcher' import { fetchSearchTokens } from 'nft/queries/genie/SearchTokensFetcher'
import { ChangeEvent, useEffect, useReducer, useRef, useState } from 'react' import { ChangeEvent, useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'
import { useQuery } from 'react-query' import { useQuery } from 'react-query'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import styled from 'styled-components/macro'
import { ChevronLeftIcon, MagnifyingGlassIcon, NavMagnifyingGlassIcon } from '../../nft/components/icons' import { ChevronLeftIcon, MagnifyingGlassIcon, NavMagnifyingGlassIcon } from '../../nft/components/icons'
import { NavIcon } from './NavIcon' import { NavIcon } from './NavIcon'
import * as styles from './SearchBar.css' import * as styles from './SearchBar.css'
import { SearchBarDropdown } from './SearchBarDropdown' import { SearchBarDropdown } from './SearchBarDropdown'
const KeyShortCut = styled.div`
background-color: ${({ theme }) => theme.searchOutline};
color: ${({ theme }) => theme.textSecondary};
padding: 0px 8px;
width: 20px;
height: 20px;
border-radius: 4px;
font-size: 12px;
font-weight: 800;
line-height: 16px;
display: flex;
align-items: center;
opacity: 0.6;
backdrop-filter: blur(60px);
`
export const SearchBar = () => { export const SearchBar = () => {
const [isOpen, toggleOpen] = useReducer((state: boolean) => !state, false) const [isOpen, toggleOpen] = useReducer((state: boolean) => !state, false)
const [searchValue, setSearchValue] = useState('') const [searchValue, setSearchValue] = useState('')
@ -93,7 +110,6 @@ export const SearchBar = () => {
} }
}, [isOpen]) }, [isOpen])
const placeholderText = phase1Flag === NftVariant.Enabled ? t`Search tokens and NFT collections` : t`Search tokens`
const isMobileOrTablet = isMobile || isTablet const isMobileOrTablet = isMobile || isTablet
const showCenteredSearchContent = const showCenteredSearchContent =
!isOpen && phase1Flag !== NftVariant.Enabled && !isMobileOrTablet && searchValue.length === 0 !isOpen && phase1Flag !== NftVariant.Enabled && !isMobileOrTablet && searchValue.length === 0
@ -105,78 +121,112 @@ export const SearchBar = () => {
hasInput: debouncedSearchValue && debouncedSearchValue.length > 0, hasInput: debouncedSearchValue && debouncedSearchValue.length > 0,
...trace, ...trace,
} }
const placeholderText = useMemo(() => {
return phase1Flag === NftVariant.Enabled
? isMobileOrTablet
? t`Search`
: t`Search tokens and NFT collections`
: t`Search tokens`
}, [phase1Flag, isMobileOrTablet])
const handleKeyPress = useCallback(
(event: any) => {
if (event.key === '/') {
event.preventDefault()
!isOpen && toggleOpen()
}
},
[isOpen]
)
useEffect(() => {
const innerRef = inputRef.current
if (innerRef !== null) {
//only mount the listener when input available as ref
document.addEventListener('keydown', handleKeyPress)
}
return () => {
if (innerRef !== null) {
document.removeEventListener('keydown', handleKeyPress)
}
}
}, [handleKeyPress, inputRef])
return ( return (
<Box position="relative"> <Trace section={SectionName.NAVBAR_SEARCH}>
<Trace section={SectionName.NAVBAR_SEARCH}> <Box
<Box position={{ sm: 'fixed', md: 'absolute', xl: 'relative' }}
position={{ sm: 'fixed', md: 'absolute' }} width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }}
width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }} ref={searchRef}
ref={searchRef} className={isPhase1 ? styles.searchBarContainerNft : styles.searchBarContainer}
className={isPhase1 ? styles.searchBarContainerNft : styles.searchBarContainer} display={{ sm: isOpen ? 'inline-block' : 'none', xl: 'inline-block' }}
display={{ sm: isOpen ? 'inline-block' : 'none', xl: 'inline-block' }} >
<Row
className={clsx(
` ${isPhase1 ? styles.nftSearchBar : styles.searchBar} ${!isOpen && !isMobile && magicalGradientOnHover} ${
isMobileOrTablet && (isOpen ? styles.visible : styles.hidden)
} `
)}
borderRadius={isOpen || isMobileOrTablet ? undefined : '12'}
borderTopRightRadius={isOpen && !isMobile ? '12' : undefined}
borderTopLeftRadius={isOpen && !isMobile ? '12' : undefined}
borderBottomWidth={isOpen || isMobileOrTablet ? '0px' : '1px'}
backgroundColor={isOpen ? 'backgroundSurface' : 'searchBackground'}
onClick={() => !isOpen && toggleOpen()}
gap="12"
> >
<Row <Box className={showCenteredSearchContent ? styles.searchContentCentered : styles.searchContentLeftAlign}>
className={clsx( <Box display={{ sm: 'none', md: 'flex' }}>
` ${isPhase1 ? styles.nftSearchBar : styles.searchBar} ${ <MagnifyingGlassIcon />
!isOpen && !isMobile && magicalGradientOnHover </Box>
} ${isMobileOrTablet && (isOpen ? styles.visible : styles.hidden)}` <Box display={{ sm: 'flex', md: 'none' }} color="textTertiary" onClick={toggleOpen}>
)} <ChevronLeftIcon />
borderRadius={isOpen || isMobileOrTablet ? undefined : '12'}
borderTopRightRadius={isOpen && !isMobile ? '12' : undefined}
borderTopLeftRadius={isOpen && !isMobile ? '12' : undefined}
borderBottomWidth={isOpen || isMobileOrTablet ? '0px' : isPhase1 ? '2px' : '1px'}
onClick={() => !isOpen && toggleOpen()}
gap="12"
>
<Box className={showCenteredSearchContent ? styles.searchContentCentered : styles.searchContentLeftAlign}>
<Box display={{ sm: 'none', md: 'flex' }}>
<MagnifyingGlassIcon />
</Box>
<Box display={{ sm: 'flex', md: 'none' }} color="textTertiary" onClick={toggleOpen}>
<ChevronLeftIcon />
</Box>
</Box> </Box>
<TraceEvent
events={[BrowserEvent.onFocus]}
name={EventName.NAVBAR_SEARCH_SELECTED}
element={ElementName.NAVBAR_SEARCH_INPUT}
properties={{ ...trace }}
>
<Box
as="input"
placeholder={placeholderText}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
!isOpen && toggleOpen()
setSearchValue(event.target.value)
}}
onBlur={() => sendAnalyticsEvent(EventName.NAVBAR_SEARCH_EXITED, navbarSearchEventProperties)}
className={`${styles.searchBarInput} ${
showCenteredSearchContent ? styles.searchContentCentered : styles.searchContentLeftAlign
}`}
value={searchValue}
ref={inputRef}
width={phase1Flag === NftVariant.Enabled || isOpen ? 'full' : '160'}
/>
</TraceEvent>
</Row>
<Box className={clsx(isOpen ? styles.visible : styles.hidden)}>
{isOpen && (
<SearchBarDropdown
toggleOpen={toggleOpen}
tokens={reducedTokens}
collections={reducedCollections}
queryText={debouncedSearchValue}
hasInput={debouncedSearchValue.length > 0}
isLoading={tokensAreLoading || (collectionsAreLoading && phase1Flag === NftVariant.Enabled)}
/>
)}
</Box> </Box>
<TraceEvent
events={[BrowserEvent.onFocus]}
name={EventName.NAVBAR_SEARCH_SELECTED}
element={ElementName.NAVBAR_SEARCH_INPUT}
properties={{ ...trace }}
>
<Box
as="input"
placeholder={placeholderText}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
!isOpen && toggleOpen()
setSearchValue(event.target.value)
}}
onBlur={() => sendAnalyticsEvent(EventName.NAVBAR_SEARCH_EXITED, navbarSearchEventProperties)}
className={`${styles.searchBarInput} ${
showCenteredSearchContent ? styles.searchContentCentered : styles.searchContentLeftAlign
}`}
value={searchValue}
ref={inputRef}
width={phase1Flag === NftVariant.Enabled || isOpen ? 'full' : '160'}
/>
</TraceEvent>
{!isOpen && isPhase1 && <KeyShortCut>/</KeyShortCut>}
</Row>
<Box className={clsx(isOpen ? styles.visible : styles.hidden)}>
{isOpen && (
<SearchBarDropdown
toggleOpen={toggleOpen}
tokens={reducedTokens}
collections={reducedCollections}
queryText={debouncedSearchValue}
hasInput={debouncedSearchValue.length > 0}
isLoading={tokensAreLoading || (collectionsAreLoading && phase1Flag === NftVariant.Enabled)}
/>
)}
</Box> </Box>
</Box>
{isMobileOrTablet && (
<NavIcon onClick={toggleOpen}> <NavIcon onClick={toggleOpen}>
<NavMagnifyingGlassIcon /> <NavMagnifyingGlassIcon />
</NavIcon> </NavIcon>
</Trace> )}
</Box> </Trace>
) )
} }

@ -87,16 +87,16 @@ const Navbar = () => {
<ChainSelector leftAlign={true} /> <ChainSelector leftAlign={true} />
</Box> </Box>
)} )}
<Row gap="8" display={{ sm: 'none', lg: 'flex' }}> <Row gap={{ xl: '0', xxl: '8' }} display={{ sm: 'none', lg: 'flex' }}>
<PageTabs /> <PageTabs />
</Row> </Row>
</Box> </Box>
<Box className={styles.middleContainer}> <Box className={styles.middleContainer} alignItems="flex-start">
<SearchBar /> <SearchBar />
</Box> </Box>
<Box className={styles.rightSideContainer}> <Box className={styles.rightSideContainer}>
<Row gap="12"> <Row gap="12">
<Box display={{ sm: 'flex', xl: 'none' }}> <Box position="relative" display={{ sm: 'flex', xl: 'none' }}>
<SearchBar /> <SearchBar />
</Box> </Box>
<Box display={{ sm: 'none', lg: 'flex' }}> <Box display={{ sm: 'none', lg: 'flex' }}>

@ -29,14 +29,7 @@ export const logo = style([
}), }),
]) ])
export const baseContainer = style([
sprinkles({
alignItems: 'center',
}),
])
export const baseSideContainer = style([ export const baseSideContainer = style([
baseContainer,
sprinkles({ sprinkles({
display: 'flex', display: 'flex',
width: 'full', width: 'full',
@ -53,12 +46,12 @@ export const leftSideContainer = style([
]) ])
export const middleContainer = style([ export const middleContainer = style([
baseContainer,
sprinkles({ sprinkles({
flex: '1', flex: '1',
flexShrink: '1', flexShrink: '1',
justifyContent: 'center', justifyContent: { lg: 'flex-end', xl: 'center' },
display: { sm: 'none', xl: 'flex' }, display: { sm: 'none', xl: 'flex' },
alignItems: 'flex-start',
}), }),
]) ])

@ -23,6 +23,9 @@ const themeContractValues = {
modalBackdrop: '', modalBackdrop: '',
searchBackground: '',
searchOutline: '',
stateOverlayHover: '', stateOverlayHover: '',
textPrimary: '', textPrimary: '',

@ -22,6 +22,8 @@ export const darkTheme: Theme = {
modalBackdrop: 'linear-gradient(0deg, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7))', modalBackdrop: 'linear-gradient(0deg, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7))',
searchBackground: `rgba(255,255,255,0.07)`,
searchOutline: `rgba(255,255,255,0.07)`,
stateOverlayHover: `rgba(153,161,189,0.08)`, stateOverlayHover: `rgba(153,161,189,0.08)`,
textPrimary: '#FFFFFF', textPrimary: '#FFFFFF',

@ -19,6 +19,8 @@ export const lightTheme: Theme = {
modalBackdrop: 'rgba(0, 0, 0, 0.3)', modalBackdrop: 'rgba(0, 0, 0, 0.3)',
searchBackground: `rgba(255,255,255,0.4)`,
searchOutline: `rgba(0,0,0,0.1)`,
stateOverlayHover: `rgba(153,161,189,0.08)`, stateOverlayHover: `rgba(153,161,189,0.08)`,
green: vars.color.green400, green: vars.color.green400,
gold: vars.color.gold400, gold: vars.color.gold400,

@ -167,6 +167,9 @@ export const darkTheme = {
stateOverlayHover: opacify(8, colors.gray300), stateOverlayHover: opacify(8, colors.gray300),
stateOverlayPressed: opacify(24, colors.gray200), stateOverlayPressed: opacify(24, colors.gray200),
searchBackground: `rgba(255,255,255,0.07)`,
searchOutline: `rgba(255,255,255,0.07)`,
} }
export const lightTheme: Theme = { export const lightTheme: Theme = {
@ -218,4 +221,7 @@ export const lightTheme: Theme = {
stateOverlayHover: opacify(8, colors.gray300), stateOverlayHover: opacify(8, colors.gray300),
stateOverlayPressed: opacify(24, colors.gray200), stateOverlayPressed: opacify(24, colors.gray200),
searchBackground: opacify(4, colors.white),
searchOutline: opacify(1, colors.black),
} }