@instructure/ui-number-input 11.7.4-snapshot-121 → 11.7.4-snapshot-125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,9 +3,13 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [11.7.4-snapshot-121](https://github.com/instructure/instructure-ui/compare/v11.7.3...v11.7.4-snapshot-121) (2026-07-22)
6
+ ## [11.7.4-snapshot-125](https://github.com/instructure/instructure-ui/compare/v11.7.3...v11.7.4-snapshot-125) (2026-07-22)
7
7
 
8
- **Note:** Version bump only for package @instructure/ui-number-input
8
+
9
+ ### Bug Fixes
10
+
11
+ * **many:** keep form field messages out of the control's accessible name ([409d077](https://github.com/instructure/instructure-ui/commit/409d077a3095b318fd7d2e150bb01bc2732c9bf5))
12
+ * **many:** only reference rendered messages via aria-describedby ([ccc9516](https://github.com/instructure/instructure-ui/commit/ccc95165ec8dae6d06e001c0a20fcebef1cf9962))
9
13
 
10
14
 
11
15
 
@@ -82,6 +82,9 @@ const NumberInput = /*#__PURE__*/forwardRef((props, ref) => {
82
82
  // Computed values
83
83
  const invalid = !!messages && messages.some(message => message.type === 'error' || message.type === 'newError');
84
84
  const success = !!messages && messages.some(message => message.type === 'success');
85
+ const hasMessages = !!messages?.some(m => !!m.text);
86
+ const messagesId = id ? `${id}-messages` : undefined;
87
+ const labelId = id ? `${id}-label` : undefined;
85
88
  const interaction = getInteraction({
86
89
  props
87
90
  });
@@ -229,6 +232,8 @@ const NumberInput = /*#__PURE__*/forwardRef((props, ref) => {
229
232
  return _jsx(FormField, {
230
233
  ...pickProps(props, FormField.allowedProps),
231
234
  label: label,
235
+ messagesId: messagesId,
236
+ labelId: labelId,
232
237
  inline: display === 'inline-block',
233
238
  id: id,
234
239
  elementRef: handleRef,
@@ -247,7 +252,11 @@ const NumberInput = /*#__PURE__*/forwardRef((props, ref) => {
247
252
  children: [_jsx("input", {
248
253
  ...passedProps,
249
254
  css: styles?.input,
250
- "aria-invalid": invalid ? 'true' : undefined,
255
+ "aria-invalid": invalid ? 'true' : undefined
256
+ // Keep messages in the description so the accessible name contains only the label.
257
+ ,
258
+ "aria-describedby": [passedProps['aria-describedby'], hasMessages ? messagesId : null].filter(Boolean).join(' ') || undefined,
259
+ "aria-labelledby": hasMessages ? passedProps['aria-labelledby'] || labelId : passedProps['aria-labelledby'],
251
260
  id: id,
252
261
  type: allowStringValue ? 'text' : 'number',
253
262
  inputMode: inputMode,
@@ -93,6 +93,9 @@ const NumberInput = exports.NumberInput = /*#__PURE__*/(0, _react.forwardRef)((p
93
93
  // Computed values
94
94
  const invalid = !!messages && messages.some(message => message.type === 'error' || message.type === 'newError');
95
95
  const success = !!messages && messages.some(message => message.type === 'success');
96
+ const hasMessages = !!messages?.some(m => !!m.text);
97
+ const messagesId = id ? `${id}-messages` : undefined;
98
+ const labelId = id ? `${id}-label` : undefined;
96
99
  const interaction = (0, _getInteraction.getInteraction)({
97
100
  props
98
101
  });
@@ -240,6 +243,8 @@ const NumberInput = exports.NumberInput = /*#__PURE__*/(0, _react.forwardRef)((p
240
243
  return (0, _jsxRuntime.jsx)(_latest.FormField, {
241
244
  ...(0, _pickProps.pickProps)(props, _latest.FormField.allowedProps),
242
245
  label: label,
246
+ messagesId: messagesId,
247
+ labelId: labelId,
243
248
  inline: display === 'inline-block',
244
249
  id: id,
245
250
  elementRef: handleRef,
@@ -258,7 +263,11 @@ const NumberInput = exports.NumberInput = /*#__PURE__*/(0, _react.forwardRef)((p
258
263
  children: [(0, _jsxRuntime.jsx)("input", {
259
264
  ...passedProps,
260
265
  css: styles?.input,
261
- "aria-invalid": invalid ? 'true' : undefined,
266
+ "aria-invalid": invalid ? 'true' : undefined
267
+ // Keep messages in the description so the accessible name contains only the label.
268
+ ,
269
+ "aria-describedby": [passedProps['aria-describedby'], hasMessages ? messagesId : null].filter(Boolean).join(' ') || undefined,
270
+ "aria-labelledby": hasMessages ? passedProps['aria-labelledby'] || labelId : passedProps['aria-labelledby'],
262
271
  id: id,
263
272
  type: allowStringValue ? 'text' : 'number',
264
273
  inputMode: inputMode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-number-input",
3
- "version": "11.7.4-snapshot-121",
3
+ "version": "11.7.4-snapshot-125",
4
4
  "description": "A UI component library made by Instructure Inc.",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -16,23 +16,23 @@
16
16
  "dependencies": {
17
17
  "@babel/runtime": "^7.29.7",
18
18
  "keycode": "^2",
19
- "@instructure/emotion": "11.7.4-snapshot-121",
20
- "@instructure/shared-types": "11.7.4-snapshot-121",
21
- "@instructure/ui-react-utils": "11.7.4-snapshot-121",
22
- "@instructure/ui-icons": "11.7.4-snapshot-121",
23
- "@instructure/ui-form-field": "11.7.4-snapshot-121",
24
- "@instructure/ui-themes": "11.7.4-snapshot-121",
25
- "@instructure/ui-utils": "11.7.4-snapshot-121",
26
- "@instructure/ui-a11y-utils": "11.7.4-snapshot-121",
27
- "@instructure/uid": "11.7.4-snapshot-121"
19
+ "@instructure/emotion": "11.7.4-snapshot-125",
20
+ "@instructure/shared-types": "11.7.4-snapshot-125",
21
+ "@instructure/ui-a11y-utils": "11.7.4-snapshot-125",
22
+ "@instructure/ui-form-field": "11.7.4-snapshot-125",
23
+ "@instructure/ui-icons": "11.7.4-snapshot-125",
24
+ "@instructure/ui-react-utils": "11.7.4-snapshot-125",
25
+ "@instructure/ui-themes": "11.7.4-snapshot-125",
26
+ "@instructure/ui-utils": "11.7.4-snapshot-125",
27
+ "@instructure/uid": "11.7.4-snapshot-125"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@testing-library/jest-dom": "^6.9.1",
31
31
  "@testing-library/react": "16.3.2",
32
32
  "@testing-library/user-event": "^14.6.1",
33
33
  "vitest": "^4.1.9",
34
- "@instructure/ui-babel-preset": "11.7.4-snapshot-121",
35
- "@instructure/ui-scripts": "11.7.4-snapshot-121"
34
+ "@instructure/ui-scripts": "11.7.4-snapshot-125",
35
+ "@instructure/ui-babel-preset": "11.7.4-snapshot-125"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "react": ">=18 <=19"
@@ -120,6 +120,10 @@ const NumberInput = forwardRef<NumberInputHandle, NumberInputProps>(
120
120
  const success =
121
121
  !!messages && messages.some((message) => message.type === 'success')
122
122
 
123
+ const hasMessages = !!messages?.some((m) => !!m.text)
124
+ const messagesId = id ? `${id}-messages` : undefined
125
+ const labelId = id ? `${id}-label` : undefined
126
+
123
127
  const interaction = getInteraction({ props })
124
128
  if (
125
129
  interaction === 'disabled' &&
@@ -320,7 +324,7 @@ const NumberInput = forwardRef<NumberInputHandle, NumberInputProps>(
320
324
 
321
325
  const label = callRenderProp(renderLabel)
322
326
 
323
- const passedProps = passthroughProps(rest)
327
+ const passedProps = passthroughProps(rest) as Record<string, any>
324
328
 
325
329
  // Don't render until we have an ID
326
330
  if (!id) {
@@ -331,6 +335,8 @@ const NumberInput = forwardRef<NumberInputHandle, NumberInputProps>(
331
335
  <FormField
332
336
  {...pickProps(props, FormField.allowedProps)}
333
337
  label={label}
338
+ messagesId={messagesId}
339
+ labelId={labelId}
334
340
  inline={display === 'inline-block'}
335
341
  id={id}
336
342
  elementRef={handleRef}
@@ -346,6 +352,20 @@ const NumberInput = forwardRef<NumberInputHandle, NumberInputProps>(
346
352
  {...passedProps}
347
353
  css={styles?.input}
348
354
  aria-invalid={invalid ? 'true' : undefined}
355
+ // Keep messages in the description so the accessible name contains only the label.
356
+ aria-describedby={
357
+ [
358
+ passedProps['aria-describedby'],
359
+ hasMessages ? messagesId : null
360
+ ]
361
+ .filter(Boolean)
362
+ .join(' ') || undefined
363
+ }
364
+ aria-labelledby={
365
+ hasMessages
366
+ ? passedProps['aria-labelledby'] || labelId
367
+ : passedProps['aria-labelledby']
368
+ }
349
369
  id={id}
350
370
  type={allowStringValue ? 'text' : 'number'}
351
371
  inputMode={inputMode}