diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd947f1c8e4..91f5d6dee85 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,12 +6,17 @@
- Converted `EuiFilterButton` to TypeScript ([#2761](https://github.com/elastic/eui/pull/2761))
- Converted `EuiFilterSelectItem` to TypeScript ([#2761](https://github.com/elastic/eui/pull/2761))
- Converted `EuiFieldSearch` to TypeScript ([#2775](https://github.com/elastic/eui/pull/2775))
+- Improved `EuiDescribedFormGroup` accessibility by avoiding duplicated output in screen readers ([#2783](https://github.com/elastic/eui/pull/2783))
- Added `data-test-subj` to the `EuiContextMenuItem` in `EuiTablePagination` ([#2778](https://github.com/elastic/eui/pull/2778))
**Bug fixes**
- Increased column width on `EuiTableHeaderCellCheckbox` to prevent `EuiCheckbox`'s focus ring from getting clipped in `EuiBasicTable` ([#2770](https://github.com/elastic/eui/pull/2770))
+**Breaking changes**
+
+- Removed `idAria` prop from `EuiDescribedFormGroup` ([#2783](https://github.com/elastic/eui/pull/2783))
+
**Deprecations**
- `EuiIcon`'s `logoEnterpriseSearch` type deprecated in favor of `logoWorkplaceSearch`
diff --git a/src-docs/src/views/form_layouts/described_form_group.js b/src-docs/src/views/form_layouts/described_form_group.js
index 58c3abe07d1..aa77d9b9dee 100644
--- a/src-docs/src/views/form_layouts/described_form_group.js
+++ b/src-docs/src/views/form_layouts/described_form_group.js
@@ -10,6 +10,7 @@ import {
EuiRange,
EuiSelect,
EuiSwitch,
+ EuiLink,
} from '../../../../src/components';
import makeId from '../../../../src/components/form/form_row/make_id';
@@ -86,45 +87,34 @@ export default class extends Component {
return (
Single text field}
description={
- When using this with a single form row where this text serves as
- the help text for the input, it is a good idea to pass{' '}
- idAria="someID" to the form group and
- pass
- describedByIds={[someID]} to its form
- row.
+ A single text field that can be used to display additional text.
+ It can have{' '}
+
+ links
+ {' '}
+ or any other type of content.
}>
-
-
+
+
- No description}>
-
+ No description}>
+ Multiple fields}
- titleSize="m"
+ title={
Multiple fields
}
description="Here are three form rows. The first form row does not have a title.">
- We do not pass describedByIds when there are
- multiple form rows.
-
- }>
+ helpText={This is a help text}>
Use EuiDescribedFormGroup component to associate
multiple EuiFormRows. It can also simply be used
- with one EuiFormRow as a way to display help text
- (or additional text) next to the field instead of below (on mobile,
- will revert to being stacked).
+ with one EuiFormRow as a way to display additional
+ text next to the field (on mobile, it will revert to being stacked).
+
+
+
+
`;
exports[`EuiDescribedFormGroup ties together parts for accessibility 1`] = `
@@ -244,7 +557,6 @@ exports[`EuiDescribedFormGroup ties together parts for accessibility 1`] = `
description="Test description"
fullWidth={false}
gutterSize="l"
- idAria="test-id"
title={
Title
@@ -252,164 +564,168 @@ exports[`EuiDescribedFormGroup ties together parts for accessibility 1`] = `
}
titleSize="xs"
>
-
-
+
-
+
+ Help text
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
`;
diff --git a/src/components/form/described_form_group/described_form_group.js b/src/components/form/described_form_group/described_form_group.js
index 6b130e57c35..3f9d2df5836 100644
--- a/src/components/form/described_form_group/described_form_group.js
+++ b/src/components/form/described_form_group/described_form_group.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
@@ -7,7 +7,8 @@ import { EuiText } from '../../text/text';
import { EuiFlexGroup, EuiFlexItem } from '../../flex';
import { GUTTER_SIZES } from '../../flex/flex_group';
-import makeId from '../form_row/make_id';
+import { EuiScreenReaderOnly } from '../../accessibility';
+import { EuiInnerText } from '../../inner_text';
const paddingSizeToClassNameMap = {
xxxs: 'euiDescribedFormGroup__fieldPadding--xxxsmall',
@@ -18,12 +19,7 @@ const paddingSizeToClassNameMap = {
l: 'euiDescribedFormGroup__fieldPadding--large',
};
-export class EuiDescribedFormGroup extends Component {
- constructor(props) {
- super(props);
- this.ariaId = props.idAria || makeId();
- }
-
+export class EuiDescribedFormGroup extends PureComponent {
render() {
const {
children,
@@ -33,12 +29,9 @@ export class EuiDescribedFormGroup extends Component {
titleSize,
title,
description,
- idAria: userAriaId,
...rest
} = this.props;
- const ariaId = this.ariaId;
-
const classes = classNames(
'euiDescribedFormGroup',
{
@@ -52,45 +45,46 @@ export class EuiDescribedFormGroup extends Component {
paddingSizeToClassNameMap[titleSize]
);
- const ariaProps = {
- 'aria-labelledby': `${ariaId}-title`,
- };
-
let renderedDescription;
if (description) {
renderedDescription = (
{description}
);
-
- // If user has defined an aria ID, assume they have passed the ID to
- // the form row describedByIds and skip describedby here.
- ariaProps['aria-describedby'] = userAriaId ? null : ariaId;
}
return (
-