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:
parent
b1fd484894
commit
448090b534
@ -3,11 +3,11 @@ import { buttonTextSmall, subhead, subheadSmall } from 'nft/css/common.css'
|
||||
|
||||
import { breakpoints, sprinkles, vars } from '../../nft/css/sprinkles.css'
|
||||
|
||||
const DESKTOP_NAVBAR_WIDTH = 360
|
||||
const DESKTOP_NAVBAR_WIDTH_L = 440
|
||||
const DESKTOP_NAVBAR_WIDTH_XL = 540
|
||||
const DESKTOP_NAVBAR_WIDTH = 330
|
||||
const DESKTOP_NAVBAR_WIDTH_MD = 360
|
||||
const DESKTOP_NAVBAR_WIDTH_L = 480
|
||||
const DESKTOP_NAVBAR_WIDTH_XL = 520
|
||||
const DESKTOP_NAVBAR_WIDTH_XXL = 640
|
||||
const MAGNIFYING_GLASS_ICON_WIDTH = 28
|
||||
|
||||
const baseSearchStyle = style([
|
||||
sprinkles({
|
||||
@ -15,12 +15,13 @@ const baseSearchStyle = style([
|
||||
width: { sm: 'viewWidth' },
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '1px',
|
||||
borderColor: 'backgroundOutline',
|
||||
borderColor: 'searchOutline',
|
||||
}),
|
||||
{
|
||||
backdropFilter: 'blur(60px)',
|
||||
'@media': {
|
||||
[`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([
|
||||
baseSearchStyle,
|
||||
{
|
||||
borderWidth: '2px',
|
||||
'@media': {
|
||||
[`screen and (min-width: 1024px) and (max-width: 1080px)`]: {
|
||||
width: `${330}px`,
|
||||
[`screen and (min-width: ${breakpoints.md}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`,
|
||||
},
|
||||
[`screen and (min-width: 1380px) and (max-width: 1479px)`]: {
|
||||
[`screen and (min-width: ${breakpoints.xxl}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`,
|
||||
},
|
||||
},
|
||||
@ -54,14 +57,6 @@ export const searchBarContainer = style([
|
||||
zIndex: '3',
|
||||
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([
|
||||
@ -72,43 +67,35 @@ export const searchBarContainerNft = style([
|
||||
display: 'inline-block',
|
||||
}),
|
||||
{
|
||||
'@media': {
|
||||
[`screen and (min-width: ${breakpoints.lg}px)`]: {
|
||||
right: `-${DESKTOP_NAVBAR_WIDTH / 2}px`,
|
||||
top: '-6px',
|
||||
},
|
||||
[`screen and (min-width: 1024px) and (max-width: 1080px)`]: {
|
||||
right: `-${300 / 2}px`,
|
||||
},
|
||||
[`screen and (min-width: 1190px) and (max-width: 1380px)`]: {
|
||||
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`,
|
||||
},
|
||||
},
|
||||
backdropFilter: 'blur(60px)',
|
||||
borderRadius: '12px',
|
||||
},
|
||||
])
|
||||
|
||||
export const searchBarContainerNftOpen = style([
|
||||
searchBarContainerNft,
|
||||
{
|
||||
boxShadow: vars.color.cardDropShadow,
|
||||
},
|
||||
])
|
||||
|
||||
export const searchBar = style([
|
||||
baseSearchStyle,
|
||||
sprinkles({
|
||||
color: 'textTertiary',
|
||||
color: 'textSecondary',
|
||||
paddingX: '16',
|
||||
background: 'backgroundSurface',
|
||||
}),
|
||||
])
|
||||
|
||||
export const nftSearchBar = style([
|
||||
baseSearchNftStyle,
|
||||
sprinkles({
|
||||
color: 'textTertiary',
|
||||
color: 'textSecondary',
|
||||
paddingX: '16',
|
||||
background: 'backgroundSurface',
|
||||
}),
|
||||
{
|
||||
backdropFilter: 'blur(60px)',
|
||||
},
|
||||
])
|
||||
|
||||
export const searchBarInput = style([
|
||||
@ -116,7 +103,7 @@ export const searchBarInput = style([
|
||||
padding: '0',
|
||||
fontWeight: 'normal',
|
||||
fontSize: '16',
|
||||
color: { default: 'textPrimary', placeholder: 'textTertiary' },
|
||||
color: { default: 'textPrimary', placeholder: 'textSecondary' },
|
||||
border: 'none',
|
||||
background: 'none',
|
||||
lineHeight: '24',
|
||||
@ -129,12 +116,9 @@ export const searchBarDropdown = style([
|
||||
sprinkles({
|
||||
borderBottomLeftRadius: '12',
|
||||
borderBottomRightRadius: '12',
|
||||
background: 'backgroundSurface',
|
||||
height: { sm: 'viewHeight', md: 'auto' },
|
||||
}),
|
||||
{
|
||||
borderTop: 'none',
|
||||
},
|
||||
}),
|
||||
])
|
||||
|
||||
export const searchBarDropdownNft = style([
|
||||
@ -142,10 +126,11 @@ export const searchBarDropdownNft = style([
|
||||
sprinkles({
|
||||
borderBottomLeftRadius: '12',
|
||||
borderBottomRightRadius: '12',
|
||||
background: 'backgroundSurface',
|
||||
height: { sm: 'viewHeight', md: 'auto' },
|
||||
backgroundColor: 'backgroundSurface',
|
||||
}),
|
||||
{
|
||||
backdropFilter: 'blur(60px)',
|
||||
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([
|
||||
sprinkles({
|
||||
visibility: 'hidden',
|
||||
@ -253,10 +235,6 @@ export const hidden = style([
|
||||
padding: '0',
|
||||
height: '0',
|
||||
}),
|
||||
{
|
||||
transition: `${visibilityTransition}, ${delayedTransitionProperties}`,
|
||||
transitionTimingFunction: 'ease-in',
|
||||
},
|
||||
])
|
||||
export const visible = style([
|
||||
sprinkles({
|
||||
@ -264,10 +242,6 @@ export const visible = style([
|
||||
opacity: '1',
|
||||
height: 'full',
|
||||
}),
|
||||
{
|
||||
transition: `${visibilityTransition}`,
|
||||
transitionTimingFunction: 'ease-out',
|
||||
},
|
||||
])
|
||||
|
||||
export const searchContentCentered = style({
|
||||
|
@ -14,15 +14,32 @@ import { magicalGradientOnHover } from 'nft/css/common.css'
|
||||
import { useIsMobile, useIsTablet } from 'nft/hooks'
|
||||
import { fetchSearchCollections } from 'nft/queries'
|
||||
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 { useLocation } from 'react-router-dom'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { ChevronLeftIcon, MagnifyingGlassIcon, NavMagnifyingGlassIcon } from '../../nft/components/icons'
|
||||
import { NavIcon } from './NavIcon'
|
||||
import * as styles from './SearchBar.css'
|
||||
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 = () => {
|
||||
const [isOpen, toggleOpen] = useReducer((state: boolean) => !state, false)
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
@ -93,7 +110,6 @@ export const SearchBar = () => {
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
const placeholderText = phase1Flag === NftVariant.Enabled ? t`Search tokens and NFT collections` : t`Search tokens`
|
||||
const isMobileOrTablet = isMobile || isTablet
|
||||
const showCenteredSearchContent =
|
||||
!isOpen && phase1Flag !== NftVariant.Enabled && !isMobileOrTablet && searchValue.length === 0
|
||||
@ -105,78 +121,112 @@ export const SearchBar = () => {
|
||||
hasInput: debouncedSearchValue && debouncedSearchValue.length > 0,
|
||||
...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 (
|
||||
<Box position="relative">
|
||||
<Trace section={SectionName.NAVBAR_SEARCH}>
|
||||
<Box
|
||||
position={{ sm: 'fixed', md: 'absolute' }}
|
||||
width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }}
|
||||
ref={searchRef}
|
||||
className={isPhase1 ? styles.searchBarContainerNft : styles.searchBarContainer}
|
||||
display={{ sm: isOpen ? 'inline-block' : 'none', xl: 'inline-block' }}
|
||||
<Trace section={SectionName.NAVBAR_SEARCH}>
|
||||
<Box
|
||||
position={{ sm: 'fixed', md: 'absolute', xl: 'relative' }}
|
||||
width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }}
|
||||
ref={searchRef}
|
||||
className={isPhase1 ? styles.searchBarContainerNft : styles.searchBarContainer}
|
||||
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
|
||||
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' : 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 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>
|
||||
<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>
|
||||
<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>
|
||||
{isMobileOrTablet && (
|
||||
<NavIcon onClick={toggleOpen}>
|
||||
<NavMagnifyingGlassIcon />
|
||||
</NavIcon>
|
||||
</Trace>
|
||||
</Box>
|
||||
)}
|
||||
</Trace>
|
||||
)
|
||||
}
|
||||
|
@ -87,16 +87,16 @@ const Navbar = () => {
|
||||
<ChainSelector leftAlign={true} />
|
||||
</Box>
|
||||
)}
|
||||
<Row gap="8" display={{ sm: 'none', lg: 'flex' }}>
|
||||
<Row gap={{ xl: '0', xxl: '8' }} display={{ sm: 'none', lg: 'flex' }}>
|
||||
<PageTabs />
|
||||
</Row>
|
||||
</Box>
|
||||
<Box className={styles.middleContainer}>
|
||||
<Box className={styles.middleContainer} alignItems="flex-start">
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<Box className={styles.rightSideContainer}>
|
||||
<Row gap="12">
|
||||
<Box display={{ sm: 'flex', xl: 'none' }}>
|
||||
<Box position="relative" display={{ sm: 'flex', xl: 'none' }}>
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<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([
|
||||
baseContainer,
|
||||
sprinkles({
|
||||
display: 'flex',
|
||||
width: 'full',
|
||||
@ -53,12 +46,12 @@ export const leftSideContainer = style([
|
||||
])
|
||||
|
||||
export const middleContainer = style([
|
||||
baseContainer,
|
||||
sprinkles({
|
||||
flex: '1',
|
||||
flexShrink: '1',
|
||||
justifyContent: 'center',
|
||||
justifyContent: { lg: 'flex-end', xl: 'center' },
|
||||
display: { sm: 'none', xl: 'flex' },
|
||||
alignItems: 'flex-start',
|
||||
}),
|
||||
])
|
||||
|
||||
|
@ -23,6 +23,9 @@ const themeContractValues = {
|
||||
|
||||
modalBackdrop: '',
|
||||
|
||||
searchBackground: '',
|
||||
searchOutline: '',
|
||||
|
||||
stateOverlayHover: '',
|
||||
|
||||
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))',
|
||||
|
||||
searchBackground: `rgba(255,255,255,0.07)`,
|
||||
searchOutline: `rgba(255,255,255,0.07)`,
|
||||
stateOverlayHover: `rgba(153,161,189,0.08)`,
|
||||
|
||||
textPrimary: '#FFFFFF',
|
||||
|
@ -19,6 +19,8 @@ export const lightTheme: Theme = {
|
||||
|
||||
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)`,
|
||||
green: vars.color.green400,
|
||||
gold: vars.color.gold400,
|
||||
|
@ -167,6 +167,9 @@ export const darkTheme = {
|
||||
|
||||
stateOverlayHover: opacify(8, colors.gray300),
|
||||
stateOverlayPressed: opacify(24, colors.gray200),
|
||||
|
||||
searchBackground: `rgba(255,255,255,0.07)`,
|
||||
searchOutline: `rgba(255,255,255,0.07)`,
|
||||
}
|
||||
|
||||
export const lightTheme: Theme = {
|
||||
@ -218,4 +221,7 @@ export const lightTheme: Theme = {
|
||||
|
||||
stateOverlayHover: opacify(8, colors.gray300),
|
||||
stateOverlayPressed: opacify(24, colors.gray200),
|
||||
|
||||
searchBackground: opacify(4, colors.white),
|
||||
searchOutline: opacify(1, colors.black),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user