Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

feat(Label): added image and imagePosition props #55

Merged
merged 31 commits into from
Sep 5, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
32f1b81
-added image shorthand to the label component
Aug 7, 2018
5ab51a9
Merge branch 'master' into feat/label-image-prop
Aug 7, 2018
14799ca
Merge branch 'master' into feat/label-image-prop
mnajdova Aug 7, 2018
500810f
-update changelog
Aug 7, 2018
828a13c
Merge remote-tracking branch 'origin/feat/label-image-prop' into feat…
Aug 7, 2018
e31bdbc
-extract label height in a method
Aug 7, 2018
0aeab96
Merge branch 'master' into feat/label-image-prop
Aug 9, 2018
c1a7117
-replaced image, icon, iconPosition with start and end
Aug 9, 2018
3249b01
-updated changelog
Aug 9, 2018
d1cbd91
-updated layout styles to align the content int he start and end in m…
Aug 9, 2018
c7ed6cc
Merge branch 'master' into feat/label-image-prop
Aug 13, 2018
ba3b5be
-refactoring Label to work with icon, iconPosition, image and imagePo…
Aug 13, 2018
b3001e4
-fixes
Aug 13, 2018
12652e9
-updated CHANGELOG
Aug 13, 2018
4ca94e6
-added test for handling the tabIndex property set to the icon with o…
Aug 13, 2018
29185e8
Merge branch 'master' into feat/label-image-prop
Aug 23, 2018
74a2819
-merge conflicts
Aug 23, 2018
58c47ba
-handling cursor pointer if the icon has onClick prop
Aug 23, 2018
211f372
-remove margin from the label styles
Aug 23, 2018
b8afd16
Merge branch 'master' into feat/label-image-prop
mnajdova Aug 23, 2018
59b145a
Merge branch 'master' into feat/label-image-prop
Aug 23, 2018
0d0cfe8
Merge branch 'feat/label-image-prop' of https://github.com/stardust-u…
Aug 23, 2018
b0ea6c5
Merge branch 'master' into feat/label-image-prop
Aug 27, 2018
ad24d4f
-updated with latest master, fixed changelog, added shorthand tests
Aug 27, 2018
3b96351
Merge branch 'master' into feat/label-image-prop
Aug 30, 2018
bc1d0e6
-merge conflicts
Sep 3, 2018
0cb6d1b
Merge branch 'master' into feat/label-image-prop
Sep 3, 2018
e31fed7
-fixed changelog
Sep 3, 2018
dbafa51
Merge branch 'master' into feat/label-image-prop
Sep 3, 2018
e0a86a9
Merge branch 'master' into feat/label-image-prop
Sep 4, 2018
61aaa6d
Merge branch 'master' into feat/label-image-prop
Sep 5, 2018
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 @@ -27,6 +27,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Update styles for Menu underlined primary @miroslavstastny ([#20](https://github.com/stardust-ui/react/pull/20))
- Add Avatar `getInitials` prop and `presenceIndicatorBackground` variable @mnajdova ([#38](https://github.com/stardust-ui/react/pull/38))
- Add 'fluid' variant and size variables to Image @kuzhelov ([#54](https://github.com/stardust-ui/react/pull/54))
- Add Label `image` shorthand prop @mnajdova ([#55](https://github.com/stardust-ui/react/pull/55))

<!--------------------------------[ v0.2.5 ]------------------------------- -->
## [v0.2.5](https://github.com/stardust-ui/react/tree/v0.2.5) (2018-08-03)
Expand Down

This file was deleted.

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

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

public hide = () => {
Expand Down

This file was deleted.

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

const LabelExampleImageShorthand = () => (
<Label
circular
icon="close"
iconPosition="end"
Copy link
Member

Choose a reason for hiding this comment

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

What happens if you add an icon, but not iconPosition="end"? If both the icon and the image are added to the start position by default, which I think makes sense, then perhaps we call these media or startMedia and endMedia instead?

Trying to think about how this aligns to the similar case of the ListItem. In that case, you can add media and endMedia. The layout of both a ListItem and a Label are idential in this regard. The start and end media pieces collapse their width while the main area expands to fill the space.

The flip side of this argument is that perhaps it might be more common and more intuitive to add an image to the "start" side by default but maybe icons are most intuitive on the "end" side by default. Therefore, a position prop is introduced to allow positioning them on the less common/intuitive side when needed.

Feedback?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@levithomason I already created PR for the ItemLayout component, and yes, after working with it I tried to re-implement the Label with the startMedia and endMedia and it it much cleaner. With that we would get rid of the icon, iconPosition and image props and have more abstract way of defining the start and end media in the Label, as well as other components. My proposal is, to wait for the ItemLayout component PR to be merged and immediately after it, I will publish the PR for the Label containing the start and end media, as I already have it ready on a separate branch.

content="John Doe"
image={{ src: 'public/images/avatar/small/matt.jpg', avatar: true }}
/>
)

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

class LabelExampleIconShorthand extends React.Component<{}, { display: string }> {
class LabelExampleIconShorthand extends React.Component<any, any> {
Copy link
Member

Choose a reason for hiding this comment

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

No typings in examples, please. They should be geared for minimalism and all consumers.

constructor(props) {
super(props)
this.state = {
display: 'inline-block',
}
this.state = {}
Copy link
Member

Choose a reason for hiding this comment

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

This:

constructor(props) {
  super(props)
  this.state = {}
}

Is identical to:

state = {}

}

public hide = () => {
Expand Down
5 changes: 5 additions & 0 deletions docs/src/examples/components/Label/Variations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ const Variations = () => (
description="The Icon component inside the Label can be defined with customizing it's prop"
examplePath="components/Label/Variations/LabelExampleIconAsShorthand"
/>
<ComponentExample
title="Image"
Copy link
Member

Choose a reason for hiding this comment

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

Image is part of the Content that a Label can contain. This example should be moved from Variations to Content.

description="The Label can contain an image"
Copy link
Member

Choose a reason for hiding this comment

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

Missing period

examplePath="components/Label/Variations/LabelExampleImage"
/>
</ExampleSection>
)

Expand Down
6 changes: 5 additions & 1 deletion src/components/Image/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import * as PropTypes from 'prop-types'
import * as React from 'react'

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

/**
* An image is a graphic representation of something.
*/
class Image extends UIComponent<any, any> {
static create: Function

static className = 'ui-image'

static displayName = 'Image'
Expand Down Expand Up @@ -45,4 +47,6 @@ class Image extends UIComponent<any, any> {
}
}

Image.create = createShorthandFactory(Image, src => ({ src }))

export default Image
19 changes: 17 additions & 2 deletions src/components/Label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as _ from 'lodash'

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

import { Icon } from '../..'
import { Icon, Image } from '../..'
import labelRules from './labelRules'
import labelVariables from './labelVariables'
import callable from '../../lib/callable'
Expand Down Expand Up @@ -41,6 +41,9 @@ class Label extends UIComponent<any, any> {
/** An icon label can format an Icon to appear before or after the text in the label */
iconPosition: PropTypes.oneOf(['start', 'end']),

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

@levithomason levithomason Aug 8, 2018

Choose a reason for hiding this comment

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

customPropTypes.itemShorthand. All shorthand props that create a single item use this custom prop type. It allows string, number, object, element, and is disallowed with children.


/**
* Function called when the icon is clicked.
*
Expand All @@ -58,6 +61,7 @@ class Label extends UIComponent<any, any> {
'content',
'icon',
'iconPosition',
'image',
'onIconClick',
]

Expand Down Expand Up @@ -94,7 +98,7 @@ class Label extends UIComponent<any, any> {
}

renderComponent({ ElementType, classes, rest }) {
const { children, content, icon, iconPosition } = this.props
const { children, content, icon, iconPosition, image } = this.props
const getContent = (): React.ReactNode => {
const iconAtEnd = iconPosition === 'end'
const iconAtStart = !iconAtEnd
Expand All @@ -110,8 +114,19 @@ class Label extends UIComponent<any, any> {
},
)

const imageElement = Image.create(
{
className: classes.image,
...(typeof image === 'string' ? { src: image } : { ...image }),
},
Copy link
Member

Choose a reason for hiding this comment

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

This does not handle other cases of shorthand, such as passing elements. Instead of attempting to figure out which type of shorthand was passed, you can leave this to the factory. To pass additional defaultProps, such as the className in this case, you can use the options object:

Image.create(image, {
  generateKey: false,
  defaultProps: { className: classes.image },
})

Copy link
Member

Choose a reason for hiding this comment

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

Also, it may be required to override the user's props and merge the classes.image with their className. This way, if they pass a props.className, it doesn't override the styling classes:

handleImageOverrideProps = props => ({
  ...props,
  className: cx(classes.image, props.className),
})

Image.create(image, {
  generateKey: false,
  overrideProps: this.handleImageOverrideProps,
})

Now, the component will override any props.className provided by the user by merging the style className into them.


Bonus: What if the user doesn't want our classNames?!

Answer: They can use a function for shorthand and whatever they want:

<Label
  image={(Image, props) => <Image {...props} className='only these' />}
/>

{
generateKey: false,
},
)

return (
<React.Fragment>
{image && imageElement}
{iconAtStart && icon && iconElement}
{content}
{iconAtEnd && icon && iconElement}
Expand Down
21 changes: 19 additions & 2 deletions src/components/Label/labelRules.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
import { pxToRem } from '../../lib'

const getLabelHeight = () => {
return pxToRem(20)
}
Copy link
Member

Choose a reason for hiding this comment

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

Seems this can just be a constant value:

const labelHeight = pxToRem(20)

Perhaps it should even be a variable?

// labelVariables.ts

export default () => ({
  height: pxToRem(20)
})


export default {
root: ({ props, variables }) => ({
height: getLabelHeight(),
margin: `${pxToRem(4)} 0 0 ${pxToRem(4)}`,
padding: variables.padding,
fontWeight: '500',
display: 'inline-block',
fontSize: pxToRem(14),
lineHeight: getLabelHeight(),
verticalAlign: 'middle',
backgroundColor: 'rgb(232, 232, 232)',
color: variables.color,
borderRadius: pxToRem(3),
...(props.circular && {
borderRadius: variables.circularRadius,
}),
overflow: 'hidden',
}),
icon: ({ props }) => ({
position: 'relative',
top: '-0.15em',
top: `-${pxToRem(2)}`,
...((props.onIconClick ||
(props.icon && typeof props.icon === 'object' && props.icon.onClick)) && {
cursor: 'pointer',
}),
}),
image: () => ({
height: `${getLabelHeight()} !important`,
width: `${getLabelHeight()} !important`,
Copy link
Member

Choose a reason for hiding this comment

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

Use of !important is a red flag, is this required? If so, is there a way around it?

verticalAlign: 'top',
position: 'relative',
left: `-${pxToRem(4)}`,
}),
}
4 changes: 2 additions & 2 deletions src/components/Label/labelVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { pxToRem } from '../../lib'

export default () => {
const vars: any = {}
vars.circularRadius = pxToRem(5000)
vars.padding = `${pxToRem(6)} ${pxToRem(8)}`
vars.circularRadius = pxToRem(9999)
vars.padding = `0 ${pxToRem(4)} 0 ${pxToRem(4)}`
vars.color = 'rgba(0, 0, 0, 0.6)'
return vars
}