@fluentui/react-spinbutton 9.0.8 → 9.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. package/CHANGELOG.json +81 -1
  2. package/CHANGELOG.md +27 -2
  3. package/lib/SpinButton.js.map +1 -1
  4. package/lib/SpinButtonField.js.map +1 -1
  5. package/lib/components/SpinButton/SpinButton.js.map +1 -1
  6. package/lib/components/SpinButton/SpinButton.types.js.map +1 -1
  7. package/lib/components/SpinButton/index.js.map +1 -1
  8. package/lib/components/SpinButton/renderSpinButton.js.map +1 -1
  9. package/lib/components/SpinButton/useSpinButton.js.map +1 -1
  10. package/lib/components/SpinButton/useSpinButtonStyles.js.map +1 -1
  11. package/lib/components/SpinButtonField/SpinButtonField.js.map +1 -1
  12. package/lib/components/SpinButtonField/index.js.map +1 -1
  13. package/lib/index.js.map +1 -1
  14. package/lib/utils/clamp.js.map +1 -1
  15. package/lib/utils/getBound.js.map +1 -1
  16. package/lib/utils/index.js.map +1 -1
  17. package/lib/utils/precision.js.map +1 -1
  18. package/lib-amd/SpinButton.js +6 -0
  19. package/lib-amd/SpinButton.js.map +1 -0
  20. package/lib-amd/SpinButtonField.js +6 -0
  21. package/lib-amd/SpinButtonField.js.map +1 -0
  22. package/lib-amd/components/SpinButton/SpinButton.js +15 -0
  23. package/lib-amd/components/SpinButton/SpinButton.js.map +1 -0
  24. package/lib-amd/components/SpinButton/SpinButton.types.js +5 -0
  25. package/lib-amd/components/SpinButton/SpinButton.types.js.map +1 -0
  26. package/lib-amd/components/SpinButton/index.js +10 -0
  27. package/lib-amd/components/SpinButton/index.js.map +1 -0
  28. package/lib-amd/components/SpinButton/renderSpinButton.js +36 -0
  29. package/lib-amd/components/SpinButton/renderSpinButton.js.map +1 -0
  30. package/lib-amd/components/SpinButton/useSpinButton.js +252 -0
  31. package/lib-amd/components/SpinButton/useSpinButton.js.map +1 -0
  32. package/lib-amd/components/SpinButton/useSpinButtonStyles.js +312 -0
  33. package/lib-amd/components/SpinButton/useSpinButtonStyles.js.map +1 -0
  34. package/lib-amd/components/SpinButtonField/SpinButtonField.js +13 -0
  35. package/lib-amd/components/SpinButtonField/SpinButtonField.js.map +1 -0
  36. package/lib-amd/components/SpinButtonField/index.js +6 -0
  37. package/lib-amd/components/SpinButtonField/index.js.map +1 -0
  38. package/lib-amd/index.js +13 -0
  39. package/lib-amd/index.js.map +1 -0
  40. package/lib-amd/utils/clamp.js +30 -0
  41. package/lib-amd/utils/clamp.js.map +1 -0
  42. package/lib-amd/utils/getBound.js +19 -0
  43. package/lib-amd/utils/getBound.js.map +1 -0
  44. package/lib-amd/utils/index.js +8 -0
  45. package/lib-amd/utils/index.js.map +1 -0
  46. package/lib-amd/utils/precision.js +44 -0
  47. package/lib-amd/utils/precision.js.map +1 -0
  48. package/lib-commonjs/SpinButton.js.map +1 -1
  49. package/lib-commonjs/SpinButtonField.js.map +1 -1
  50. package/lib-commonjs/components/SpinButton/SpinButton.js.map +1 -1
  51. package/lib-commonjs/components/SpinButton/index.js.map +1 -1
  52. package/lib-commonjs/components/SpinButton/renderSpinButton.js.map +1 -1
  53. package/lib-commonjs/components/SpinButton/useSpinButton.js.map +1 -1
  54. package/lib-commonjs/components/SpinButton/useSpinButtonStyles.js.map +1 -1
  55. package/lib-commonjs/components/SpinButtonField/SpinButtonField.js.map +1 -1
  56. package/lib-commonjs/components/SpinButtonField/index.js.map +1 -1
  57. package/lib-commonjs/index.js.map +1 -1
  58. package/lib-commonjs/utils/clamp.js.map +1 -1
  59. package/lib-commonjs/utils/getBound.js.map +1 -1
  60. package/lib-commonjs/utils/index.js.map +1 -1
  61. package/lib-commonjs/utils/precision.js.map +1 -1
  62. package/package.json +8 -9
  63. package/Spec.md +0 -370
  64. package/spec-assets/spec-spinbutton-anatomy-alt-optional.png +0 -0
  65. package/spec-assets/spec-spinbutton-anatomy.png +0 -0
  66. package/spec-assets/spec-spinbutton-rtl.png +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui/react-spinbutton",
