-
Notifications
You must be signed in to change notification settings - Fork 363
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
added: [M3-6989] - aria-describedby
to TextField with helper text
#11351
Changes from all commits
b012453
addbae4
3ab45e5
6d9cb2a
8437f9c
b317a03
fd53887
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,5 @@ | ||
--- | ||
"@linode/manager": Added | ||
--- | ||
|
||
aria-describedby to TextField with helper text ([#11351](https://github.com/linode/manager/pull/11351)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,7 +113,8 @@ interface InputToolTipProps { | |
tooltipWidth?: number; | ||
} | ||
|
||
interface TextFieldPropsOverrides extends StandardTextFieldProps { | ||
interface TextFieldPropsOverrides | ||
extends Omit<StandardTextFieldProps, 'label'> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This helps TS in general not having to compare overridden types. While in this case this is just a string and this likely has no impact, it's just good practice. |
||
// We override this prop to make it required | ||
label: string; | ||
} | ||
|
@@ -166,6 +167,7 @@ export const TextField = (props: TextFieldProps) => { | |
|
||
const [_value, setValue] = React.useState<Value>(value); | ||
const theme = useTheme(); | ||
const fallbackId = React.useId(); | ||
|
||
React.useEffect(() => { | ||
setValue(value); | ||
|
@@ -249,7 +251,14 @@ export const TextField = (props: TextFieldProps) => { | |
} | ||
|
||
const validInputId = | ||
inputId || (label ? convertToKebabCase(`${label}`) : undefined); | ||
inputId || | ||
(label | ||
? convertToKebabCase(label) | ||
: // label could still be an empty string | ||
fallbackId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. always making sure we have an ID |
||
|
||
const helperTextId = `${validInputId}-helper-text`; | ||
const errorTextId = `${validInputId}-error-text`; | ||
|
||
const labelSuffixText = required | ||
? '(required)' | ||
|
@@ -317,6 +326,7 @@ export const TextField = (props: TextFieldProps) => { | |
marginTop: theme.spacing(), | ||
}} | ||
data-qa-textfield-helper-text | ||
id={helperTextId} | ||
> | ||
{helperText} | ||
</FormHelperText> | ||
|
@@ -364,6 +374,9 @@ export const TextField = (props: TextFieldProps) => { | |
...SelectProps, | ||
}} | ||
inputProps={{ | ||
'aria-describedby': helperText ? helperTextId : undefined, | ||
'aria-errormessage': errorText ? errorTextId : undefined, | ||
'aria-invalid': !!error || !!errorText, | ||
'data-testid': 'textfield-input', | ||
id: validInputId, | ||
...inputProps, | ||
|
@@ -437,7 +450,7 @@ export const TextField = (props: TextFieldProps) => { | |
</FormHelperText> | ||
)} | ||
{helperText && helperTextPosition === 'bottom' && ( | ||
<FormHelperText data-qa-textfield-helper-text> | ||
<FormHelperText data-qa-textfield-helper-text id={helperTextId}> | ||
{helperText} | ||
</FormHelperText> | ||
)} | ||
|
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 should make the same change when displaying error messages. VoiceOver currently isn't able to pick them up:
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.
@hkhalil-akamai That's fair, this one has a
role="alert"
attribute which is very much meant for this type of behavior (aka, a validation error injected into the DOM) but could indeed use more context.see commit 95a8d3e which follows this recommended pattern