Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

Commit

Permalink
feat: add new component for filter icons, add new badge in curved ico…
Browse files Browse the repository at this point in the history
…ns tab
  • Loading branch information
jrgarciadev committed Mar 27, 2021
1 parent 6b00da5 commit 74a86f8
Show file tree
Hide file tree
Showing 16 changed files with 354 additions and 29 deletions.
1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"react-tippy": "^1.4.0",
"react-virtualized": "^9.22.2",
"styled-components": "^5.2.0",
"styled-tools": "^1.7.2",
"svgo": "^1.3.2"
},
"devDependencies": {
Expand Down
17 changes: 17 additions & 0 deletions website/src/components/Badge/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import PropTypes from 'prop-types'
import { isFunction } from 'lodash'
import { StyledBadge } from './styles'

const Badge = ({ label, onClick, ...props }) => {
return (
<StyledBadge onClick={isFunction(onClick) && onClick} {...props}>
{label || 'Badge'}
</StyledBadge>
)
}

Badge.propTypes = {
label: PropTypes.string,
onClick: PropTypes.func
}
export default Badge
26 changes: 26 additions & 0 deletions website/src/components/Badge/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import styled from 'styled-components'
import { hexa } from '@utils'
import { prop } from 'styled-tools'

export const Span = styled.span`
display: inline-block;
align-items: center;
color: ${(props) => props.theme.colors.accent2};
background-color: ${(props) => props.theme.colors.white};
text-transform: uppercase;
padding: 3px 4px;
margin: 0 2px;
font-size: ${(props) => props.theme.fontSize.xxs};
font-weight: 800;
border-radius: ${(props) => props.theme.radius.sm};
letter-spacing: 0.6px;
line-height: 1;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.16);
align-items: center;
align-self: center;
`

export const StyledBadge = styled(Span)`
color: ${prop('theme.colors.primary')};
background-color: ${(props) => hexa(props.theme.colors.primary, 0.1)};
`
24 changes: 0 additions & 24 deletions website/src/components/CheckboxList/index.js

This file was deleted.

26 changes: 26 additions & 0 deletions website/src/components/IconSets/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { memo } from 'react'
import { connectRefinementList } from 'react-instantsearch-dom'
import { Tabs } from '@components'
import { startCase } from 'lodash'
import { StyledContainer } from './styles'

const IconSets = ({ items, refine }) => {
return (
<StyledContainer>
<Tabs hideDivider initialValue='bold' onChange={(value) => refine(value)}>
{items.map((item, i) => (
<Tabs.Item
key={i}
badgeText={item.label === 'curved' && 'New'}
label={startCase(item.label)}
value={item.label}
/>
))}
</Tabs>
</StyledContainer>
)
}

const CustomRefinementList = connectRefinementList(memo(IconSets))

export default CustomRefinementList
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import styled from 'styled-components'

export const StyledContainer = styled.div`
${({ theme }) => theme.mixins.flexBetween};
${({ theme }) => theme.mixins.flexCenter};
width: 100%;
padding: 0 20%;
padding: 0 2rem;
margin-top: 4rem;
input {
margin-right: 1rem;
Expand Down
7 changes: 7 additions & 0 deletions website/src/components/Tabs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Tabs from './tabs'
import TabsItem from './tabs-item'

Tabs.Item = TabsItem
Tabs.Tab = TabsItem

export default Tabs
96 changes: 96 additions & 0 deletions website/src/components/Tabs/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import styled, { css } from 'styled-components'
import { ifProp } from 'styled-tools'

export const TabsContainer = styled.div`
width: initial;
`

export const Tab = styled.div`
padding: ${({ theme }) =>
`${theme.layout.gapHalf} calc(0.65 * ${theme.layout.gapHalf})`};
cursor: pointer;
outline: 0;
transition: all 200ms ease;
text-transform: capitalize;
margin: 0 calc(0.8 * ${(props) => props.theme.layout.gapQuarter});
font-size: ${({ theme }) => theme.fontSize.md};
color: ${({ theme }) => theme.colors.accent4};
user-select: none;
display: flex;
align-items: center;
line-height: 1.25rem;
position: relative;
&:after {
position: absolute;
content: '';
bottom: -1px;
left: 0;
right: 0;
width: 100%;
height: 2px;
transform: scaleX(0.75);
background-color: transparent;
transition: all 200ms ease;
}
${({ active, theme }) =>
active &&
css`
color: ${theme.colors.primary};
&:after {
background-color: ${theme.colors.primary};
transform: scaleX(1);
}
`}
${ifProp(
{ hasBadge: true },
css`
span {
margin-left: 1rem;
}
`
)}
&:disabled,
&:disabled:hover,
&:disabled:focus {
color: ${({ theme }) => theme.colors.accent4};
cursor: not-allowed;
}
svg {
max-height: 1em;
margin-right: 5px;
}
&:first-of-type {
margin-left: 0;
}
`

export const TabsHeader = styled.div`
display: flex;
flex-wrap: wrap;
align-items: center;
border-bottom: 1px solid ${({ theme }) => theme.colors.accent4};
${({ hideDivider }) =>
hideDivider &&
css`
border-bottom: none;
`}
${({ fullWidth }) =>
fullWidth &&
css`
width: 100%;
flex-wrap: nowrap;
justify-content: space-between;
${Tab} {
justify-content: center;
text-align: center;
width: 100%;
}
`}
`

export const TabContent = styled.div`
padding-top: 0.625rem;
`
9 changes: 9 additions & 0 deletions website/src/components/Tabs/tabs-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'

const defaultContext = {
inGroup: false
}

export const TabsContext = React.createContext(defaultContext)

export const useTabsContext = () => React.useContext(TabsContext)
36 changes: 36 additions & 0 deletions website/src/components/Tabs/tabs-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useEffect, useMemo } from 'react'
import PropTypes from 'prop-types'
import { useTabsContext } from './tabs-context'

const TabsItem = ({
children,
value,
label,
badgeText = '',
disabled = false
}) => {
const { register, currentValue } = useTabsContext()
const isActive = useMemo(() => currentValue === value, [currentValue, value])

useEffect(() => {
// eslint-disable-next-line no-unused-expressions
register && register({ value, label, disabled, badgeText })
}, [value, label, disabled])

/* eslint-disable react/jsx-no-useless-fragment */
return isActive ? <>{children}</> : null
}

TabsItem.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
badgeText: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
value: PropTypes.string,
disabled: PropTypes.bool
}

export default TabsItem
/* eslint-enable */
96 changes: 96 additions & 0 deletions website/src/components/Tabs/tabs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useEffect, useMemo, useState } from 'react'
import PropTypes from 'prop-types'
import { Badge } from '@components'
import { TabsContext } from './tabs-context'
import { isEmpty } from 'lodash'
import { TabsContainer, TabsHeader, Tab, TabContent } from './styles'

const Tabs = ({
initialValue: userCustomInitialValue,
value,
hideDivider = false,
fullWidth = false,
children,
onChange,
className = '',
...props
}) => {
const [selfValue, setSelfValue] = useState(userCustomInitialValue)
const [tabs, setTabs] = useState([])

const register = (next) => {
setTabs((last) => {
const hasItem = last.find((item) => item.value === next.value)
if (!hasItem) return [...last, next]
return last.map((item) => {
if (item.value !== next.value) return item
return {
...item,
badgeText: next.badgeText,
label: next.label,
disabled: next.disabled
}
})
})
}

const initialValue = useMemo(
() => ({
register,
currentValue: selfValue,
inGroup: true
}),
[selfValue]
)

useEffect(() => {
if (value === undefined) return
setSelfValue(value)
}, [value])

const clickHandler = (item) => {
if (item.disabled) return
setSelfValue(item.value)
// eslint-disable-next-line no-unused-expressions
onChange && onChange(item.value)
}

return (
<TabsContext.Provider value={initialValue}>
<TabsContainer className={className} {...props}>
<TabsHeader hideDivider={hideDivider} fullWidth={fullWidth}>
{tabs.map((item, index) => (
<Tab
active={selfValue === item.value}
hasBadge={!isEmpty(item.badgeText)}
disabled={item.disabled}
tabIndex={index}
role='button'
key={item.value}
onClick={() => clickHandler(item)}
>
{item.label}
{item.badgeText && <Badge label={item.badgeText} />}
</Tab>
))}
</TabsHeader>
<TabContent>{children}</TabContent>
</TabsContainer>
</TabsContext.Provider>
)
}

Tabs.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
fullWidth: PropTypes.bool,
initialValue: PropTypes.string,
value: PropTypes.string,
hideDivider: PropTypes.bool,
onChange: PropTypes.func,
className: PropTypes.string
}

export default Tabs
18 changes: 18 additions & 0 deletions website/src/components/Tabs/use-tabs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useCurrentState } from '@hooks'

const useTabs = ({ initialValue }) => {
const [state, setState, currentRef] = useCurrentState(initialValue)
return {
state,
setState,
currentRef,
bindings: {
value: state,
onChange: (val) => {
setState(val)
}
}
}
}

export default useTabs
4 changes: 3 additions & 1 deletion website/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export { default as IconDetail } from './IconDetail'
export { default as IconCode } from './IconCode'
export { default as Tooltip } from './Tooltip'
export { default as Checkbox } from './Checkbox'
export { default as CheckboxList } from './CheckboxList'
export { default as IconSets } from './IconSets'
export { default as Loader } from './Loader'
export { default as Badge } from './Badge'
export { default as NoResults } from './NoResults'
export { default as Tabs } from './Tabs'
Loading

1 comment on commit 74a86f8

@vercel
Copy link

@vercel vercel bot commented on 74a86f8 Mar 27, 2021

Choose a reason for hiding this comment

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

Please sign in to comment.