diff --git a/docs/src/views/accordion/accordion.js b/docs/src/views/accordion/accordion.js index ac95bd05219..d2e89a81f4f 100644 --- a/docs/src/views/accordion/accordion.js +++ b/docs/src/views/accordion/accordion.js @@ -11,6 +11,7 @@ import { export default () => (
@@ -21,6 +22,7 @@ export default () => ( diff --git a/docs/src/views/accordion/accordion_extra.js b/docs/src/views/accordion/accordion_extra.js index d2b59d65a32..a881689432a 100644 --- a/docs/src/views/accordion/accordion_extra.js +++ b/docs/src/views/accordion/accordion_extra.js @@ -7,6 +7,7 @@ import { export default () => ( Extra action!} > diff --git a/docs/src/views/accordion/accordion_form.js b/docs/src/views/accordion/accordion_form.js index 35c164cedc4..21f26873ba0 100644 --- a/docs/src/views/accordion/accordion_form.js +++ b/docs/src/views/accordion/accordion_form.js @@ -29,13 +29,16 @@ const repeatableForm = ( + + + @@ -48,12 +51,14 @@ const buttonContent = ( +
Webhook
+

@@ -65,7 +70,12 @@ const buttonContent = ( ); const extraAction = ( - + ); export default () => ( @@ -73,8 +83,11 @@ export default () => (

I am a complicated, highly styled, repeatable form!

+ + ( {repeatableForm}
+ ( color="ghost" iconType="user" onClick={() => window.alert('Button clicked')} + aria-label="Your account" /> ); diff --git a/docs/src/views/button/button_icon.js b/docs/src/views/button/button_icon.js index f6e1f9d52b2..4fe827dfdc9 100644 --- a/docs/src/views/button/button_icon.js +++ b/docs/src/views/button/button_icon.js @@ -9,6 +9,7 @@ export default () => ( window.alert('Button clicked')} iconType="arrowRight" + aria-label="Next" /> ( color="danger" onClick={() => window.alert('Button clicked')} iconType="arrowRight" + aria-label="Next" /> ( color="disabled" onClick={() => window.alert('Button clicked')} iconType="arrowRight" + aria-label="Next" /> ); diff --git a/docs/src/views/context_menu/context_menu.js b/docs/src/views/context_menu/context_menu.js index 85617e754b0..d2601f04065 100644 --- a/docs/src/views/context_menu/context_menu.js +++ b/docs/src/views/context_menu/context_menu.js @@ -135,6 +135,7 @@ export default class extends Component { return ( ( code: formControlsHtml, }]} text={ -

- These are the base inputs without their labels. If you need labels - then use the FormRow wrapper as explained - in the next example. -

+
+

+ These are the base inputs without their labels. If you need labels + then use the FormRow wrapper as explained + in the next example. +

+

+ Never forget to label every input element. You can either + use a label element with a for attribute + referencing the id of the input field, wrap the input field + within the label element or use aria-label or aria-labelledby. +

+
} demo={ diff --git a/docs/src/views/form/form_popover.js b/docs/src/views/form/form_popover.js index 159cef98122..6ef8c6718d7 100644 --- a/docs/src/views/form/form_popover.js +++ b/docs/src/views/form/form_popover.js @@ -92,6 +92,7 @@ export default class extends Component { return (
@@ -189,8 +190,10 @@ export default class extends Component { Popover content + @@ -204,8 +207,10 @@ export default class extends Component { Popover content + @@ -226,6 +231,7 @@ export default class extends Component { @@ -239,8 +245,10 @@ export default class extends Component { Popover content + @@ -254,8 +262,10 @@ export default class extends Component { Popover content + @@ -276,6 +286,7 @@ export default class extends Component { @@ -294,8 +305,10 @@ export default class extends Component { + @@ -309,8 +322,10 @@ export default class extends Component { Popover content + @@ -336,6 +351,7 @@ export default class extends Component { @@ -354,8 +370,10 @@ export default class extends Component { + @@ -369,8 +387,10 @@ export default class extends Component { Popover content + diff --git a/docs/src/views/popover/popover_panel_class_name.js b/docs/src/views/popover/popover_panel_class_name.js index 48d6fbfccee..e44199f44d9 100644 --- a/docs/src/views/popover/popover_panel_class_name.js +++ b/docs/src/views/popover/popover_panel_class_name.js @@ -31,6 +31,7 @@ export default class extends Component { render() { return ( diff --git a/docs/src/views/popover/popover_with_title.js b/docs/src/views/popover/popover_with_title.js index 5281abf8377..de56d92fc1e 100644 --- a/docs/src/views/popover/popover_with_title.js +++ b/docs/src/views/popover/popover_with_title.js @@ -61,6 +61,7 @@ export default class extends Component { @@ -83,8 +84,10 @@ export default class extends Component {
+ @@ -107,8 +110,10 @@ export default class extends Component { + diff --git a/docs/src/views/popover/trap_focus.js b/docs/src/views/popover/trap_focus.js index f386f600eef..bb8846c650b 100644 --- a/docs/src/views/popover/trap_focus.js +++ b/docs/src/views/popover/trap_focus.js @@ -43,6 +43,7 @@ export default class extends Component { return ( + @@ -66,7 +68,8 @@ export default class extends Component { label="Current time range" /> - Copy iFrame code + + Copy IFRAME code ); } diff --git a/src/components/accordion/__snapshots__/accordion.test.js.snap b/src/components/accordion/__snapshots__/accordion.test.js.snap index 76c1d02085d..7b514d97118 100644 --- a/src/components/accordion/__snapshots__/accordion.test.js.snap +++ b/src/components/accordion/__snapshots__/accordion.test.js.snap @@ -12,10 +12,10 @@ exports[`EuiAccordion is rendered 1`] = `
- +
diff --git a/src/components/accordion/accordion.js b/src/components/accordion/accordion.js index 9f5346c3a4b..3f8152339f3 100644 --- a/src/components/accordion/accordion.js +++ b/src/components/accordion/accordion.js @@ -5,7 +5,6 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { - EuiKeyboardAccessible, EuiIcon, EuiFlexGroup, EuiFlexItem, @@ -46,6 +45,7 @@ export class EuiAccordion extends Component { children, buttonContent, className, + id, buttonClassName, buttonContentClassName, extraAction, @@ -91,23 +91,32 @@ export class EuiAccordion extends Component { > - -
- - - {icon} - - - {buttonContent} - - -
-
+
+ {optionalAction}
-
{ this.childWrapper = node; }}> +
{ this.childWrapper = node; }} + id={id} + >
{ this.childContent = node; }}> {children}
@@ -119,6 +128,7 @@ export class EuiAccordion extends Component { EuiAccordion.propTypes = { children: PropTypes.node, + id: PropTypes.string.isRequired, className: PropTypes.string, buttonContentClassName: PropTypes.string, buttonContent: PropTypes.node, diff --git a/src/components/accordion/accordion.test.js b/src/components/accordion/accordion.test.js index 773794bd615..fbb3b54fa3c 100644 --- a/src/components/accordion/accordion.test.js +++ b/src/components/accordion/accordion.test.js @@ -4,10 +4,16 @@ import { requiredProps } from '../../test/required_props'; import { EuiAccordion } from './accordion'; +let id = 0; +const getId = () => (`${id++}`); + describe('EuiAccordion', () => { test('is rendered', () => { const component = render( - + ); expect(component) diff --git a/src/components/button/button_icon/button_icon.js b/src/components/button/button_icon/button_icon.js index 2719ce10c02..98281bb69d6 100644 --- a/src/components/button/button_icon/button_icon.js +++ b/src/components/button/button_icon/button_icon.js @@ -7,6 +7,21 @@ import { EuiIcon, } from '../../icon'; +const accessibleButtonIcon = (props, propName, componentName) => { + if (props['aria-label']) { + return; + } + + if (props['aria-labelledby']) { + return; + } + + throw new Error( + `${componentName} requires aria-label or aria-labelledby to be specified because icon-only + buttons are screen-reader-inaccessible without them.` + ); +}; + const colorToClassNameMap = { primary: 'euiButtonIcon--primary', danger: 'euiButtonIcon--danger', @@ -61,6 +76,7 @@ EuiButtonIcon.propTypes = { iconType: PropTypes.oneOf(ICON_TYPES), color: PropTypes.oneOf(COLORS), isDisabled: PropTypes.bool, + 'aria-label': accessibleButtonIcon, }; EuiButtonIcon.defaultProps = { diff --git a/src/components/button/button_icon/button_icon.test.js b/src/components/button/button_icon/button_icon.test.js index d4cd8ac0a16..ed4c815cb8c 100644 --- a/src/components/button/button_icon/button_icon.test.js +++ b/src/components/button/button_icon/button_icon.test.js @@ -7,7 +7,7 @@ import { EuiButtonIcon } from './button_icon'; describe('EuiButtonIcon', () => { test('is rendered', () => { const component = render( - + ); expect(component) diff --git a/src/components/description_list/description_list.js b/src/components/description_list/description_list.js index b355e663a7f..03f9b34eb07 100644 --- a/src/components/description_list/description_list.js +++ b/src/components/description_list/description_list.js @@ -44,10 +44,15 @@ export const EuiDescriptionList = ({ let childrenOrListItems = null; if (listItems) { childrenOrListItems = ( - listItems.map((item) => { + listItems.map((item, index) => { return [ - {item.title}, - {item.description} + + {item.title} + , + + + {item.description} + ]; }) ); diff --git a/src/components/header/header_alert/__snapshots__/header_alert.test.js.snap b/src/components/header/header_alert/__snapshots__/header_alert.test.js.snap index 6e9d0ff30ee..a268f1626e0 100644 --- a/src/components/header/header_alert/__snapshots__/header_alert.test.js.snap +++ b/src/components/header/header_alert/__snapshots__/header_alert.test.js.snap @@ -7,6 +7,7 @@ exports[`EuiHeaderAlert is rendered 1`] = ` data-test-subj="test subject string" >
`; @@ -14,7 +17,10 @@ exports[`EuiPopover is rendered 1`] = ` class="euiPopover euiPopover--anchorDownCenter testClass1 testClass2" data-test-subj="test subject string" > -
`; @@ -22,7 +28,10 @@ exports[`EuiPopover props anchorPosition defaults to centerDown 1`] = `
-
`; @@ -30,7 +39,10 @@ exports[`EuiPopover props anchorPosition downRight is rendered 1`] = `
-
`; @@ -38,7 +50,10 @@ exports[`EuiPopover props anchorPosition leftCenter is rendered 1`] = `
-
`; @@ -46,7 +61,10 @@ exports[`EuiPopover props isOpen defaults to false 1`] = `
-
`; @@ -54,10 +72,14 @@ exports[`EuiPopover props isOpen renders true 1`] = `
-
`; diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 06bb4a0fa0f..1479afbab07 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -1,4 +1,5 @@ import React, { + cloneElement, Component, } from 'react'; import PropTypes from 'prop-types'; @@ -123,6 +124,7 @@ export class EuiPopover extends Component { ownFocus, withTitle, children, + id, className, closePopover, panelClassName, @@ -166,6 +168,7 @@ export class EuiPopover extends Component { paddingSize={panelPaddingSize} tabIndex={tabIndex} hasShadow + id={id} > {children} @@ -180,7 +183,10 @@ export class EuiPopover extends Component { onKeyDown={this.onKeyDown} {...rest} > - {button} + {cloneElement(button, { + 'aria-controls': id, + 'aria-expanded': !!isOpen, + })} {panel}
@@ -189,6 +195,7 @@ export class EuiPopover extends Component { } EuiPopover.propTypes = { + id: PropTypes.string.isRequired, isOpen: PropTypes.bool, ownFocus: PropTypes.bool, withTitle: PropTypes.bool, diff --git a/src/components/popover/popover.test.js b/src/components/popover/popover.test.js index 59851084aa2..05d5da6135a 100644 --- a/src/components/popover/popover.test.js +++ b/src/components/popover/popover.test.js @@ -7,10 +7,14 @@ import { EuiPopover } from './popover'; import { keyCodes } from '../../services'; +let id = 0; +const getId = () => (`${id++}`); + describe('EuiPopover', () => { test('is rendered', () => { const component = render( } closePopover={() => {}} {...requiredProps} @@ -24,6 +28,7 @@ describe('EuiPopover', () => { test('children is rendered', () => { const component = render( } closePopover={() => {}} > @@ -40,6 +45,7 @@ describe('EuiPopover', () => { test('is rendered', () => { const component = render( } closePopover={() => {}} @@ -57,6 +63,7 @@ describe('EuiPopover', () => { const component = mount( } closePopover={closePopoverHandler} @@ -72,6 +79,7 @@ describe('EuiPopover', () => { test('defaults to centerDown', () => { const component = render( } closePopover={() => {}} /> @@ -84,6 +92,7 @@ describe('EuiPopover', () => { test('leftCenter is rendered', () => { const component = render( } closePopover={() => {}} anchorPosition="leftCenter" @@ -97,6 +106,7 @@ describe('EuiPopover', () => { test('downRight is rendered', () => { const component = render( } closePopover={() => {}} anchorPosition="downRight" @@ -112,6 +122,7 @@ describe('EuiPopover', () => { test('defaults to false', () => { const component = render( } closePopover={() => {}} /> @@ -124,6 +135,7 @@ describe('EuiPopover', () => { test('renders true', () => { const component = render( } closePopover={() => {}} isOpen @@ -139,6 +151,7 @@ describe('EuiPopover', () => { test('defaults to false', () => { const component = render( } closePopover={() => {}} @@ -152,6 +165,7 @@ describe('EuiPopover', () => { test('renders true', () => { const component = render( } @@ -168,6 +182,7 @@ describe('EuiPopover', () => { test('is rendered', () => { const component = render( } closePopover={() => {}} panelClassName="test" @@ -184,6 +199,7 @@ describe('EuiPopover', () => { test('is rendered', () => { const component = render( } closePopover={() => {}} panelPaddingSize="s" diff --git a/src/components/tabs/__snapshots__/tab.test.js.snap b/src/components/tabs/__snapshots__/tab.test.js.snap index 6ae98d678b7..a1a7c6a65c6 100644 --- a/src/components/tabs/__snapshots__/tab.test.js.snap +++ b/src/components/tabs/__snapshots__/tab.test.js.snap @@ -3,8 +3,10 @@ exports[`EuiTab renders 1`] = `