Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add Icon `xSpacing` prop @Bugaa92 ([#22](https://github.com/stardust-ui/react/pull/22))
- Add Button `icon` prop and Text `truncated` prop @Bugaa92 ([#13](https://github.com/stardust-ui/react/pull/13))
- Add Button `disabled` prop @Bugaa92 ([#14](https://github.com/stardust-ui/react/pull/14))
- Add Label `icon`, `onIconClick` and `iconPosition` props @mnajdova ([#19](https://github.com/stardust-ui/react/pull/19))
- Add Menu `vertical` prop @miroslavstastny ([#21](https://github.com/stardust-ui/react/pull/21))

### Documentation
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react'
import { Label } from '@stardust-ui/react'

const LabelExampleIconShorthand = () => <Label icon="coffee" content="Label containing icon" />

export default LabelExampleIconShorthand
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'
import { Label, Icon } from '@stardust-ui/react'

const LabelExampleIcon = () => (
<Label>
<Icon name="coffee" xSpacing="after" variables={() => ({ color: 'rgba(0, 0, 0, 0.6)' })} />
Copy link
Contributor

Choose a reason for hiding this comment

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

note to myself - these keywords for xSpacing should be changed as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should introduce separate PR for the Icon's xSpacing and the Button's iconPosition to be consistent with the rest of the components.

Label containing icon
</Label>
)

export default LabelExampleIcon
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react'
import { Label } from '@stardust-ui/react'

class LabelExampleIconAsShorthand extends React.Component<{}, { display: string }> {
constructor(props) {
super(props)
this.state = {
display: 'inline-block',
}
}

public hide = () => {
this.setState({ display: 'none' })
}

public render() {
const { display } = this.state
return (
<Label
circular
style={{ display }}
icon={{
name: 'close',
onClick: this.hide,
}}
iconPosition="end"
content="Removable label"
/>
)
}
}

export default LabelExampleIconAsShorthand
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'
import { Label } from '@stardust-ui/react'

const LabelExampleIconPositionShorthand = () => (
<Label circular icon="close" iconPosition="end" content="Label with icon after the content" />
)

export default LabelExampleIconPositionShorthand
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'
import { Label, Icon } from '@stardust-ui/react'

const LabelExampleIconPosition = () => (
<Label circular>
Label with icon after the content
<Icon name="close" xSpacing="before" variables={() => ({ color: 'rgba(0, 0, 0, 0.6)' })} />
</Label>
)

export default LabelExampleIconPosition
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react'
import { Label } from '@stardust-ui/react'

class LabelExampleIconShorthand extends React.Component<{}, { display: string }> {
constructor(props) {
super(props)
this.state = {
display: 'inline-block',
}
}

public hide = () => {
this.setState({ display: 'none' })
}

public render() {
const { display } = this.state
return (
<Label
circular
style={{ display }}
icon="close"
iconPosition="end"
onIconClick={this.hide}
content="Removable label"
/>
)
}
}

export default LabelExampleIconShorthand
20 changes: 20 additions & 0 deletions docs/src/examples/components/Label/Variations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ const Variations = () => (
description="A label can be circular"
examplePath="components/Label/Variations/LabelExampleCircular"
/>
<ComponentExample
title="Icon"
description="The label can contain an icon"
examplePath="components/Label/Variations/LabelExampleIcon"
/>
<ComponentExample
title="Icon position"
description="The icon inside the label can be aligned before or after the content"
examplePath="components/Label/Variations/LabelExampleIconPosition"
/>
<ComponentExample
title="Clickable icon"
description="The icon inside the label can be clickable"
examplePath="components/Label/Variations/LabelExampleOnIconClick"
/>
<ComponentExample
title="The Icon inside Label can be customized"
description="The Icon component inside the Label can be defined with customizing it's prop"
examplePath="components/Label/Variations/LabelExampleIconAsShorthand"
/>
</ExampleSection>
)

Expand Down
6 changes: 5 additions & 1 deletion src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { CSSProperties } from 'react'
import PropTypes from 'prop-types'
import { customPropTypes, UIComponent, SUI } from '../../lib'
import { customPropTypes, UIComponent, SUI, createShorthandFactory } from '../../lib'

import iconRules from './iconRules'
import iconVariables from './iconVariables'
Expand Down Expand Up @@ -38,9 +38,11 @@ export interface IconProps {
xSpacing?: IconXSpacing
style?: CSSProperties
title?: string
variables?: (siteVariables: object) => object
}

class Icon extends UIComponent<IconProps, {}> {
static create: Function
static className = 'ui-icon'

static displayName = 'Icon'
Expand Down Expand Up @@ -119,4 +121,6 @@ class Icon extends UIComponent<IconProps, {}> {
}
}

Icon.create = createShorthandFactory(Icon, name => ({ name }))

export default Icon
82 changes: 78 additions & 4 deletions src/components/Label/Label.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import PropTypes from 'prop-types'
import React from 'react'
import React, { ReactNode } from 'react'
import _ from 'lodash'

import { childrenExist, createShorthandFactory, customPropTypes, UIComponent } from '../../lib'

import { Icon } from '../..'
import labelRules from './labelRules'
import labelVariables from './labelVariables'
import callable from '../../lib/callable'

/**
* A label displays content classification
Expand All @@ -31,9 +34,32 @@ class Label extends UIComponent<any, any> {

/** Shorthand for primary content. */
content: customPropTypes.contentShorthand,

/** Label can have an icon. */
icon: customPropTypes.some([PropTypes.string, PropTypes.object]),

/** An icon label can format an Icon to appear before or after the text in the label */
iconPosition: PropTypes.oneOf(['start', 'end']),

/**
* Function called when the icon is clicked.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onIconClick: PropTypes.func,
}

static handledProps = ['as', 'children', 'circular', 'className', 'content']
static handledProps = [
'as',
'children',
'circular',
'className',
'content',
'icon',
'iconPosition',
'onIconClick',
]

static defaultProps = {
as: 'label',
Expand All @@ -43,11 +69,59 @@ class Label extends UIComponent<any, any> {

static variables = labelVariables

handleIconOverrides = predefinedProps => {
const { onIconClick, iconPosition, content, variables: labelPropVariables } = this.props
const { onClick, variables, xSpacing } = predefinedProps

const iconVariables = callable(variables)()
const labelVariables = labelPropVariables
? callable(labelPropVariables)()
: callable(Label.variables)()

return {
onClick: e => {
_.invoke(predefinedProps, 'onClick', e)
_.invoke(this.props, 'onIconClick', e, this.props)
},
...((onClick || onIconClick) && { tabIndex: '0' }),
...((!iconVariables || !iconVariables.color) && {
variables: { color: labelVariables.color },
}),
...(!xSpacing && {
xSpacing: !content ? 'none' : iconPosition === 'end' ? 'before' : 'after',
}),
}
}

renderComponent({ ElementType, classes, rest }) {
const { children, content } = this.props
const { children, content, icon, iconPosition } = this.props
const getContent = (): ReactNode => {
const iconAtEnd = iconPosition === 'end'
const iconAtStart = !iconAtEnd

const iconElement = Icon.create(
{
className: classes.icon,
...(typeof icon === 'string' ? { name: icon } : { ...icon }),
},
{
generateKey: false,
overrideProps: this.handleIconOverrides,
},
)

return (
<React.Fragment>
{iconAtStart && icon && iconElement}
{content}
{iconAtEnd && icon && iconElement}
</React.Fragment>
)
}

return (
<ElementType {...rest} className={classes.root}>
{childrenExist(children) ? children : content}
{childrenExist(children) ? children : getContent()}
</ElementType>
)
}
Expand Down
10 changes: 9 additions & 1 deletion src/components/Label/labelRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ export default {
padding: variables.padding,
fontWeight: '500',
backgroundColor: 'rgb(232, 232, 232)',
color: 'rgba(0, 0, 0, 0.6)',
color: variables.color,
borderRadius: pxToRem(3),
...(props.circular && {
borderRadius: variables.circularRadius,
}),
}),
icon: ({ props }) => ({
position: 'relative',
top: '-0.15em',
...((props.onIconClick ||
(props.icon && typeof props.icon === 'object' && props.icon.onClick)) && {
cursor: 'pointer',
}),
}),
}
1 change: 1 addition & 0 deletions src/components/Label/labelVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export default () => {
const vars: any = {}
vars.circularRadius = pxToRem(5000)
vars.padding = `${pxToRem(6)} ${pxToRem(8)}`
vars.color = 'rgba(0, 0, 0, 0.6)'
return vars
}
7 changes: 0 additions & 7 deletions test/specs/components/Label/Label-test.ts

This file was deleted.

21 changes: 21 additions & 0 deletions test/specs/components/Label/Label-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import { isConformant } from 'test/specs/commonTests'

import Label from 'src/components/Label/Label'
import { mountWithProvider } from '../../../utils'

describe('Label', () => {
isConformant(Label)

describe('onIconClick', () => {
it('calls onIconClick when the icon is clicked', () => {
const onClick = jest.fn()
const button = mountWithProvider(
<Label icon={{ name: 'close', key: 'icon-key' }} onIconClick={onClick} />,
).find('Icon[name="close"]')
button.simulate('click')

expect(onClick).toHaveBeenCalled()
})
})
})