Skip to content
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
83 changes: 79 additions & 4 deletions src/components/common/tag.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import styled, { withTheme } from 'styled-components'
import { Media } from '../../utils/css-utils'
import { DownArrowIcon } from '../icons'

export const Tag = styled.li`
font-size: 1.6rem;
Expand All @@ -25,6 +27,7 @@ const TagListLabel = styled.span`
`

const tagColors = ['lipstick', 'vividPurple', 'rouge', 'warmPurple']
const morePlaqueColor = '#545454'
Copy link
Member

Choose a reason for hiding this comment

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

move it to src/utils/css-utils.js please, there is speations colors objects there


const Tags = styled.ul`
list-style: none;
Expand All @@ -33,11 +36,71 @@ const Tags = styled.ul`
padding: 0;
`

export class TagListCutter extends Component {
constructor(props) {
super(props)
this.state = { allOpen: false }
}
handleChange() {
this.setState({ allOpen: !this.state.allOpen })
}
render() {
const { tagNumberDesktop, tagNumberMobile, tags } = this.props

return (
<Media.MobileOnly>
{isMobile => {
let currentNumber = isMobile ? tagNumberMobile : tagNumberDesktop
return currentNumber && currentNumber < tags.length
? this.props.children(
this.state.allOpen ? tags : tags.slice(0, currentNumber),
ToogleLabel(() => this.handleChange(), this.state.allOpen),
MoreTag(() => this.handleChange(), this.state.allOpen),
)
: this.props.children(tags)
}}
</Media.MobileOnly>
)
}
}

const ToogleLabel = (onLableClick, allOpen) => (label, theme) => (
<div style={{ display: 'flex' }}>
<TagListLabel>{label}</TagListLabel>
<ToogleButton onClick={onLableClick} down={!allOpen}>
<DownArrowIcon fill={theme.greyishBrown} />
</ToogleButton>
</div>
)

const ToogleButton = styled.div`
display: flex;
transform: ${props => (props.down ? 'rotate(0deg)' : 'rotate(180deg)')};
cursor: pointer;
`

const MoreTag = (onLableClick, allOpen) => () =>
allOpen ? null : (
<Tag
key="moreTagsHere"
color={morePlaqueColor}
onClick={() => onLableClick()}>
more tags...
</Tag>
)

export const TagList = withTheme(
({ tags, selectedTags, label, theme, onTagClick }) => (
({
tags,
selectedTags,
label,
theme,
onTagClick,
LabelComponent = label => <TagListLabel>{label}</TagListLabel>,
Copy link
Member

Choose a reason for hiding this comment

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

if you are using render props, it is better to name them renderLabel, renderMoreTags to make it clearer for the user of the component what should he pass in.

MoreTag = () => null,
}) => (
<div>
{label && <TagListLabel>{label}</TagListLabel>}

{label && LabelComponent(label, theme)}
{tags &&
tags.length > 0 && (
<Tags>
Expand All @@ -50,6 +113,7 @@ export const TagList = withTheme(
#{tag}
</Tag>
))}
{MoreTag()}
</Tags>
)}
</div>
Expand All @@ -67,3 +131,14 @@ TagList.defaultProps = {
selectedTags: [],
onTagClick: () => null,
}

TagListCutter.propTypes = {
Copy link
Member

Choose a reason for hiding this comment

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

it is prefered to use Flow instead of propTypes

tags: PropTypes.arrayOf(String).isRequired,
tagNumberDesktop: PropTypes.number,
tagNumberMobile: PropTypes.number,
}

TagListCutter.defaultProps = {
tagNumberDesktop: 0,
tagNumberMobile: 0,
}
25 changes: 18 additions & 7 deletions src/components/events-page/events-feed.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { chain, difference, either, isEmpty, pipe, uniq } from 'ramda'

import BlockHeader from '../common/block-header'
import MainContainer from '../common/main-container'
import { TagList } from '../common/tag'
import { TagList, TagListCutter } from '../common/tag'
import EventList from './event-list'
import { eventTags } from '../../utils/selectors'

Expand All @@ -20,12 +20,23 @@ let EventsFeed = ({
<BlockHeader size="h1">Events</BlockHeader>

{(filteredEventsTags.length > 0 || !selectedTags.length) && (
<TagList
label="Events tags"
tags={filteredEventsTags.length > 0 ? filteredEventsTags : selectedTags}
selectedTags={selectedTags}
onTagClick={toggleTag}
/>
<TagListCutter
Copy link
Member

Choose a reason for hiding this comment

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

To tell the truth this composition looks pretty complex.
It would be much simpler if the logic related to expanding/collapsing tags just live in Tags component.

tagNumberDesktop={20}
tagNumberMobile={10}
tags={
filteredEventsTags.length > 0 ? filteredEventsTags : selectedTags
}>
{(visibleTags, ToogleLable, MoreTag) => (
<TagList
label="Events tags"
tags={visibleTags}
selectedTags={selectedTags}
onTagClick={toggleTag}
LabelComponent={ToogleLable}
MoreTag={MoreTag}
/>
)}
</TagListCutter>
)}

{filteredEvents && (
Expand Down
17 changes: 17 additions & 0 deletions src/components/icons/down-arrow-icon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react'

const DownArrowIcon = props => {
return (
Copy link
Member

Choose a reason for hiding this comment

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

no need in function body and return statement here

<svg
fill={props.fill}
viewBox="0 0 24 24"
focusable="false"
width="26"
height="26"
xmlns="http://www.w3.org/2000/svg">
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
</svg>
)
}

export default DownArrowIcon
1 change: 1 addition & 0 deletions src/components/icons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { default as PadlockIcon } from './padlock-icon'
export { default as WebpurpleLogoIcon } from './webpurple-logo-icon'
export { default as WatchIcon } from './watch'
export { default as DownloadIcon } from './download'
export { default as DownArrowIcon } from './down-arrow-icon'