@instructure/ui-text-input 11.7.4-snapshot-121 → 11.7.4-snapshot-126
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 +3 -1
- package/es/TextInput/v2/index.js +12 -1
- package/lib/TextInput/v2/index.js +12 -1
- package/package.json +13 -13
- package/src/TextInput/v2/index.tsx +14 -1
- package/src/TextInput/v2/props.ts +3 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/TextInput/v2/index.d.ts +1 -0
- package/types/TextInput/v2/index.d.ts.map +1 -1
- package/types/TextInput/v2/props.d.ts +3 -1
- package/types/TextInput/v2/props.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,11 +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-
|
|
6
|
+
## [11.7.4-snapshot-126](https://github.com/instructure/instructure-ui/compare/v11.7.3...v11.7.4-snapshot-126) (2026-07-22)
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
### Bug Fixes
|
|
10
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))
|
|
11
13
|
* **ui-text-input:** restore inline cursor flow next to selected tags ([3dd1736](https://github.com/instructure/instructure-ui/commit/3dd1736173ff089970bbbd175bda81faa02895f7))
|
|
12
14
|
|
|
13
15
|
|
package/es/TextInput/v2/index.js
CHANGED
|
@@ -56,11 +56,13 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyl
|
|
|
56
56
|
super(props);
|
|
57
57
|
this._defaultId = props.deterministicId();
|
|
58
58
|
this._messagesId = props.deterministicId('TextInput-messages');
|
|
59
|
+
this._labelId = props.deterministicId('TextInput-label');
|
|
59
60
|
}
|
|
60
61
|
ref = null;
|
|
61
62
|
_input = null;
|
|
62
63
|
_defaultId;
|
|
63
64
|
_messagesId;
|
|
65
|
+
_labelId;
|
|
64
66
|
_focusListener = null;
|
|
65
67
|
handleRef = el => {
|
|
66
68
|
const {
|
|
@@ -123,7 +125,7 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyl
|
|
|
123
125
|
});
|
|
124
126
|
}
|
|
125
127
|
get hasMessages() {
|
|
126
|
-
return !!this.props.messages
|
|
128
|
+
return !!this.props.messages?.some(m => !!m.text);
|
|
127
129
|
}
|
|
128
130
|
get invalid() {
|
|
129
131
|
return !!this.props.messages && this.props.messages.findIndex(message => {
|
|
@@ -182,6 +184,13 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyl
|
|
|
182
184
|
if (props['aria-describedby']) {
|
|
183
185
|
descriptionIds = `${props['aria-describedby']}`;
|
|
184
186
|
}
|
|
187
|
+
// Keep messages in the description, not the accessible name.
|
|
188
|
+
// A consumer-provided aria-labelledby wins.
|
|
189
|
+
let labelledById = props['aria-labelledby'];
|
|
190
|
+
if (this.hasMessages) {
|
|
191
|
+
descriptionIds = [descriptionIds, this._messagesId].filter(Boolean).join(' ');
|
|
192
|
+
labelledById = labelledById || this._labelId;
|
|
193
|
+
}
|
|
185
194
|
return _jsx("input", {
|
|
186
195
|
...props,
|
|
187
196
|
css: this.props.styles?.textInput,
|
|
@@ -196,6 +205,7 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyl
|
|
|
196
205
|
disabled: interaction === 'disabled',
|
|
197
206
|
readOnly: interaction === 'readonly',
|
|
198
207
|
"aria-describedby": descriptionIds !== '' ? descriptionIds : undefined,
|
|
208
|
+
"aria-labelledby": labelledById,
|
|
199
209
|
size: htmlSize,
|
|
200
210
|
onChange: this.handleChange,
|
|
201
211
|
onBlur: this.handleBlur
|
|
@@ -221,6 +231,7 @@ let TextInput = (_dec = withDeterministicId(), _dec2 = withStyleNew(generateStyl
|
|
|
221
231
|
id: this.id,
|
|
222
232
|
label: label,
|
|
223
233
|
messagesId: this._messagesId,
|
|
234
|
+
labelId: this._labelId,
|
|
224
235
|
messages: messages,
|
|
225
236
|
inline: display === 'inline-block',
|
|
226
237
|
width: width,
|
|
@@ -67,11 +67,13 @@ let TextInput = exports.TextInput = (_dec = (0, _withDeterministicId.withDetermi
|
|
|
67
67
|
super(props);
|
|
68
68
|
this._defaultId = props.deterministicId();
|
|
69
69
|
this._messagesId = props.deterministicId('TextInput-messages');
|
|
70
|
+
this._labelId = props.deterministicId('TextInput-label');
|
|
70
71
|
}
|
|
71
72
|
ref = null;
|
|
72
73
|
_input = null;
|
|
73
74
|
_defaultId;
|
|
74
75
|
_messagesId;
|
|
76
|
+
_labelId;
|
|
75
77
|
_focusListener = null;
|
|
76
78
|
handleRef = el => {
|
|
77
79
|
const {
|
|
@@ -134,7 +136,7 @@ let TextInput = exports.TextInput = (_dec = (0, _withDeterministicId.withDetermi
|
|
|
134
136
|
});
|
|
135
137
|
}
|
|
136
138
|
get hasMessages() {
|
|
137
|
-
return !!this.props.messages
|
|
139
|
+
return !!this.props.messages?.some(m => !!m.text);
|
|
138
140
|
}
|
|
139
141
|
get invalid() {
|
|
140
142
|
return !!this.props.messages && this.props.messages.findIndex(message => {
|
|
@@ -193,6 +195,13 @@ let TextInput = exports.TextInput = (_dec = (0, _withDeterministicId.withDetermi
|
|
|
193
195
|
if (props['aria-describedby']) {
|
|
194
196
|
descriptionIds = `${props['aria-describedby']}`;
|
|
195
197
|
}
|
|
198
|
+
// Keep messages in the description, not the accessible name.
|
|
199
|
+
// A consumer-provided aria-labelledby wins.
|
|
200
|
+
let labelledById = props['aria-labelledby'];
|
|
201
|
+
if (this.hasMessages) {
|
|
202
|
+
descriptionIds = [descriptionIds, this._messagesId].filter(Boolean).join(' ');
|
|
203
|
+
labelledById = labelledById || this._labelId;
|
|
204
|
+
}
|
|
196
205
|
return (0, _jsxRuntime.jsx)("input", {
|
|
197
206
|
...props,
|
|
198
207
|
css: this.props.styles?.textInput,
|
|
@@ -207,6 +216,7 @@ let TextInput = exports.TextInput = (_dec = (0, _withDeterministicId.withDetermi
|
|
|
207
216
|
disabled: interaction === 'disabled',
|
|
208
217
|
readOnly: interaction === 'readonly',
|
|
209
218
|
"aria-describedby": descriptionIds !== '' ? descriptionIds : undefined,
|
|
219
|
+
"aria-labelledby": labelledById,
|
|
210
220
|
size: htmlSize,
|
|
211
221
|
onChange: this.handleChange,
|
|
212
222
|
onBlur: this.handleBlur
|
|
@@ -232,6 +242,7 @@ let TextInput = exports.TextInput = (_dec = (0, _withDeterministicId.withDetermi
|
|
|
232
242
|
id: this.id,
|
|
233
243
|
label: label,
|
|
234
244
|
messagesId: this._messagesId,
|
|
245
|
+
labelId: this._labelId,
|
|
235
246
|
messages: messages,
|
|
236
247
|
inline: display === 'inline-block',
|
|
237
248
|
width: width,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instructure/ui-text-input",
|
|
3
|
-
"version": "11.7.4-snapshot-
|
|
3
|
+
"version": "11.7.4-snapshot-126",
|
|
4
4
|
"description": "A styled HTML text input component.",
|
|
5
5
|
"author": "Instructure, Inc. Engineering and Product Design",
|
|
6
6
|
"module": "./es/index.js",
|
|
@@ -18,21 +18,21 @@
|
|
|
18
18
|
"@testing-library/react": "16.3.2",
|
|
19
19
|
"@testing-library/user-event": "^14.6.1",
|
|
20
20
|
"vitest": "^4.1.9",
|
|
21
|
-
"@instructure/ui-axe-check": "11.7.4-snapshot-
|
|
22
|
-
"@instructure/ui-babel-preset": "11.7.4-snapshot-
|
|
23
|
-
"@instructure/ui-
|
|
24
|
-
"@instructure/ui-
|
|
21
|
+
"@instructure/ui-axe-check": "11.7.4-snapshot-126",
|
|
22
|
+
"@instructure/ui-babel-preset": "11.7.4-snapshot-126",
|
|
23
|
+
"@instructure/ui-badge": "11.7.4-snapshot-126",
|
|
24
|
+
"@instructure/ui-color-utils": "11.7.4-snapshot-126"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@babel/runtime": "^7.29.7",
|
|
28
|
-
"@instructure/shared-types": "11.7.4-snapshot-
|
|
29
|
-
"@instructure/emotion": "11.7.4-snapshot-
|
|
30
|
-
"@instructure/ui-
|
|
31
|
-
"@instructure/ui-
|
|
32
|
-
"@instructure/ui-dom-utils": "11.7.4-snapshot-
|
|
33
|
-
"@instructure/ui-react-utils": "11.7.4-snapshot-
|
|
34
|
-
"@instructure/ui-
|
|
35
|
-
"@instructure/ui-
|
|
28
|
+
"@instructure/shared-types": "11.7.4-snapshot-126",
|
|
29
|
+
"@instructure/emotion": "11.7.4-snapshot-126",
|
|
30
|
+
"@instructure/ui-form-field": "11.7.4-snapshot-126",
|
|
31
|
+
"@instructure/ui-a11y-utils": "11.7.4-snapshot-126",
|
|
32
|
+
"@instructure/ui-dom-utils": "11.7.4-snapshot-126",
|
|
33
|
+
"@instructure/ui-react-utils": "11.7.4-snapshot-126",
|
|
34
|
+
"@instructure/ui-tag": "11.7.4-snapshot-126",
|
|
35
|
+
"@instructure/ui-themes": "11.7.4-snapshot-126"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": ">=18 <=19"
|
|
@@ -70,6 +70,7 @@ class TextInput extends Component<TextInputProps> {
|
|
|
70
70
|
super(props)
|
|
71
71
|
this._defaultId = props.deterministicId!()
|
|
72
72
|
this._messagesId = props.deterministicId!('TextInput-messages')
|
|
73
|
+
this._labelId = props.deterministicId!('TextInput-label')
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
ref: Element | null = null
|
|
@@ -78,6 +79,7 @@ class TextInput extends Component<TextInputProps> {
|
|
|
78
79
|
|
|
79
80
|
private readonly _defaultId: string
|
|
80
81
|
private readonly _messagesId: string
|
|
82
|
+
private readonly _labelId: string
|
|
81
83
|
|
|
82
84
|
private _focusListener: { remove(): void } | null = null
|
|
83
85
|
|
|
@@ -158,7 +160,7 @@ class TextInput extends Component<TextInputProps> {
|
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
get hasMessages() {
|
|
161
|
-
return !!this.props.messages
|
|
163
|
+
return !!this.props.messages?.some((m) => !!m.text)
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
get invalid() {
|
|
@@ -231,6 +233,15 @@ class TextInput extends Component<TextInputProps> {
|
|
|
231
233
|
if (props['aria-describedby']) {
|
|
232
234
|
descriptionIds = `${props['aria-describedby']}`
|
|
233
235
|
}
|
|
236
|
+
// Keep messages in the description, not the accessible name.
|
|
237
|
+
// A consumer-provided aria-labelledby wins.
|
|
238
|
+
let labelledById = props['aria-labelledby'] as string | undefined
|
|
239
|
+
if (this.hasMessages) {
|
|
240
|
+
descriptionIds = [descriptionIds, this._messagesId]
|
|
241
|
+
.filter(Boolean)
|
|
242
|
+
.join(' ')
|
|
243
|
+
labelledById = labelledById || this._labelId
|
|
244
|
+
}
|
|
234
245
|
|
|
235
246
|
return (
|
|
236
247
|
<input
|
|
@@ -247,6 +258,7 @@ class TextInput extends Component<TextInputProps> {
|
|
|
247
258
|
disabled={interaction === 'disabled'}
|
|
248
259
|
readOnly={interaction === 'readonly'}
|
|
249
260
|
aria-describedby={descriptionIds !== '' ? descriptionIds : undefined}
|
|
261
|
+
aria-labelledby={labelledById}
|
|
250
262
|
size={htmlSize}
|
|
251
263
|
onChange={this.handleChange}
|
|
252
264
|
onBlur={this.handleBlur}
|
|
@@ -283,6 +295,7 @@ class TextInput extends Component<TextInputProps> {
|
|
|
283
295
|
id={this.id}
|
|
284
296
|
label={label}
|
|
285
297
|
messagesId={this._messagesId}
|
|
298
|
+
labelId={this._labelId}
|
|
286
299
|
messages={messages}
|
|
287
300
|
inline={display === 'inline-block'}
|
|
288
301
|
width={width}
|
|
@@ -174,7 +174,9 @@ type TextInputOwnProps = {
|
|
|
174
174
|
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
|
-
*
|
|
177
|
+
* Valid values are `0`, `none`, `auto`, and Spacing token values,
|
|
178
|
+
* see https://instructure.design/layout-spacing. Apply these values via
|
|
179
|
+
* familiar CSS-like shorthand. For example, `margin="general.spaceMd auto"`.
|
|
178
180
|
*/
|
|
179
181
|
margin?: Spacing
|
|
180
182
|
}
|