3
- "version": "9.0.8",
3
+ "version": "9.0.10",
4
4
  "description": "Fluent UI React SpinButton component.",
5
5
  "main": "lib-commonjs/index.js",
6
6
  "module": "lib/index.js",
@@ -20,26 +20,25 @@
20
20
  "lint": "just-scripts lint",
21
21
  "start": "yarn storybook",
22
22
  "test": "jest --passWithNoTests",
23
- "docs": "api-extractor run --config=config/api-extractor.local.json --local",
24
- "build:local": "tsc -p ./tsconfig.lib.json --module esnext --emitDeclarationOnly && node ../../../scripts/typescript/normalize-import --output ./dist/types/packages/react-components/react-spinbutton/src && yarn docs",
25
23
  "storybook": "start-storybook",
26
- "type-check": "tsc -b tsconfig.json"
24
+ "type-check": "tsc -b tsconfig.json",
25
+ "generate-api": "tsc -p ./tsconfig.lib.json --emitDeclarationOnly && just-scripts api-extractor"
27
26
  },
28
27
  "devDependencies": {
29
28
  "@fluentui/eslint-plugin": "*",
30
29
  "@fluentui/react-conformance": "*",
31
30
  "@fluentui/react-conformance-griffel": "9.0.0-beta.18",
32
- "@fluentui/react-label": "^9.0.10",
31
+ "@fluentui/react-label": "^9.0.12",
33
32
  "@fluentui/scripts": "^1.0.0"
34
33
  },
35
34
  "dependencies": {
36
35
  "@griffel/react": "^1.4.2",
37
36
  "@fluentui/keyboard-keys": "^9.0.1",
38
- "@fluentui/react-field": "9.0.0-alpha.8",
37
+ "@fluentui/react-field": "9.0.0-alpha.10",
39
38
  "@fluentui/react-icons": "^2.0.175",
40
- "@fluentui/react-input": "^9.2.5",
41
- "@fluentui/react-theme": "^9.1.2",
42
- "@fluentui/react-utilities": "^9.2.1",
39
+ "@fluentui/react-input": "^9.2.7",
40
+ "@fluentui/react-theme": "^9.1.3",
41
+ "@fluentui/react-utilities": "^9.2.2",
43
42
  "tslib": "^2.1.0"
44
43
  },
