Input Field: Fix accessibility issues with errors not associated to proper form fields (#30430)

* Cursor first pass

* Iterating

* Updated snapshots

* Alert role only for error or warning

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Maria A Nunez
2025-04-03 15:08:36 -04:00
коммит произвёл GitHub
родитель a4c745c97b
Коммит e4124ed320
4 изменённых файлов: 29 добавлений и 5 удалений

Просмотреть файл

@@ -76,6 +76,7 @@ Object {
class="Input_wrapper"
>
<input
aria-invalid="false"
aria-label="Name"
class="Input form-control large"
id="input_name"
@@ -102,6 +103,8 @@ Object {
class="Input_wrapper"
>
<input
aria-describedby="error_email"
aria-invalid="true"
aria-label="Business Email"
class="Input form-control large Input__focus"
id="input_email"
@@ -114,8 +117,11 @@ Object {
</fieldset>
<div
class="Input___customMessage Input___error"
id="error_email"
role="alert"
>
<i
aria-hidden="true"
class="icon error icon-alert-circle-outline"
/>
<span>
@@ -136,6 +142,7 @@ Object {
class="Input_wrapper"
>
<input
aria-invalid="false"
aria-label="Company Name"
class="Input form-control large"
id="input_company_name"

Просмотреть файл

@@ -14,6 +14,7 @@ exports[`components/widgets/inputs/Input should match snapshot 1`] = `
className="Input_wrapper"
>
<input
aria-invalid={false}
className="Input form-control medium"
id="input_"
onBlur={[Function]}

Просмотреть файл

@@ -80,6 +80,9 @@ const Input = React.forwardRef((
const [focused, setFocused] = useState(false);
const [customInputLabel, setCustomInputLabel] = useState<CustomMessageInputType>(null);
const errorId = `error_${name || ''}`;
const inputId = `input_${name || ''}`;
useEffect(() => {
if (customMessage === undefined || customMessage === null) {
if (customInputLabel !== null) {
@@ -136,7 +139,8 @@ const Input = React.forwardRef((
};
const showLegend = Boolean(focused || value);
const error = customInputLabel?.type === 'error';
const error = customInputLabel?.type === ItemStatus.ERROR;
const warning = customInputLabel?.type === ItemStatus.WARNING;
const limitExceeded = limit && value && !Array.isArray(value) ? value.toString().length - limit : 0;
const clearButton = value && clearable ? (
@@ -161,11 +165,13 @@ const Input = React.forwardRef((
return (
<textarea
ref={ref as React.RefObject<HTMLTextAreaElement>}
id={`input_${name || ''}`}
id={inputId}
className={classNames('Input form-control', inputSize, inputClassName, {Input__focus: showLegend})}
value={value}
placeholder={placeholderValue}
aria-label={ariaLabel}
aria-describedby={error ? errorId : undefined}
aria-invalid={error || hasError || limitExceeded > 0}
rows={3}
name={name}
disabled={disabled}
@@ -179,11 +185,13 @@ const Input = React.forwardRef((
return (
<input
ref={ref as React.RefObject<HTMLInputElement>}
id={`input_${name || ''}`}
id={inputId}
className={classNames('Input form-control', inputSize, inputClassName, {Input__focus: showLegend})}
value={value}
placeholder={placeholderValue}
aria-label={ariaLabel}
aria-describedby={error ? errorId : undefined}
aria-invalid={error || hasError || limitExceeded > 0}
name={name}
disabled={disabled}
{...otherProps}
@@ -223,7 +231,11 @@ const Input = React.forwardRef((
{addon}
</fieldset>
{customInputLabel && (
<div className={`Input___customMessage Input___${customInputLabel.type}`}>
<div
id={errorId}
className={`Input___customMessage Input___${customInputLabel.type}`}
role={error || warning ? 'alert' : undefined}
>
{customInputLabel.type && (
<i
className={classNames(`icon ${customInputLabel.type}`, {
@@ -232,6 +244,7 @@ const Input = React.forwardRef((
'icon-information-outline': customInputLabel.type === ItemStatus.INFO,
'icon-check': customInputLabel.type === ItemStatus.SUCCESS,
})}
aria-hidden='true'
/>)}
<span>{customInputLabel.value}</span>
</div>

Просмотреть файл

@@ -71,7 +71,10 @@ const PasswordInput = React.forwardRef((
onClick={toggleShowPassword}
disabled={disabled}
>
<i className={showPassword && !disabled ? 'icon-eye-off-outline' : 'icon-eye-outline'}/>
<i
className={showPassword && !disabled ? 'icon-eye-off-outline' : 'icon-eye-outline'}
aria-hidden='true'
/>
</button>
}
value={value}