Skip to content

Commit

Permalink
feat(community-tags): add Tags
Browse files Browse the repository at this point in the history
  • Loading branch information
jraff authored and theetrain committed Mar 19, 2020
1 parent 6545596 commit 62d279b
Show file tree
Hide file tree
Showing 14 changed files with 3,680 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/Tags/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# TDS Community: Tags
132 changes: 132 additions & 0 deletions packages/Tags/TagItem/TagItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React, { forwardRef } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'

import Box from '@tds/core-box'

import { safeRest } from '@tds/util-helpers'
import { colorWhite, colorTelusPurple } from '@tds/core-colours'
import { Print } from '@tds/core-interactive-icon'

const tagColors = {
selected: {
text: colorWhite,
default: colorTelusPurple,
hover: '#33204C',
active: '#201430',
focus: '#33204C',
outline: '#7557A0',
border: '#33204C',
},
unselected: {
text: colorTelusPurple,
default: colorWhite,
hover: colorWhite,
active: '#F1EFF4',
focus: colorWhite,
outline: '#7557A0',
border: '#33204C',
},
}

const StyledTagButton = styled(Box)(
{
marginTop: '1rem', // add vertical spacing when TagItems wrap
},
({ isSelected, isLoading }) => {
const colors = tagColors[isSelected ? 'selected' : 'unselected']

return {
overflow: 'visible',
color: colors.text,
background: isLoading ? colors.active : colors.default,
display: 'inline-flex',
alignItems: 'center',
position: 'relative',
border: `1px solid ${colorTelusPurple}`,
borderRadius: '20px',
height: '2.5rem',
'&:hover': {
background: colors.hover,
border: isSelected && `1px solid ${tagColors.selected.hover}`,
},
'&:hover:after': {
content: "''",
position: 'absolute',
top: '-2px',
left: '-2px',
bottom: '-2px',
right: '-2px',
border: `1px solid ${colors.border}`,
borderRadius: '22px',
},
'&:focus': {
outline: 'none',
backgroundColor: isLoading ? colors.active : colors.focus,
':after': {
content: "''",
position: 'absolute',
top: isSelected ? '-10px' : '-11px',
left: isSelected ? '-10px' : '-11px',
bottom: isSelected ? '-10px' : '-11px',
right: isSelected ? '-10px' : '-11px',
border: `${isSelected ? '2px' : '3px'} solid ${colors.outline}`,
margin: '5px',
borderRadius: '25px',
},
},
'&:active': {
backgroundColor: colors.active,
border: isSelected && `1px solid ${colors.active}`,
},
':after': {
content: "''",
},
}
}
)

const StyledText = styled.span({
marginLeft: '0.5rem',
})

const TagItem = forwardRef(({ children, isSelected, isLoading, onClick, ...rest }, ref) => {
const handleClick = () => {
onClick(children)
}

return (
<StyledTagButton
{...safeRest(rest)}
ref={ref}
between={2}
inline
isSelected={isSelected}
isLoading={isLoading}
tag="button"
role="switch"
aria-checked={isSelected}
onClick={handleClick}
>
<StyledText>{children}</StyledText>
<Print invert={isSelected} />
</StyledTagButton>
)
})

TagItem.propTypes = {
children: PropTypes.node.isRequired,
isSelected: PropTypes.bool,
isLoading: PropTypes.bool,
onClick: PropTypes.func,
}

TagItem.defaultProps = {
isSelected: false,
isLoading: false,
onClick: undefined,
}

TagItem.displayName = 'TagItem'

export default TagItem
3 changes: 3 additions & 0 deletions packages/Tags/TagItem/TagItem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### TagItem

Refer to the [Tags](#tags) component for usage examples
46 changes: 46 additions & 0 deletions packages/Tags/TagItem/__tests__/TagItem.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react'
import { shallow, mount } from 'enzyme'

import TagItem from '../TagItem'

describe('TagItem', () => {
const defaultProps = {
children: 'Android',
onClick: () => {},
}
const doShallow = (props = {}) => shallow(<TagItem {...defaultProps} {...props} />)
const doMount = (props = {}) => mount(<TagItem {...defaultProps} {...props} />)

it('renders', () => {
const tagItem = doMount()

expect(tagItem).toMatchSnapshot()
})

it('renders with a button with role="switch"', () => {
const tagItem = doShallow()
expect(tagItem).toHaveProp('role', 'switch')
})

it('renders with a pressed state when isLoading is true', () => {
const tagItem = doMount({ isLoading: true })
expect(tagItem).toMatchSnapshot()
})

it('passes additional attributes to the element', () => {
const tagItem = doShallow({ id: 'the-id', 'data-some-attr': 'some value' })

expect(tagItem).toHaveProp('id', 'the-id')
expect(tagItem).toHaveProp('data-some-attr', 'some value')
})

it('does not allow custom CSS', () => {
const tagItem = doShallow({
className: 'my-custom-class',
style: { color: 'hotpink' },
})

expect(tagItem).not.toHaveProp('className', 'my-custom-class')
expect(tagItem).not.toHaveProp('style')
})
})
Loading

0 comments on commit 62d279b

Please sign in to comment.