Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update ui of map badges on list view #4042

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"oa-themes": "workspace:^",
"photoswipe": "^5.4.1",
"react-country-flag": "^3.1.0",
"react-horizontal-scrolling-menu": "^8.2.0",
"react-icons": "^5.3.0",
"react-image-crop": "^11.0.5",
"react-player": "^2.16.0",
Expand Down
12 changes: 8 additions & 4 deletions packages/components/src/CardButton/CardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,31 @@ export const CardButton = (props: IProps) => {
sx={{
alignItems: 'center',
alignContent: 'center',
marginTop: '2px',
marginTop: '4px',
borderRadius: 2,
padding: 0,
transition: 'borderBottom 0.2s, transform 0.2s',
'&:hover': !isSelected && {
animationSpeed: '0.3s',
cursor: 'pointer',
marginTop: '0',
borderBottom: '4px solid',
marginTop: '2px',
marginBottom: '2px',
borderBottom: '2px solid',
transform: 'translateY(-2px)',
borderColor: 'black',
},
'&:active': {
transform: 'translateY(1px)',
marginTop: '2px',
marginBottom: '2px',
borderBottom: '3px solid',
borderColor: 'grey',
transition: 'borderBottom 0.2s, transform 0.2s, borderColor 0.2s',
},
...(isSelected
? {
marginTop: '0',
marginTop: '1px',
marginBottom: '2px',
borderBottom: '4px solid',
borderColor: 'grey',
transform: 'translateY(-2px)',
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ interface IGlyphProps {
glyph: keyof IGlyphs
}

export interface IProps {
export interface IProps extends React.ButtonHTMLAttributes<HTMLElement> {
glyph: keyof IGlyphs
color?: string
size?: number | string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ const availableFilters = [
{
label: 'Workspace',
_id: 'workspace' as ProfileTypeName,
filterType: 'ProfileType',
filterType: 'profileType',
},
{
label: 'Machine Builder',
_id: 'machine-builder' as ProfileTypeName,
filterType: 'ProfileType',
filterType: 'profileType',
},
{
label: 'Collection Point',
_id: 'collection-point' as ProfileTypeName,
filterType: 'ProfileType',
filterType: 'profileType',
},
{
label: 'Want to get started',
_id: 'member' as ProfileTypeName,
filterType: 'ProfileType',
filterType: 'profileType',
},
]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,161 +1,72 @@
import { useEffect, useRef, useState } from 'react'
import { Flex, Text } from 'theme-ui'

import { ButtonIcon } from '../ButtonIcon/ButtonIcon'
import { CardButton } from '../CardButton/CardButton'
import { MemberBadge } from '../MemberBadge/MemberBadge'
import { Text } from 'theme-ui'

import type {
MapFilterOption,
MapFilterOptionsList,
ProfileTypeName,
} from 'oa-shared'
import type { KeyboardEvent } from 'react'

export interface IProps {
activeFilters: MapFilterOptionsList
availableFilters: MapFilterOptionsList
onFilterChange: (filter: MapFilterOption) => void
}

import { CardButton } from '../CardButton/CardButton'
import { MemberBadge } from '../MemberBadge/MemberBadge'
import { VerticalList } from '../VerticalList/VerticalList'

import 'react-horizontal-scrolling-menu/dist/styles.css'

export const MapFilterProfileTypeCardList = (props: IProps) => {
const elementRef = useRef<HTMLDivElement>(null)
const [disableLeftArrow, setDisableLeftArrow] = useState<boolean>(true)
const [disableRightArrow, setDisableRightArrow] = useState<boolean>(false)
const { activeFilters, availableFilters, onFilterChange } = props

const typeFilters = availableFilters.filter(
const items = availableFilters.filter(
({ filterType }) => filterType === 'profileType',
)

const handleHorizantalScroll = (step: number) => {
const distance = 121
const element = elementRef.current
const speed = 10
let scrollAmount = 0

const slideTimer = setInterval(() => {
if (element) {
element.scrollLeft += step
scrollAmount += Math.abs(step)
if (scrollAmount >= distance) {
clearInterval(slideTimer)
}
const { scrollLeft, scrollWidth, clientWidth } = element
switch (scrollLeft + clientWidth) {
case clientWidth:
setDisableLeftArrow(true)
// scrollWidth && setDisableRightArrow(true)
break
case scrollWidth:
setDisableRightArrow(true)
break
default:
setDisableLeftArrow(false)
setDisableRightArrow(false)
break
}
}
}, speed)
}

useEffect(() => {
handleHorizantalScroll(0)
}, [])

if (!availableFilters || availableFilters.length < 2) {
return null
}

return (
<Flex
sx={{
flexDirection: 'column',
position: 'relative',
}}
>
<Flex
as="ul"
data-cy="MapFilterProfileTypeCardList"
ref={elementRef}
sx={{
listStyle: 'none',
flexWrap: 'nowrap',
overflow: 'hidden',
paddingY: 2,
paddingX: 4,
gap: 2,
zIndex: 1,
top: '-80px',
height: 'auto',
}}
>
{typeFilters.map((typeFilter, index) => {
const active = activeFilters.find(
(filter) => filter.label === typeFilter.label,
)
return (
<CardButton
as="li"
data-cy={`MapListFilter${active ? '-active' : ''}`}
key={index}
onClick={() => onFilterChange(typeFilter)}
extrastyles={{
backgroundColor: 'offWhite',
padding: 1,
textAlign: 'center',
width: '130px',
minWidth: '130px',
height: '75px',
flexDirection: 'column',
...(active
? {
borderColor: 'green',
':hover': { borderColor: 'green' },
}
: {
borderColor: 'offWhite',
':hover': { borderColor: 'offWhite' },
}),
}}
>
<MemberBadge
size={30}
profileType={typeFilter._id as ProfileTypeName}
/>
<br />
<Text variant="quiet" sx={{ fontSize: 1 }}>
{typeFilter.label}
</Text>
</CardButton>
)
})}
</Flex>
{typeFilters.length > 3 && (
<Flex
sx={{
justifyContent: 'space-between',
zIndex: 2,
paddingX: 2,
position: 'relative',
top: '-62px',
height: 0,
}}
>
<ButtonIcon
onClick={() => handleHorizantalScroll(-10)}
icon="chevron-left"
disabled={disableLeftArrow}
sx={{ height: '28px', borderColor: 'grey' }}
/>
<ButtonIcon
data-cy="MapFilterProfileTypeCardList-ButtonRight"
onClick={() => handleHorizantalScroll(10)}
icon="chevron-right"
disabled={disableRightArrow}
sx={{ height: '28px', borderColor: 'grey' }}
/>
</Flex>
)}
</Flex>
<VerticalList>
{items.map((item, index) => {
const active = activeFilters.find(
(filter) => item.label === filter.label,
)
return (
<CardButton
onKeyDown={(ev: KeyboardEvent) => {
ev.code === 'Enter'
}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is some logic missing here?

title={item._id}
key={index}
onClick={() => onFilterChange(item)}
extrastyles={{
background: 'none',
textAlign: 'center',
width: '130px',
minWidth: '130px',
marginX: 1,
height: '75px',
flexDirection: 'column',
...(active
? {
borderColor: 'green',
':hover': { borderColor: 'green' },
}
: {
borderColor: 'background',
':hover': { borderColor: 'background' },
}),
}}
>
<MemberBadge size={40} profileType={item._id as ProfileTypeName} />
<br />
<Text variant="quiet" sx={{ fontSize: 1 }}>
{item.label}
</Text>
</CardButton>
)
})}
</VerticalList>
)
}
52 changes: 52 additions & 0 deletions packages/components/src/VerticalList/Arrows.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useContext } from 'react'
import { VisibilityContext } from 'react-horizontal-scrolling-menu'
import { Flex } from 'theme-ui'

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

import type { publicApiType } from 'react-horizontal-scrolling-menu'
import type { availableGlyphs } from '../Icon/types'

interface IProps {
disabled: boolean
glyph: availableGlyphs
onClick: () => void
}

const Arrow = ({ disabled, glyph, onClick }: IProps) => {
return (
<Flex
sx={{
width: '35px',
overflow: 'hidden',
alignItems: 'center',
position: 'relative',
borderRadius: 2,
':hover': !disabled ? { backgroundColor: 'lightGrey' } : {},
':active': !disabled ? { backgroundColor: 'softgrey' } : {},
}}
>
{disabled ? null : (
<Icon glyph={glyph} size={40} onClick={onClick} className="arrow-" />
)}
</Flex>
)
}

export const LeftArrow = () => {
const visibility = useContext<publicApiType>(VisibilityContext)
const disabled = visibility.useLeftArrowVisible()
const onClick = () =>
visibility.scrollToItem(visibility.getPrevElement(), 'smooth', 'start')

return <Arrow disabled={disabled} glyph="chevron-left" onClick={onClick} />
}

export const RightArrow = () => {
const visibility = useContext<publicApiType>(VisibilityContext)
const disabled = visibility.useRightArrowVisible()
const onClick = () =>
visibility.scrollToItem(visibility.getNextElement(), 'smooth', 'end')

return <Arrow disabled={disabled} glyph="chevron-right" onClick={onClick} />
}
32 changes: 32 additions & 0 deletions packages/components/src/VerticalList/VerticalList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Box } from 'theme-ui'

import { VerticalList } from './VerticalList'

import type { Meta, StoryFn } from '@storybook/react'

export default {
title: 'Components/VerticalList',
component: VerticalList,
} as Meta<typeof VerticalList>

export const Default: StoryFn<typeof VerticalList> = () => {
const items = ['hello', 'world!', '...', 'Yeah,', 'you!']
return (
<div style={{ width: '500px' }}>
<VerticalList>
{items.map((item, index) => (
<Box
key={index}
sx={{
width: '200px',
height: '200px',
border: '2px solid #000',
}}
>
{item}
</Box>
))}
</VerticalList>
</div>
)
}
Loading
Loading