-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New Component: Stepper (Spin Button) #1759
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
Conversation
| } | ||
|
|
||
| export interface ISpinButton { | ||
| value?: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: jsdoc comments?
|
|
||
| describe('SpinButton', () => { | ||
| function renderIntoDocument(element: React.ReactElement<any>): HTMLElement { | ||
| const component = ReactTestUtils.renderIntoDocument(element); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not use shallow and full enzyme rendering?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jair-cazarin, we followed what other unit tests are doing. Is there a benefit to using Shallow and Enzyme rendering?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I understand that, perhaps we should just do a separate work to migrate all UTs to enzyme.
|
|
||
| let newCurrentValue = inputDOM.value; | ||
| expect(currentValue).to.equal(newCurrentValue); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing test that gets the value from the component instance when uncontrolled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We added more tests for that.
| private _stepDelay = 100; | ||
| private _formattedValidUnitOptions: string[] = []; | ||
|
|
||
| constructor(props?: ISpinButtonProps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is the argument props optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it shouldn't be optional. Thanks!
| iconProps={ incrementButtonIcon } | ||
| title='Increase' | ||
| aria-hidden='true' | ||
| onMouseDown={ () => { this._updateValue(true /* shouldSpin */, this._onIncrement); } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is pretty much allocating a new function for every render...does it make sense to make it a class member?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the benefits of using a class member?
It would require us to either create two almost similar functions or check the event to see if increase or decrease is triggered, which seems fragile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As is now, every time it renders is creating a new function that is bind to onMouseDown. If you use a a class method or store it in a field it would not. This typically breaks pure components since you pass a new reference hence shallow reference checks fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, thanks for the explanation!
| className={ css('ms-UpButton', styles.UpButton, (keyboardSpinDirection === KeyboardSpinDirection.up ? styles.active : '')) } | ||
| disabled={ disabled } | ||
| iconProps={ incrementButtonIcon } | ||
| title='Increase' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't title be localizable/configurable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. We actually moved the title to the outter component.
| * Set the label direction with the gap on the correct side | ||
| */ | ||
| @autobind | ||
| private _labelDirectionHelper(): any { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment before about considering renaming this function to be getLabelDirectionStyle or something like that
| */ | ||
| @autobind | ||
| private _stop() { | ||
| if (this._currentStepFunctionHandle !== null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_currentStepFunctionHandle is a number, should this be explicitly comparing to 0 instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we used 0 instead of null.
| @autobind | ||
| private _handleKeyUp(event: React.KeyboardEvent<HTMLElement>) { | ||
|
|
||
| if (this.props.disabled) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment before about collapsing these two if cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about the missing comments, sometimes GitHub collapses comments for no apparent reason, making it hard to see what has been addressed or not.
|
@cschleiden, we've taken a look at the time picker in VSTS mobile, and it feels different than what we're building here. I added a screenshot illustrating the SpinButton to this PR. |
| value?: number; | ||
| /** | ||
| * The value of the SpinButton. Use this if you intend to pass in a new value as a result of onChange events. | ||
| * This value is mutually exclusive to defaultValue. Use one or the other. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if this description matches the intention of this, can you set the value from here? I thought this was for readonly when using the component as uncontrolled component.
| ReactTestUtils.Simulate.mouseDown(downButtonDOM); | ||
| ReactTestUtils.Simulate.mouseUp(downButtonDOM); | ||
|
|
||
| expect(inputDOM.value).to.equal(String(exampleNewValue)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the value be checked from the component instance rather than the HTML element?
|
@Boris-Em, |
|
I think this conflicted with the fabric-core merge; @Boris-Em can you repair the sass merge? If you are confused @mikewheaton is the expert on the fabric-core sass renames and can help clarify |
|
oh nice finally passing! I will take a look |
* First step at stepper implementation. * Add first implementation of stepper. * Add functionality to stepper * Refine the Stepper class and add tests * let's make sure to put focus back on the text field when submitting via enter * Added documentation to Stepper. * Add flexibility to current stepper implementation. * Modified example implementations. * Add aria-valuemax. * Change Stepper to SpinButton. * Add example with unit. * Implement color scheme in the ContextualMenu control to enable alternative theming. * Improvements to SpinButton. * Fix increment function calls. * Add new width optional parameter. * Add label direction. * Fix border. * Add Position enum. * `defaultValue` is now the deciding prop for using the default implementation or not. * onBlur is now onValidate. * Fix tests. * Fix warnings. * Add implementation for labelGap. * Put some polish on the styling, added some icon support, and added some more example spinButtons * Implement the bar and unit tests and component page * Add the ability for the spinButton buttons to look pressed when spinning via keyboard * Revert "Implement color scheme in the ContextualMenu control to enable alternative theming." This reverts commit 4f830cd. * Don't render an empty icon for an icon-less header menu item. * Revert "Implement Document Title Bar" * update some CSS for high contrast in ff and use css utility instead of concatenating string classnames * Fix quotation issue * Fix Spin Button properties table. * Fix Spin Button example code * Use iconProps instead of string * Extracted `spinning` out of state * Add autobind instead of manually binding private functions to this * Change `+` syntax for more explicit `Number()` * Remove unnecessary cast * Fix typos * `incrementButtonIcon` and `decrementButtonIcon` are now IIconProps * Add KeyboardSpinDirection enum * Fix test description * Fix SpinButton tests * Remove unused onChange callback from SpinButton * Revert onChange * Remove old Stepper.ts file * Use module css instead of global * Fix missing word in comment * Callback functions now allow for void return (state to be updated outside) * Use `_async` instead of window * Fix minor rendering issue with browser zoom * Rename `_spinning` to `_spinningByMouse` for clarity * Fix tests * Fix extra space before label * Remove width outside of SpinButton component and fix styling * Add more tests to SpinButton * Fix SpinButton documentation * Fix typo * Fix AppDefinition for SpinButton and Spinner * Add missing documentation to SpinButton title prop * Various SpinButton fixes * Fix SpinButton path for properties * Fix SpinButton styling issues * Remove labelGap property from SpinButton
* Add ComboBox functionality * Make a fix for IE where non-allowFreeform is showing the keypresses... * Update the PR with code review feedback. Simplified the code a lot, decoupled the shared props/memebers from comboBox and Dropdown, and extended BaseAutoFill which allowed DynamicAutoFill to be removed * Fixing some build warnings * Update my example page to explicitly not use two mutually exclusive props * The npm-shrinkwrap.json file automatically updated... commiting * Had a bad copy paste, fixing up the incorrectly logic * Removing the fontFamily aspect of the comboBox and utilizing the onRenderOption instead. The fontFamily aspect was too specific for the generic comboBox * Update based on feedback * Jspurlin jspurlin/combo box (#2) * Enable no implicit any in the utilities package (#1970) * Fix no implicit anys in utilities package. * Rush change * Reverse all shrinkwrap changes except the typings one. * Fix bundle minification to exclude debug warnings. (#1973) * Updating shrinkwrap, rush, and making minify build have production flag to remove debug code. * Updates. * removing lockfile. * dropping to 7. Moving back to npm run build. * Downgrading rush. * Applying package updates. * Website: Update dev.office.com header (#1966) * Use Fabric Core 7.1.0 for the website * Adjust position of caret's in header so that they spin around central axis * Update to latest icon font from dev.office.com for header and move outside out :global{} to fix build issue * Remove a u- prefix that was missed earlier * Update dev.office.com header with the latest navigation links * Add change file * Make sure the quote rule is enabled for tsline (#1961) * With responsive mode error (#1956) * withResponsiveMode: Adding error handling around the case where window.innerWidth throws an exception * adding change log file * Create withResponsiveMode.tsx * New Component: Stepper (#1759) * First step at stepper implementation. * Add first implementation of stepper. * Add functionality to stepper * Refine the Stepper class and add tests * let's make sure to put focus back on the text field when submitting via enter * Added documentation to Stepper. * Add flexibility to current stepper implementation. * Modified example implementations. * Add aria-valuemax. * Change Stepper to SpinButton. * Add example with unit. * Implement color scheme in the ContextualMenu control to enable alternative theming. * Improvements to SpinButton. * Fix increment function calls. * Add new width optional parameter. * Add label direction. * Fix border. * Add Position enum. * `defaultValue` is now the deciding prop for using the default implementation or not. * onBlur is now onValidate. * Fix tests. * Fix warnings. * Add implementation for labelGap. * Put some polish on the styling, added some icon support, and added some more example spinButtons * Implement the bar and unit tests and component page * Add the ability for the spinButton buttons to look pressed when spinning via keyboard * Revert "Implement color scheme in the ContextualMenu control to enable alternative theming." This reverts commit 4f830cd. * Don't render an empty icon for an icon-less header menu item. * Revert "Implement Document Title Bar" * update some CSS for high contrast in ff and use css utility instead of concatenating string classnames * Fix quotation issue * Fix Spin Button properties table. * Fix Spin Button example code * Use iconProps instead of string * Extracted `spinning` out of state * Add autobind instead of manually binding private functions to this * Change `+` syntax for more explicit `Number()` * Remove unnecessary cast * Fix typos * `incrementButtonIcon` and `decrementButtonIcon` are now IIconProps * Add KeyboardSpinDirection enum * Fix test description * Fix SpinButton tests * Remove unused onChange callback from SpinButton * Revert onChange * Remove old Stepper.ts file * Use module css instead of global * Fix missing word in comment * Callback functions now allow for void return (state to be updated outside) * Use `_async` instead of window * Fix minor rendering issue with browser zoom * Rename `_spinning` to `_spinningByMouse` for clarity * Fix tests * Fix extra space before label * Remove width outside of SpinButton component and fix styling * Add more tests to SpinButton * Fix SpinButton documentation * Fix typo * Fix AppDefinition for SpinButton and Spinner * Add missing documentation to SpinButton title prop * Various SpinButton fixes * Fix SpinButton path for properties * Fix SpinButton styling issues * Remove labelGap property from SpinButton * merge some changes * merge changes * merge * Fix a new tslint warning after npm installing * Fixing some casing warnings npm start was angry about * Removing an extra line that got added with the last push * Create SelectableOption.ts * Create SelectableOption.ts * Create ComboBox.Props.ts * Create ComboBox.test.tsx * Create ComboBox.Basic.Example.tsx * Create Dropdown.Props.ts * Fix the case sensitivity issue * one more casing issue * changing the reference of utilities in the test file * Actually it look like it has to be pascalCase here * ... really... what's going on with the casing here * Address feedback from in person review with David * A few minor updated to remove uneeded comment and unneeded try/finally in tests * Fix up a typo and fix up to use consistent syntax on a few lines
Pull request checklist
Description of changes
This PR adds a new component: the SpinButton.
Here is an example of a SpinButton:
