Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

breaking(Progress): control progress solely with progress #1355

Merged
merged 4 commits into from
Feb 23, 2017

Conversation

BrainMaestro
Copy link
Contributor

@BrainMaestro BrainMaestro commented Feb 20, 2017

Breaking Changes!

The label prop no longer accepts ratio|percent as a means to control the progress readout on the bar. It now refers to the text label applied to the element. The children prop takes precedence however.
The progress prop now handles this by either accepting a boolean which defaults to percent or a string with either ratio or percent.

Before

<Progress total={2} value={1} label='ratio' />
<Progress total={2} value={1} label='percent' />

After

<Progress total={2} value={1} progress='ratio' />
<Progress total={2} value={1} progress='percent' />
<Progress total={2} value={2} label='Dragon ISS Berthing' />

Unchanged

<Progress total={2} value={2}>Dragon ISS Berthing</Progress>

Fixes #1352

@@ -140,10 +140,9 @@ class Progress extends Component {
}

showProgress = () => {
const { label, precision, progress, total, value } = this.props
const { label, precision, progress } = this.props

if (label || progress || !_.isUndefined(precision)) return true
Copy link
Member

Choose a reason for hiding this comment

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

Let's make this condition more simple:

-if (label || progress || !_.isUndefined(precision)) return true
+return label || progress || !_.isUndefined(precision)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. I noticed it, but I didn't want to make changes that were not directly related to the task. I'll do that now

@codecov-io
Copy link

codecov-io commented Feb 20, 2017

Codecov Report

Merging #1355 into master will not change coverage.
The diff coverage is 100%.

@@           Coverage Diff           @@
##           master    #1355   +/-   ##
=======================================
  Coverage   99.74%   99.74%           
=======================================
  Files         140      140           
  Lines        2346     2346           
=======================================
  Hits         2340     2340           
  Misses          6        6
Impacted Files Coverage Δ
src/modules/Progress/Progress.js 100% <100%> (ø)
src/modules/Dropdown/Dropdown.js 100% <ø> (ø)
src/addons/TextArea/TextArea.js 100% <ø> (ø)
src/collections/Form/Form.js 100% <ø> (ø)
src/modules/Checkbox/Checkbox.js 100% <ø> (ø)
src/views/Feed/Feed.js 100% <ø> (ø)
src/modules/Modal/Modal.js 100% <ø> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 82cdbe9...5c3d43a. Read the comment docs.

Copy link
Member

@layershifter layershifter left a comment

Choose a reason for hiding this comment

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

@BrainMaestro Thanks for PR 👍

@levithomason
Copy link
Member

Issue

I think we need to rework the relationship of the progress and label props altogether.

  1. SUI core offers a label setting, which takes a value of percent or ratio. This is where we got our prop label. However, this is super confusing since the label prop controls the progress readout, and the children control the actual label component.

  2. It also makes for this very confusing case where the label boolean prop does exactly the same thing as the booleanprogress prop:

    http://g.recordit.co/iN1aOdD1MR.gif

Fix Proposal

I think we need to make the progress prop control the progress readout and make the label prop control the label component.

image

This would be more inline with our prop-to-subcomponent relationship we have across the entire library as well.


Thoughts?

@BrainMaestro
Copy link
Contributor Author

@levithomason I agree. That makes it clearer. The other way was slightly confusing.

@levithomason
Copy link
Member

levithomason commented Feb 21, 2017

Awesome. Here are some pointers are how to handle the new propTypes and values. The label prop is now a "shorthand" prop used to create the label element. We should start with propTypes like so:

    /** Can be set to either to display progress as percent or ratio. */
    label: customPropTypes.itemShorthand,

    /** A progress bar can contain a text value indicating current progress. */
    progress: PropTypes.oneOfType([
      PropTypes.bool,
      PropTypes.oneOf(['ratio', 'percent']),
    ]),

The itemShorthand allows users to pass a number, string, props object, or an element from which we will then create an element for them. In this case we'll create the className='label' div.

We have a factory function for doing this called, createShorthand. You get it by adding it to the lib import:

import { createShorthand } from '../../lib'

This function takes an element class (string or function), a function to map number/string values to props, and finally the value you want to create an element with (number, string, props object, or another element). Create a labelElement in the render method (comments can be left out):

const labelElement = createShorthand(
  'div',                                // create a div
  val => ({ children: val }),           // map string/numbers to children
  label,                                // use the label prop as the value
  { className: 'label' }                // default props
)

Now, we can conditionally display the children or the labelElement, whichever the user passed.

-{children && <div className='label'>{children}</div>}
+{children ? <div className='label'>{children}</div> : labelElement}

@BrainMaestro
Copy link
Contributor Author

Hey @levithomason. Thanks for the task breakdown. I implemented it exactly as you suggested, but the check {children ? fails for any falsy value which includes 0 that is used in the renders child number with 0 value test. Should I use !_.isUndefined in the render function which is how I solved the problem? Or do you have a cleaner approach?

@levithomason
Copy link
Member

We've updated the code base to use _.isNil(children) so as to capture null and undefined.

@BrainMaestro
Copy link
Contributor Author

Okay has it been merged in?

</div>
)}
</div>
{children && <div className='label'>{children}</div>}
{!_.isUndefined(children) ? <div className='label'>{children}</div> : labelElement}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the line I was talking about. Can I safely change it to {children ? <div className='label'>{children}</div> : labelElement} without the false positives of 0 failing the truthy check?

