-
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
Changes from all commits
8e1b55a
d54e9f4
4369f67
41ac16a
0d1412f
8570e56
f78f686
8e28b99
4ccaf1d
4e2f418
d699fc0
4f830cd
ffa948d
40c6f64
f002ceb
486fc93
68e4c1f
e6fbc48
25cf2cf
0fe58fe
9241663
21453e3
629d21d
8475fc4
94d2adc
fdaadbd
6b9716d
238ad26
0436c11
590d005
ee4b3d0
a74f950
107af4d
f5c7bb3
9fbfc1c
d309a83
c9a3dc7
e3b3962
be816b6
4e7b615
4348ca5
89976f7
c4ac999
5720c2d
a65634d
7b6061f
a9564ee
8112bac
5c641eb
e33deba
0d56702
b822c98
3cfc49a
b948cae
b089ade
c385ca2
a6d4c80
ff61822
bd53c5a
c711744
16ee4d2
b70c862
ec02de3
a5aac7c
fbccd1b
0f3561f
faa7700
f359b37
a82c296
1c56b5e
70edd03
8d5f70c
717f233
297d56d
102a1b7
482e785
58562b3
0604770
f4d96b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import * as React from 'react'; | ||
| import { SpinButtonPage } from 'office-ui-fabric-react/lib/components/SpinButton/SpinButtonPage'; | ||
| import { PageHeader } from '../../components/PageHeader/PageHeader'; | ||
| import { ComponentPage } from '../../components/ComponentPage/ComponentPage'; | ||
|
|
||
| export class SpinButtonComponentPage extends React.Component<any, any> { | ||
| public render() { | ||
| return ( | ||
| <div ref='pageElement'> | ||
| <ComponentPage> | ||
| <PageHeader pageTitle='SpinButton' backgroundColor='#038387' | ||
| links={ | ||
| [ | ||
| { | ||
| 'text': 'Overview', | ||
| 'location': 'Overview' | ||
| }, | ||
| { | ||
| 'text': 'Best Practices', | ||
| 'location': 'Best Practices' | ||
| }, | ||
| { | ||
| 'text': 'Variants', | ||
| 'location': 'Variants' | ||
| }, | ||
| { | ||
| 'text': 'Implementation', | ||
| 'location': 'Implementation' | ||
| } | ||
| ] | ||
| } /> | ||
| <SpinButtonPage isHeaderVisible={ false } /> | ||
| </ComponentPage> | ||
| </div> | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './components/SpinButton/index'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import { Position } from '../../utilities/positioning'; | ||
| import { IIconProps } from '../../Icon'; | ||
|
|
||
| export interface ISpinButtonProps { | ||
|
|
||
| /** | ||
| * The initial value of the SpinButton. Use this if you intend for the SpinButton to be an uncontrolled component. | ||
| * This value is mutually exclusive to value. Use one or the other. | ||
| * @default 0 | ||
| */ | ||
| defaultValue?: string; | ||
|
|
||
| /** | ||
| * 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. | ||
| */ | ||
| value?: string; | ||
|
|
||
| /** | ||
| * The min value of the SpinButton. | ||
| * @default 0 | ||
| */ | ||
| min?: number; | ||
|
|
||
| /** | ||
| * The max value of the SpinButton. | ||
| * @default 10 | ||
| */ | ||
| max?: number; | ||
|
|
||
| /** | ||
| * The difference between the two adjacent values of the SpinButton. | ||
| * @default 1 | ||
| */ | ||
| step?: number; | ||
|
|
||
| /** | ||
| * A description of the SpinButton for the benefit of screen readers. | ||
| */ | ||
| ariaLabel?: string; | ||
|
|
||
| /** | ||
| * A title for the SpinButton used for a more descriptive name that's also visible on its tooltip. | ||
| */ | ||
| title?: string; | ||
|
|
||
| /** | ||
| * Whether or not the SpinButton is disabled. | ||
| */ | ||
| disabled?: boolean; | ||
|
|
||
| /** | ||
| * Optional className for SpinButton. | ||
| */ | ||
| className?: string; | ||
|
|
||
| /** | ||
| * Descriptive label for the SpinButton. | ||
| */ | ||
| label: string; | ||
|
|
||
| /** | ||
| * @default: Left | ||
| */ | ||
| labelPosition?: Position; | ||
|
|
||
| /** | ||
|
||
| * Icon that goes along with the label for the whole SpinButton | ||
| */ | ||
| iconProps?: IIconProps; | ||
|
|
||
| /** | ||
| * This callback is triggered when the value inside the SpinButton should be validated. | ||
| * @return {string | void} If a string is returned, it will be used as the value of the SpinButton. | ||
| */ | ||
| onValidate?: (value: string) => string | void; | ||
|
|
||
| /** | ||
| * This callback is triggered when the increment button is pressed or if the user presses up arrow with focus on the input of the spinButton | ||
| * @return {string | void} If a string is returned, it will be used as the value of the SpinButton. | ||
| */ | ||
| onIncrement?: (value: string) => string | void; | ||
|
|
||
| /** | ||
| * This callback is triggered when the decrement button is pressed or if the user presses down arrow with focus on the input of the spinButton | ||
| * @return {string | void} If a string is returned, it will be used as the value of the SpinButton. | ||
| */ | ||
| onDecrement?: (value: string) => string | void; | ||
|
|
||
| /** | ||
| * Icon for the increment button of the spinButton | ||
| */ | ||
| incrementButtonIcon?: IIconProps; | ||
|
|
||
| /** | ||
| * Icon for the decrement button of the spinButton | ||
| */ | ||
| decrementButtonIcon?: IIconProps; | ||
| } | ||
|
|
||
| export interface ISpinButton { | ||
| /** | ||
| * 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. | ||
| */ | ||
| value?: string; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,226 @@ | ||
| @import '../../common/common'; | ||
| @import '../Label/LabelMixins.scss'; | ||
|
|
||
| .ArrowBox, .Input, | ||
| .UpButton, .DownButton, .SpinButtonContainer { | ||
| outline: none; | ||
| font-size: 12px; | ||
| } | ||
|
|
||
| .SpinButtonLabel { | ||
| pointer-events: none; | ||
| padding: 2px 0px; | ||
| } | ||
|
|
||
| .SpinButtonContainer { | ||
| width: 100%; | ||
| min-width: 86px; | ||
| padding: 2px; | ||
| } | ||
|
|
||
| .ArrowBox { | ||
| display: block; | ||
| float: left; | ||
| height: 100%; | ||
| border: 1px solid $ms-color-neutralTertiaryAlt; | ||
| border-left-width: 0px; | ||
| cursor: default; | ||
| padding: 0px; | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
| .SpinButtonWrapper:hover .ArrowBox, .SpinButtonWrapper:hover .Input { | ||
| border-color: $ms-color-neutralSecondaryAlt; | ||
| outline: 2px dashed transparent; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| border-color: $ms-color-contrastBlackSelected; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| border-color: $ms-color-contrastWhiteSelected; | ||
| } | ||
| } | ||
|
|
||
| .labelWrapper { | ||
| display: inline-flex; | ||
|
|
||
| &.start { | ||
| float: left; | ||
| margin-right: 10px; | ||
| } | ||
|
|
||
| &.end { | ||
| float: right; | ||
| margin-left: 10px; | ||
| } | ||
|
|
||
| &.top { | ||
| margin-bottom: 10px; | ||
| } | ||
|
|
||
| &.bottom { | ||
| margin-top: 10px; | ||
| } | ||
| } | ||
|
|
||
| .SpinButtonIcon { | ||
| padding: 2px 5px; | ||
| font-size: 20px; | ||
| } | ||
|
|
||
| .SpinButtonWrapper { | ||
| display: flex; | ||
| height: 26px; | ||
| min-width: 86px; | ||
| } | ||
|
|
||
| .SpinButtonWrapper.topBottom { | ||
| width: 100%; | ||
| } | ||
|
|
||
| .Input:focus + .ArrowBox { | ||
| border-color: $ms-color-themePrimary; | ||
| outline: 2px dashed transparent; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| border-color: $ms-color-contrastBlackSelected; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| border-color: $ms-color-contrastWhiteSelected; | ||
| } | ||
| } | ||
|
|
||
| .Input.disabled + .ArrowBox { | ||
| background-color: $ms-color-neutralLighter; | ||
| border-color: $ms-color-neutralLighter; | ||
| pointer-events: none; | ||
| cursor: default; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| color: $ms-color-contrastBlackDisabled; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| color: $ms-color-contrastWhiteDisabled; | ||
| } | ||
| } | ||
|
|
||
| .SpinButtonWrapper:hover .Input:focus { | ||
| border-color: $ms-color-themePrimary; | ||
| } | ||
|
|
||
| .Input { | ||
| @include ms-normalize; | ||
| border: 1px solid $ms-color-neutralTertiaryAlt; | ||
| border-radius: 0; | ||
| font-weight: $ms-font-weight-regular; | ||
| font-size: $ms-font-size-m; | ||
| color: $ms-color-neutralPrimary; | ||
| height: 100%; | ||
| @include padding(3px, 3px, 4px, 4px); | ||
| outline: 0; | ||
| text-overflow: ellipsis; | ||
| display: block; | ||
| float: left; | ||
| width: calc(100% - 14px); | ||
| min-width: 72px; | ||
| border-right-width: 0px; | ||
| overflow: hidden; | ||
| cursor: text; | ||
| user-select: text; | ||
|
|
||
| &:focus { | ||
| border-color: $ms-color-themePrimary; | ||
| outline: 2px dashed transparent; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| border-color: $ms-color-contrastBlackSelected; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| border-color: $ms-color-contrastWhiteSelected; | ||
| } | ||
| } | ||
|
|
||
| &::selection { | ||
| background-color: $ms-color-themePrimary; | ||
| color: $ms-color-white; | ||
| } | ||
| } | ||
|
|
||
| .SpinButtonWrapper:hover .Input.disabled, | ||
| .Input.disabled { | ||
| background-color: $ms-color-neutralLighter; | ||
| border-color: $ms-color-neutralLighter; | ||
| pointer-events: none; | ||
| cursor: default; | ||
| color: $ms-color-neutralTertiaryAlt; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| color: $ms-color-contrastBlackDisabled; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| color: $ms-color-contrastWhiteDisabled; | ||
| } | ||
| } | ||
|
|
||
| .Input:hover .UpButton, .Input:hover .DownButton { | ||
| background-color: $ms-color-neutralLighter; | ||
| } | ||
|
|
||
| .SpinButtonWrapper .UpButton, .SpinButtonWrapper .DownButton { | ||
| display: block; | ||
| height: 50%; | ||
| width: 12px; | ||
| padding: 0px; | ||
| background-color: transparent; | ||
| text-align: center; | ||
| cursor: default; | ||
| font-size: 6px; | ||
| color: $ms-color-neutralPrimary; | ||
|
|
||
| &:hover { | ||
| background-color: $ms-color-neutralLight; | ||
| } | ||
|
|
||
| &:active { | ||
| background-color: $ms-color-themePrimary; | ||
| color: $ms-color-white; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| background-color: $ms-color-contrastBlackSelected; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| background-color: $ms-color-contrastWhiteSelected; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| .UpButton:disabled, .DownButton:disabled { | ||
| opacity: 0; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| color: $ms-color-contrastBlackDisabled; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| color: $ms-color-contrastWhiteDisabled; | ||
| } | ||
| } | ||
|
|
||
| .SpinButtonWrapper .UpButton.active, .SpinButtonWrapper .DownButton.active { | ||
| background-color: $ms-color-themePrimary; | ||
| color: $ms-color-white; | ||
|
|
||
| @media screen and (-ms-high-contrast: active) { | ||
| background-color: $ms-color-contrastBlackSelected; | ||
| } | ||
|
|
||
| @media screen and (-ms-high-contrast: black-on-white) { | ||
| background-color: $ms-color-contrastWhiteSelected; | ||
| } | ||
| } |
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 also missing _warnMutuallyExclusive for defaultValue and value in the component constructor