45
44
  "peerDependencies": {
package/Spec.md DELETED
@@ -1,370 +0,0 @@
1
- # @fluentui/react-spinbutton Spec
2
-
3
- ## Background
4
-
5
- SpinButtons are used to allow numeric input bounded between minimum and maximum values with button controls to increment and decrement the input value by some step amount. Values can also be manipulated via the keyboard.
6
-
7
- ## Prior Art
8
-
9
- - Open UI research: https://github.com/openui/open-ui/pull/431
10
- - Github Epic: https://github.com/microsoft/fluentui/issues/20930
11
- - WAI-ARIA Toolbar Example (font size selector): https://www.w3.org/TR/wai-aria-practices/examples/toolbar/toolbar.html
12
-
13
- ### Naming
14
-
15
- There is little consensus for naming this type of component. Of the design systems surveyed in Open UI there are seven implementations with six different names:
16
-
17
- 1. InputNumber
18
- 2. NumberInput
19
- 3. SpinButton (x2)
20
- 4. NumberField
21
- 5. Counter
22
- 6. input-stepper
23
-
24
- This specification recommends `SpinButton` as the name for this component. Given the lack of naming consensus in the surveryed design systems and that the ARIA role for this control is `spinbutton` this feels like the closest to a standard name. Additionally, Fluent UI v8 uses the name `SpinButton` so sticking with that is simpler for existing users making the upgrade to the new version.
25
-
26
- ### Anatomy
27
-
28
- `SpinButton` consists of three mandatory parts:
29
-
30
- 1. **Input**: accepts users input and displays the current value.
31
- 2. **Increment Button**: a button that increases the current value by the step amount.
32
- 3. **Decrement Button**: a button that decreases the current value by the step amount.
33
-
34
- `SpinButton` has several optional parts:
35
-
36
- 1. **Label**: any input must have a label but whether the label is included as part of the `SpinButton` control varies depending on the design system.
37
- 2. **Helper text**: extra text in addition to the label to provide "help", perhaps by offering an example. Typically appears below the input.
38
- 3. **Formatted value**: optional formatting applied to the input value. For example, turning "12" into "12 pt" for a font size picker.
39
-
40
- Note that labels and helper text are included here for completeness but will be omitted from the converged `SpinButton` as there is an [open RFC discussing how to handle these elements for vNext](https://github.com/microsoft/fluentui/issues/19627#issuecomment-1022646775).
41
-
42
- #### Base `SpinButton` Anatomy
43
-
44
- ![Base SpinButton Anatomy (annotated)](./spec-assets/spec-spinbutton-anatomy.png)
45
-
46
- #### Alternate/Optional `SpinButton` Anatomy
47
-
48
- ![Alternate/Optional SpinButton Anatomy (annotated)](./spec-assets/spec-spinbutton-anatomy-alt-optional.png)
49
-
50
- ### Common Features
51
-
52
- #### Attributes
53
-
54
- 1. **min**: the minimum valid value for the control
55
- 2. **max**: the maximum valid value for the control
56
- 3. **step**: the step size or amount the value is changed by one increment or decrement
57
- 4. **value**: the current value for the control
58
-
59
- #### Direct Input
60
-
61
- All `SpinButtons` surveyed can take input directly by typing into the control's input field. Many clamp this value in the range of `min`-`max` but, notably, the native HTML control does not. Rather, it allows values outside this range but puts the control into an invalid state. The [ARIA spec](https://www.w3.org/TR/wai-aria-practices/#wai-aria-roles-states-and-properties-18) allows for the native control behavior or for values to be restricted to only valid values as determined by users of the control.
62
-
63
- #### Step Buttons
64
-
65
- All `SpinButtons` have support for incrementing and decrementing the value via step buttons. Clicking a step button changes the current value of the control by a `step` size (e.g., `1`, `0.1`, `10`, etc.).
66
-
67
- When using a keyboard step buttons are not focusable, rather the control uses the up and down keyboard arrows to modify the current value with the same rules as clicking a step button.
68
-
69
- Unlike directly typing input into the control, step buttons do not allow input outside of the bounds of `min` and `max`.
70
-
71
- ### i18n
72
-
73
- #### RTL (Right to Left Languages)
74
-
75
- Most implementations flip the layout of the control for RTL. Using the base example, the step buttons appear on the left with the value on the right as opposed to the LTR version where the value is on the left and the steppers on the right.
76
-
77
- ![Example of an RTL SpinButton](./spec-assets/spec-spinbutton-rtl.png)
78
-
79
- ### a11y
80
-
81
- The [WAI-ARIA spec for SpinButton](https://www.w3.org/TR/wai-aria-practices/#spinbutton) covers this well and provides examples.
82
-
83
- ### [SpinButton in v8/Fabric](https://developer.microsoft.com/en-us/fluentui#/controls/web/spinbutton)
84
-
85
- Fluent UI v8 (Fabric) ships a `SpinButton` control. This control supports directly typing values into the input field, stepping via step buttons, clamping values in a min-max range and suffixes on the displayed value. The control also supports variants like including an icon in the label, label positioning and styling overrides. `SpinButton` has RTL support and implements the correct ARIA attributes for proper accessibility support.
86
-
87
- One interesting aspect of `SpinButton` in v8 is that the `value` prop (the prop that dictates the actual current value of the control) is a string but `min`, `max` and `step` are all numbers. This is in keeping with `<input type="number">` where the `value` attribute is also a string but it feels odd for a React component that works with numeric values to take in a string `value` prop. As an aside, `<input type="number">` has an additional property called [`valueAsNumber`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement) that is meant for retrieving the value as a `Number`.
88
-
89
- v8 supports an optional icon that appears before the label. As none of the other v8 input controls support adding an icon next to the label as part of their component APIs and how [labeling will work for vNext inputs is still an open question](https://github.com/microsoft/fluentui/issues/19627#issuecomment-1022646775) this feature will be omitted from this spec. Having an icon by the control can be achieved by aligning an icon with the control or perhaps by updating the vNext `Label` component to support icons.
90
-
91
- #### Props
92
-
93
- Props not directly related to `SpinButton` functionality omitted for brevity. [See the complete implementation list](https://developer.microsoft.com/en-us/fluentui#/controls/web/spinbutton#implementation) all props.
94
-
95
- | Prop | Description |
96
- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
97
- | decrementButtonAriaLabel | Accessible label text for the decrement button (for screen reader users). |
98
- | decrementButtonIcon | Custom props for the decrement button. |
99
- | defaultValue | Initial value of the control (assumed to be valid). Updates to this prop will not be respected. Use this if you intend for the SpinButton to be an uncontrolled component which maintains its own value. For a controlled component, use value instead. (Mutually exclusive with value.) |
100
- | disabled | Whether or not the control is disabled. |
101
- | downArrowButtonStyles | Custom styles for the down arrow button. Note: The buttons are in a checked state when arrow keys are used to increment/decrement the SpinButton. Use rootChecked instead of rootPressed for styling when that is the case. |
102
- | iconButtonProps | Additional props for the up and down arrow buttons. |
103
- | iconProps | Props for an icon to display alongside the control's label. |
104
- | incrementButtonAriaLabel | Accessible label text for the increment button (for screen reader users). |
105
- | incrementButtonIcon | Custom props for the increment button. |
106
- | inputProps | Additional props for the input field. |
107
- | keytipProps | Keytip for the control. |
108
- | label | Descriptive label for the control. |
109
- | labelPosition | Where to position the control's label. |
110
- | max | Max value of the control. If not provided, the control has no maximum value. |
111
- | min | Min value of the control. If not provided, the control has no minimum value. |
112
- | onBlur | Callback for when the control loses focus. |
113
- | onChange | Callback for when the committed/validated value changes. This is called _after_ onIncrement, onDecrement, or onValidate, on the following events: - User presses the up/down buttons (on single press or every spin) - User presses the up/down arrow keys (on single press or every spin) - User _commits_ edits to the input text by focusing away (blurring) or pressing enter. Note that this is NOT called for every key press while the user is editing. |
114
- | onDecrement | Callback for when the decrement button or down arrow key is pressed. |
115
- | onFocus | Callback for when the user focuses the control. |
116
- | onIncrement | Callback for when the increment button or up arrow key is pressed. |
117
- | onValidate | Callback for when the entered value should be validated. |
118
- | precision | How many decimal places the value should be rounded to. The default is calculated based on the precision of step: i.e. if step = 1, precision = 0. step = 0.0089, precision = 4. step = 300, precision = 2. step = 23.00, precision = 2. |
119
- | step | Difference between two adjacent values of the control. This value is used to calculate the precision of the input if no precision is given. The precision calculated this way will always be >= 0. |
120
- | title | A more descriptive title for the control, visible on its tooltip. |
121
- | upArrowButtonStyles | Custom styles for the up arrow button. Note: The buttons are in a checked state when arrow keys are used to increment/decrement the SpinButton. Use rootChecked instead of rootPressed for styling when that is the case. |
122
- | value | Current value of the control (assumed to be valid). Only provide this if the SpinButton is a controlled component where you are maintaining its current state and passing updates based on change events; otherwise, use the defaultValue property. (Mutually exclusive with defaultValue.) |
123
-
124
- ### [SpinButton in v0/Northstar](https://fluentsite.z22.web.core.windows.net/0.59.0/components/input/definition)
125
-
126
- Northstar [lacks a dedicated `SpinButton` component](https://github.com/microsoft/fluentui/issues/16273), rather in has `Input` which takes a `type` prop that can be set to `"number"` making the component equivalent of [input type="number"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number).
127
-
128
- Given that Northstar is only providing the native web platform number input without custom styling applied it will not be considered further. In its place the native number input will be considered as it has behavior similar to `SpinButton`.
129
-
130
- ### [input type="number"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number)
131
-
132
- This is a standard HTML control for entering numbers. It includes built-in validation to reject non-numeric values and optionally provides stepper arrows to increment or decrement the value.
133
-
134
- #### Element Attributes
135
-
136
- This is not an exhaustive list of attributes for this element but a curated list of relevant attributes. For a complete list [see the MDN page for `<input type="number">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#additional_attributes)
137
-
138
- | Attribute | Description |
139
- | --------- | ------------------------------------------------------------------------------- |
140
- | list | Allows the input to be associated with a `datalist` to provide suggested values |
141
- | max | Maximum acceptable value. Must be greater than or equal to `min` |
142
- | min | Minimum acceptable value. Must be less than or equal to `max` |
143
- | step | The granularity of the value when incrementing or decrementing |
144
-
145
- Despite supporting both `min` and `max` attributes a native number input will allow users to enter values outside the specified bounds. This situation is resolved via a process called [constraint validation](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation) that adds CSS pseudo classes to the element for styling purposes and raises validation events.
146
-
147
- There are very few options for cross-browser styling of native number inputs. The [::-webkit-inner-spin-button](https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-inner-spin-button) pseudo element allows for selecting the spin buttons of a number input but is only supported by Webkit and Blink based browsers.
148
-
149
- Native number inputs are meant strictly for number input but what constitutes number input is inconsistent across browsers ([see this Bugzilla issue for details](https://bugzilla.mozilla.org/show_bug.cgi?id=1398528)). You can easily see this on [MDN's simple example](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#a_simple_number_input). In Edge 96 you can enter exponential numbers like "1e+343434" but not arbitrary strings like "cats". On the same example in Firefox 95 you can enter both "1e+343434" and "cats".
150
-
151
- Inspecting a native number input with devtools shows that it implements the [spinbutton ARIA attributes as described by WAI-ARIA](https://www.w3.org/TR/wai-aria-practices/#spinbutton)
152
-
153
- #### Examples
154
-
155
- - [Controlling Step Size](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#controlling_step_size)
156
- - [Specifying Minimum and Maximum Values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#specifying_minimum_and_maximum_values)
157
- - [Allowing Decimal Values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#allowing_decimal_values)
158
- - [Offering Suggested Values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#offering_suggested_values)
159
-
160
- ## Sample Code
161
-
162
- ### Uncontrolled Example
163
-
164
- ```tsx
165
- <SpinButton defaultValue="1" />
166
- ```
167
-
168
- ### Controlled Example
169
-
170
- ```tsx
171
- type SpinButtonChangeData = {
172
- value?: number;
173
- displayValue?: string;
174
- };
175
-
176
- const [value, setValue] = useState<number>(2);
177
- const onControlledExampleChange = (_event, data: SpinButtonChangeData) => {
178
- setValue(data.value);
179
- };
180
-
181
- <SpinButton value={value} onChange={onControlledExampleChange} />;
182
- ```
183
-
184
- ### Custom Display Format Example
185
-
186
- ```tsx
187
- type SpinButtonChangeData = {
188
- value: number;
189
- };
190
-
191
- type FormatterFn = (value: number) => string;
192
- type ParserFn = (formattedValue: string) => number;
193
-
194
- // Takes a number in and returns a formatted string
195
- // Ex: 12 becomes "12 pt"
196
- const fontFormatter: FormatterFn = value => {
197
- return `${value} pt`;
198
- };
199
-
200
- // Takes a formatted string in and returns a number
201
- // Ex: "12 pt" becomes 12
202
- const fontParser: ParserFn = formattedValue => {
203
- return parseFloat(formattedValue);
204
- };
205
-
206
- const [value, setValue] = useState<number>(3);
207
- const [displayValue, setDisplayValue] = useState<string>(formatter(3));)
208
-
209
- const onControlledExampleChange = (_event, data: SpinButtonChangeData) => {
210
- if (data.value !== undefined) {
211
- setValue(data.value);
212
- setDisplayValue(fontFormatter(data.value));
213
- } else if (data.displayValue !== undefined) {
214
- const nextValue = fontParser(data.displayValue);
215
- setValue(nextValue);
216
- setDisplayValue(fontFormatter(nextValue));
217
- }
218
- };
219
-
220
- <SpinButton
221
- value={value}
222
- displayValue={displayValue}
223
- onChange={onControlledExampleChange}
224
- />
225
- ```
226
-
227
- ### Basic Example Implementation
228
-
229
- A very basic example to demonstrate how formatting will work in practice.
230
-
231
- [Link to example on Codesandbox](https://codesandbox.io/s/spinbutton-example-formatted-values-66pou?file=/src/SpinButton/SpinButton.js)
232
-
233
- ## API
234
-
235
- [See the types](./components/SpinButton/SpinButton.types.ts)
236
-
237
- ## Structure
238
-
239
- - _**Public**_
240
-
241
- ```tsx
242
- <SpinButton value={10} displayValue="$10.00" min={1} max={100} step={5} />
243
- ```
244
-
245
- - _**Internal**_
246
-
247
- ```tsx
248
- <slots.root {...slotProps.root}>
249
- <slots.input {...slotProps.input} />
250
- <slots.incrementButton {...slots.incrementButton} />
251
- <slots.decrementButton {...slots.decrementButton} />
252
- </slots.root>
253
- ```
254
-
255
- - _**DOM** - how the component will be rendered as HTML elements_
256
-
257
- Note that `aria-valuetext` is conditionally rendered. In this case it is rendered because formatting is applied in this example by the `displayValue` prop in JSX.
258
-
259
- ```html
260
- <!-- root slot -->
261
- <div class="fui-SpinButton">
262
- <!-- input slot -->
263
- <input
264
- type="text"
265
- role="spinbutton"
266
- class="fui-SpinButton-input"
267
- value="$10.00"
268
- aria-valuenow="10"
269
- aria-valuemin="1"
270
- aria-valuemax="100"
271
- aria-valuetext="$10.00"
272
- />
273
- <!-- increment button slot -->
274
- <!-- note we'll probably using icons rather than "+" and "-" inside the buttons -->
275
- <button tabindex="-1" type="button" class="fui-SpinButton-button fui-SpinButton-increment-button">+</button>
276
- <!-- decrement button slot -->
277
- <button tabindex="-1" type="button" class="fui-SpinButton-button fui-SpinButton-decrement-button">-</button>
278
- </div>
279
- ```
280
-
281
- ## Migration
282
-
283
- _Describe what will need to be done to upgrade from the existing implementations:_
284
-
285
- - _Migration from v8_
286
-
287
- 1. Ensure `value` prop is a number, not a string
288
- 2. Replace `onIncrement` and `onDecrement` callbacks with `onChange`.
289
- 1. Increment/decrement logic can be handled by comparing `data.value` and the current React/Redux/etc state value in the `onChange` callback.
290
- 3. Update `onChange` callback to handle new signature.
291
- 4. Remove `onValidate` callback.
292
- 5. Change ARIA props.
293
- 1. Change non-standard props to standard ones (e.g., `ariaLabel` to `aria-label`).
294
- 2. Remove `ariaPositionInSet`, `ariaSetSize`, `ariaValueNow`, `ariaValueText`. The first two are not relevant for a spinbutton and the latter two are internal implementation details managed by the component.
295
-
296
- - _Migration from v0_
297
-
298
- Not applicable as v0 does not implement this component or one like it.
299
-
300
- ## Behaviors
301
-
302
- `SpinButton`'s `value` prop is always a number, in contrast to the v8 implementation that gave `value` a string type. `SpinButton`s manipulate numeric values and making `value` a number aligns it with the other related props: `min`, `max` and `step`. `SpinButton`'s `value` is always displayed as a string which is determined by the `displayValue` prop or by stringifying `value` when `displayValue` is not provided (for uncontrolled `SpinButton`s `defaultValue` is stringified rather than `value`).
303
-
304
- `SpinButton` users may apply custom formatting to the component by providing a value to the `displayValue` prop.
305
-
306
- Values outside of the min/max bounds can be provided to `SpinButton` and they will be displayed. When stepping the value with the step buttons or hotkeys the value will not be stepped outside of the min/max bounds. If the value starts outside of the min/max bounds and is stepped it will update to a value outside of the bounds. Once the value is stepped inside the min/max bounds it will be clamped to this range.
307
-
308
- For example, assume a `SpinButton` with min=5, max=10, value=1 and step=1. Incrementing `value` with the stepper will increase it to 2.
309
-
310
- Any value may be typing into the `<input>` element of `SpinButton`. When typing into the input `SpinButton` enters an intermediate state where changes to the input are not applied to `value`. Instead the user must "commit" their edits to trigger a `value` update. This can be done two ways:
311
-
312
- 1. Blur the input field (i.e., tab or click away)
313
- 2. Use one of `SpinButton`'s hotkeys to modify the value.
314
-
315
- Aside from min/max range clamping behavior described above `SpinButton` does not currently implement any input validation.
316
-
317
- No error states are currently implemented.
318
-
319
- `SpinButton`'s `onChange` callback is invoked every time a change is committed. A change is committed when:
320
-
321
- 1. A step button is activated (e.g., clicked with a mouse or activated with a screen reader)
322
- 2. When a user presses the `Arrow Up`, `Arrow Down`, `Home` or `End` keys while focused on the component.
323
- 3. When the `blur` event is fired from the `<input>`
324
-
325
- The `onChange` callback is not invoked while a user is focused on the `<input>` and editing the value of the `SpinButton` directly.
326
-
327
- ### Component States
328
-
329
- - Rest (no value or valid value, not focused)
330
- - Focused
331
- - Disabled
332
- - Error/Warning (value is invalid in some way). NB: error and validation are not currently supported.
333
-
334
- ### Interaction
335
-
336
- #### Keyboard
337
-
338
- - Tab focuses the `<input>` element
339
- - Up arrow key increments the value by `step` until `max`, if specified.
340
- - Down arrow key decrements the value by `step` until `min`, if specified.
341
- - Home key sets the value to `min`, if specified.
342
- - End key sets the value to `max`, if specified.
343
- - Tab never focuses the increment or decrement buttons as their functionality is fully available via the keyboard
344
-
345
- #### Cursor
346
-
347
- - Clicking on the `<input>` focuses it.
348
- - Input supports all device/platform mouse interactions (i.e., text selection)
349
- - Clicking the increment button increases the value by `step` until `max`, if specified.
350
- - Clicking the decrement button decreases the value by `step` until `min`, if specified.
351
-
352
- #### Touch
353
-
354
- Same as cursor.
355
-
356
- #### Screen Readers
357
-
358
- - `<input>` is focusable and editable using standard device/platform interactions.
359
- - increment and decrement buttons are both focusable and usable with standard device/platform interactions.
360
- - If formatting is applied to values `aria-valuetext` is applied to the `spinbutton` and read by the screen reader.
361
-
362
- ## Accessibility
363
-
364
- The converged `SpinButton` component will not use the native HTML spin button (`input type="number"`) as this control has inconsistent cross-browser behavior and lacks styling options. Rather ARIA will be applied to achieve an accessible component that behaves consistently on all support platforms with robust styling options.
365
-
366
- Only the `<input>` element of `SpinButton` can be focused via the keyboard. The ARIA `spinbutton` design pattern calls for keyboard shortcuts (up/down arrow) to fulfill the value step functionality, making focus for the increment and decrement buttons redundant.
367
-
368
- - [ARIA design pattern: SpinButton](https://www.w3.org/TR/wai-aria-practices/#spinbutton)
369
- - [Date Picker Example](https://www.w3.org/TR/wai-aria-practices/examples/spinbutton/datepicker-spinbuttons.html)
370
- - [Toolbar (Font Picker) Example](https://www.w3.org/TR/wai-aria-practices/examples/toolbar/toolbar.html)
Binary file