Copy link
Member

Choose a reason for hiding this comment

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

- {!_.isUndefined(children) ? <div className='label'>{children}</div> : labelElement}
+ {_.isNil(children) ? this.getLabel() : <div className='label'>{children}</div>}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay the label should take priority over the children? I thought it was the reverse. I will make the change

Copy link
Member

@layershifter layershifter Feb 23, 2017

Choose a reason for hiding this comment

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

{_.isNil(children) ? this.getLabel() : <div className='label'>{children}</div>}
{!_.isNil(children) ? <div className='label'>{children}</div> : this.getLabel()}

There conditions do same, but first looks more clear to me.

@BrainMaestro BrainMaestro force-pushed the fix-progress-bar branch 3 times, most recently from 20957e3 to 206ca0f Compare February 23, 2017 14:22
</div>
)}
</div>
{children && <div className='label'>{children}</div>}
{!_.isNil(children) ? <div className='label'>{children}</div> : this.getLabel()}
Copy link
Member

Choose a reason for hiding this comment

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

I think we can move this condition to getLabel:

-  getLabel = () => {
-    const { label } = this.props
-
-    return createShorthand(
-      'div',
-      val => ({ children: val }),
-      label,
-      { className: 'label' }
-    )
-  }
+ renderLabel = () => {
+   const { children, label } = this.props
+   
+   if(!_.isNil(children)) return <div className='label'>{children}</div>

+    return createShorthand(
+      'div',
+      val => ({ children: val }),
+      label,
+      { className: 'label' }
+    )
+ }

@@ -190,11 +195,11 @@ class Progress extends Component {
<div className='bar' style={{ width: `${percent}%` }}>
{this.showProgress() && (
<div className='progress'>
{ label !== 'ratio' ? `${percent}%` : `${value}/${total}` }
{ progress !== 'ratio' ? `${percent}%` : `${value}/${total}` }
</div>
Copy link
Member

Choose a reason for hiding this comment

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

And this to renderProgress:

- {this.showProgress() && (
-  <div className='progress'>
-    { progress !== 'ratio' ? `${percent}%` : `${value}/${total}` }
-  </div>
- })
+ {this.renderProgress()}
+ renderProgress = () => {
+   const { precision, progress } = this.props
+
+   if(!progress && _.isUndefined(precision)) return
+   return (
+     <div className='progress'>
+      { progress === 'ratio' ? `${value}/${total}` : `${percent}%` }
+    </div>
+   )
+}

@levithomason
Copy link
Member

Excellent!

@levithomason levithomason merged commit 7387b4b into Semantic-Org:master Feb 23, 2017
@levithomason
Copy link
Member

This is a breaking change, so we need to update the PR title and description to include upgrade notes. Reference #1367 or #989 for good examples.

@BrainMaestro BrainMaestro changed the title fix(Progress): do not show progress without progress or label props breaking(Progress): control progress solely with progress Feb 24, 2017
@BrainMaestro BrainMaestro deleted the fix-progress-bar branch February 24, 2017 08:38
harel pushed a commit to harel/Semantic-UI-React that referenced this pull request Feb 25, 2017
…emantic-Org#1355)

* fix(Progress): do not show progress without progress or label props

* style(Progress): some style fixes

* style(Progress): update typings

* Update Progress.js
@levithomason
Copy link
Member

Thanks for the great notes @BrainMaestro 👍

@levithomason
Copy link
Member

Released in semantic-ui-react@0.67.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants