Skip to content

Commit

Permalink
feat(component): searchfield component with icons and center eye icon…
Browse files Browse the repository at this point in the history
… in passwordfield
  • Loading branch information
Lahuen Garcia committed Sep 24, 2024
1 parent 055430a commit ab5f426
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 96 deletions.
2 changes: 1 addition & 1 deletion packages/components/assets/icons/cross-close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 1 addition & 14 deletions packages/components/assets/icons/eye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/components/src/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export const glyphs: IGlyphs = {
view: iconMap.view,
volunteer: iconMap.volunteer,
website: iconMap.website,
search: iconMap.search,
}

export type Props = IProps & VerticalAlignProps & SpaceProps
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/Icon/svgs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import bazarSVG from '../../assets/icons/icon-bazar.svg'
import commentSVG from '../../assets/icons/icon-comment.svg'
import discordSVG from '../../assets/icons/icon-discord.svg'
import emailOutlineSVG from '../../assets/icons/icon-email.svg'
import searchSVG from '../../assets/icons/icon-search.svg'
import socialMediaSVG from '../../assets/icons/icon-social-media.svg'
import starActiveSVG from '../../assets/icons/icon-star-active.svg'
import starSVG from '../../assets/icons/icon-star-default.svg'
Expand Down Expand Up @@ -89,4 +90,5 @@ export const iconMap = {
view: <ImageIcon src={viewSVG} />,
volunteer: <ImageIcon src={volunteerSVG} />,
website: <ImageIcon src={websiteSVG} />,
search: <ImageIcon src={searchSVG} />,
}
1 change: 1 addition & 0 deletions packages/components/src/Icon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@ export type availableGlyphs =
| 'view'
| 'volunteer'
| 'website'
| 'search'

export type IGlyphs = { [k in availableGlyphs]: JSX.Element }
29 changes: 17 additions & 12 deletions packages/components/src/OsmGeocoding/OsmGeocoding.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from 'react'
import { Input } from 'theme-ui'
import { useDebouncedCallback } from 'use-debounce'

import { SearchField } from '../SearchField/SearchField'
import { OsmGeocodingLoader } from './OsmGeocodingLoader'
import { OsmGeocodingResultsList } from './OsmGeocodingResultsList'

Expand Down Expand Up @@ -94,16 +94,26 @@ export const OsmGeocoding = ({
ref={mainContainerRef}
style={{ width: '100%' }}
>
<Input
<SearchField
autoComplete="off"
type="search"
name="geocoding"
id="geocoding"
data-cy="osm-geocoding-input"
placeholder={placeholder}
dataCy="howtos-search-box"
placeHolder={placeholder}
value={searchValue}
style={{
width: '100%',
onChange={(value: string) => {
setQueryLocationService(true)
setSearchValue(value)
}}
onClickDelete={() => {
setSearchValue('')
setQueryLocationService(false)
}}
onClickSearch={() => {
setQueryLocationService(true)
setSearchValue(searchValue)
}}
additionalStyle={{
background: 'white',
fontFamily: 'Varela Round',
fontSize: '14px',
Expand All @@ -114,11 +124,6 @@ export const OsmGeocoding = ({
showResultsListing || showLoader ? '5px 5px 0 0' : '5px',
marginBottom: 0,
}}
onClick={() => setShowResults(true)}
onChange={(event) => {
setQueryLocationService(true)
setSearchValue(event.target.value)
}}
/>
{showLoader && <OsmGeocodingLoader />}
{showResultsListing && (
Expand Down
94 changes: 94 additions & 0 deletions packages/components/src/SearchField/SearchField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Box, Input } from 'theme-ui'

import { Icon } from '../Icon/Icon'

import type { ThemeUIStyleObject } from 'theme-ui'

export type Props = {
autoComplete?: string
name?: string
id?: string
dataCy: string
placeHolder: string
value: string
onChange: (value: string) => void
onClickDelete: () => void
onClickSearch: () => void
additionalStyle?: ThemeUIStyleObject
}

export const SearchField = ({
autoComplete = 'on',
name = 'rand-name',
id = 'rand-id',
dataCy,
placeHolder,
value,
onChange,
onClickDelete,
onClickSearch,
additionalStyle = {},
}: Props) => {
return (
<Box
sx={{
position: 'relative',
width: '100%',
display: 'flex',
alignItems: 'center',
}}
>
<Input
autoComplete={autoComplete}
name={name}
id={id}
variant="inputOutline"
type="search"
data-cy={dataCy}
placeholder={placeHolder}
value={value}
onChange={(e) => onChange(e.target.value)}
sx={{
...additionalStyle,
paddingRight: 11,
'::-webkit-search-cancel-button': {
display: 'none',
},
'::-ms-clear': {
display: 'none',
},
}}
/>
<Box
sx={{
right: 2,
position: 'absolute',
display: 'flex',
alignItems: 'center',
}}
>
{value && (
<Icon
sx={{
display: 'flex',
alignItems: 'center',
marginRight: 1,
}}
glyph="close"
onClick={onClickDelete}
size="17"
/>
)}
<Icon
sx={{
display: 'flex',
alignItems: 'center',
}}
glyph="search"
onClick={onClickSearch}
size="19"
/>
</Box>
</Box>
)
}
3 changes: 1 addition & 2 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export { OsmGeocoding } from './OsmGeocoding/OsmGeocoding'
export { PinProfile } from './PinProfile/PinProfile'
export { ProfileLink } from './ProfileLink/ProfileLink'
export { ResearchEditorOverview } from './ResearchEditorOverview/ResearchEditorOverview'
export { SearchField } from './SearchField/SearchField'
export { Select } from './Select/Select'
export { SettingsFormWrapper } from './SettingsFormWrapper/SettingsFormWrapper'
export { SiteFooter } from './SiteFooter/SiteFooter'
Expand All @@ -69,7 +70,5 @@ export { UserEngagementWrapper } from './UserEngagementWrapper/UserEngagementWra
export { Username } from './Username/Username'
export { UserStatistics } from './UserStatistics/UserStatistics'
export { VideoPlayer } from './VideoPlayer/VideoPlayer'

// export { IImageGalleryItem } from './ImageGallery/ImageGallery'
export type { availableGlyphs } from './Icon/types'
export type { ITab } from './SettingsFormWrapper/SettingsFormTab'
15 changes: 12 additions & 3 deletions src/common/Form/PasswordField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ export const PasswordField = ({ name, component, ...rest }) => {
const [isPasswordVisible, setIsPasswordVisible] = useState(false)

return (
<Box style={{ position: 'relative' }}>
<Box
style={{
display: 'flex',
alignItems: 'center',
position: 'relative',
}}
>
<Field
{...rest}
name={name}
Expand All @@ -19,15 +25,18 @@ export const PasswordField = ({ name, component, ...rest }) => {
sx={{
position: 'absolute',
right: 2,
top: 1,
opacity: 0.7,
}}
>
<Icon
sx={{
display: 'flex',
alignItems: 'center',
}}
glyph={isPasswordVisible ? 'hide' : 'show'}
onClick={() => setIsPasswordVisible(!isPasswordVisible)}
size="25"
></Icon>
/>
</Box>
</Box>
)
Expand Down
60 changes: 39 additions & 21 deletions src/pages/Howto/Content/HowtoList/HowtoFilterHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useCallback, useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import debounce from 'debounce'
import { Select } from 'oa-components'
import { SearchField, Select } from 'oa-components'
import { FieldContainer } from 'src/common/Form/FieldContainer'
import { Flex, Input } from 'theme-ui'
import { Flex } from 'theme-ui'

import { CategoriesSelectV2 } from '../../../common/Category/CategoriesSelectV2'
import { howtoService, HowtosSearchParams } from '../../howto.service'
Expand All @@ -15,6 +15,7 @@ import type { HowtoSortOption } from './HowtoSortOptions'

export const HowtoFilterHeader = () => {
const [categories, setCategories] = useState<SelectValue[]>([])
const [searchString, setSearchString] = useState<string>('')

const [searchParams, setSearchParams] = useSearchParams()
const categoryParam = searchParams.get(HowtosSearchParams.category)
Expand All @@ -23,11 +24,17 @@ export const HowtoFilterHeader = () => {
const sort = searchParams.get(HowtosSearchParams.sort) as HowtoSortOption

const _inputStyle = {
width: ['100%', '100%', '200px'],
width: ['100%', '100%', '230px'],
mr: [0, 0, 2],
mb: [3, 3, 0],
}

useEffect(() => {
if (q && q.length > 0) {
setSearchString(q)
}
}, [q])

useEffect(() => {
const initCategories = async () => {
const categories = (await howtoService.getHowtoCategories()) || []
Expand Down Expand Up @@ -57,22 +64,26 @@ export const HowtoFilterHeader = () => {

const onSearchInputChange = useCallback(
debounce((value: string) => {
const params = new URLSearchParams(searchParams.toString())
params.set(HowtosSearchParams.q, value)

if (value.length > 0 && sort !== 'MostRelevant') {
params.set(HowtosSearchParams.sort, 'MostRelevant')
}

if (value.length === 0 || !value) {
params.set(HowtosSearchParams.sort, 'Newest')
}

setSearchParams(params)
searchValue(value)
}, 500),
[searchParams],
)

const searchValue = (value: string) => {
const params = new URLSearchParams(searchParams.toString())
params.set(HowtosSearchParams.q, value)

if (value.length > 0 && sort !== 'MostRelevant') {
params.set(HowtosSearchParams.sort, 'MostRelevant')
}

if (value.length === 0 || !value) {
params.set(HowtosSearchParams.sort, 'Newest')
}

setSearchParams(params)
}

return (
<Flex
sx={{
Expand Down Expand Up @@ -109,12 +120,19 @@ export const HowtoFilterHeader = () => {
</FieldContainer>
</Flex>
<Flex sx={_inputStyle}>
<Input
variant="inputOutline"
data-cy="howtos-search-box"
defaultValue={q || ''}
placeholder={listing.search}
onChange={(e) => onSearchInputChange(e.target.value)}
<SearchField
dataCy="howtos-search-box"
placeHolder={listing.search}
value={searchString}
onChange={(value) => {
setSearchString(value)
onSearchInputChange(value)
}}
onClickDelete={() => {
setSearchString('')
searchValue('')
}}
onClickSearch={() => searchValue(searchString + 'asd')}
/>
</Flex>
</Flex>
Expand Down
Loading

0 comments on commit ab5f426

Please sign in to comment.