From 6fd518d1a22755873449948dec0560ef8ad23d7f Mon Sep 17 00:00:00 2001 From: Andy Terkik Date: Tue, 2 Jan 2018 13:24:13 -0500 Subject: [PATCH 01/19] Make Snackbar label arg accept React elements --- components/snackbar/Snackbar.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/snackbar/Snackbar.d.ts b/components/snackbar/Snackbar.d.ts index 9286938da..68393cc78 100644 --- a/components/snackbar/Snackbar.d.ts +++ b/components/snackbar/Snackbar.d.ts @@ -49,7 +49,7 @@ export interface SnackbarProps extends ReactToolbox.Props { /** * Text to display in the content. */ - label?: string; + label?: string | React.ReactElement; /** * Callback function that will be called when the button action is clicked. */ From efacffb8ce9b39ae80d25722693046c524067473 Mon Sep 17 00:00:00 2001 From: Ludovic Cabre Date: Thu, 4 Jan 2018 15:00:34 -0500 Subject: [PATCH 02/19] fix: Only
  • elements should be under
      . This is an accessibility requirement. This changes the ListDivider to be wrapped in a
    • tag by default. This behavior can be disabled by passing li=false. --- components/list/ListDivider.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/components/list/ListDivider.js b/components/list/ListDivider.js index 8ad53022b..5c4cf5b9f 100644 --- a/components/list/ListDivider.js +++ b/components/list/ListDivider.js @@ -3,15 +3,19 @@ import PropTypes from 'prop-types'; import { themr } from 'react-css-themr'; import { LIST } from '../identifiers'; -const ListDivider = ({ inset, theme }) => ( -
      -); +const ListDivider = ({ inset, li, theme }) => { + const hr = ( + + ); + return li ?
    • : hr; +}; ListDivider.propTypes = { inset: PropTypes.bool, + li: PropTypes.bool, theme: PropTypes.shape({ divider: PropTypes.string, inset: PropTypes.string, @@ -20,6 +24,7 @@ ListDivider.propTypes = { ListDivider.defaultProps = { inset: false, + li: true, }; export default themr(LIST)(ListDivider); From 5ac0c8e12ed2d6f5b5bb3f60a1a6347d8a613747 Mon Sep 17 00:00:00 2001 From: Nathan Miranda Date: Mon, 8 Jan 2018 15:09:25 -0500 Subject: [PATCH 03/19] Adding optional ariaLabel prop for
    • in MenuItem --- components/menu/MenuItem.d.ts | 4 ++++ components/menu/MenuItem.js | 3 +++ 2 files changed, 7 insertions(+) diff --git a/components/menu/MenuItem.d.ts b/components/menu/MenuItem.d.ts index 457718443..151e38837 100644 --- a/components/menu/MenuItem.d.ts +++ b/components/menu/MenuItem.d.ts @@ -29,6 +29,10 @@ export interface MenuItemTheme { } export interface MenuItemProps extends ReactToolbox.Props { + /** + * Aria-label for the
    • DOM element + */ + ariaLabel?: string; /** * The text to include in the menu item. Required. */ diff --git a/components/menu/MenuItem.js b/components/menu/MenuItem.js index 412f78c3f..5d0b562e1 100644 --- a/components/menu/MenuItem.js +++ b/components/menu/MenuItem.js @@ -9,6 +9,7 @@ import rippleFactory from '../ripple/Ripple'; const factory = (ripple) => { class MenuItem extends Component { static propTypes = { + ariaLabel: PropTypes.string, caption: PropTypes.string, children: PropTypes.node, className: PropTypes.string, @@ -52,6 +53,7 @@ const factory = (ripple) => { render() { const { + ariaLabel, caption, children, disabled, @@ -77,6 +79,7 @@ const factory = (ripple) => { role="menuitem" tabIndex={disabled ? '-1' : tabIndex} aria-disabled={disabled} + aria-label={ariaLabel} > {icon ? : null} {caption} From 51562456e6ddffb475e1865939e3e31faa0df3d9 Mon Sep 17 00:00:00 2001 From: Allin Resposo Date: Wed, 10 Jan 2018 16:35:45 -0500 Subject: [PATCH 04/19] Add wrapper around button label --- components/button/Button.js | 3 ++- components/button/base.d.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/components/button/Button.js b/components/button/Button.js index 90634ea87..192ba848a 100644 --- a/components/button/Button.js +++ b/components/button/Button.js @@ -33,6 +33,7 @@ const factory = (ripple, FontIcon) => { button: PropTypes.string, flat: PropTypes.string, floating: PropTypes.string, + label: PropTypes.string, icon: PropTypes.string, inverse: PropTypes.string, mini: PropTypes.string, @@ -122,7 +123,7 @@ const factory = (ripple, FontIcon) => { return React.createElement(element, props, icon ? : null, - label, + {label}, children, ); } diff --git a/components/button/base.d.ts b/components/button/base.d.ts index bd54431f9..ae05ed4b8 100644 --- a/components/button/base.d.ts +++ b/components/button/base.d.ts @@ -18,6 +18,10 @@ export interface ButtonTheme { * Used when the button is floating for the root element. */ floating?: string; + /** + * For the label inside a button. + */ + label?: string; /** * For the icon inside a button. */ From a12ca4a5851c935b62529b9272fa32fa40b54bea Mon Sep 17 00:00:00 2001 From: Nathan Miranda Date: Thu, 11 Jan 2018 17:50:00 -0500 Subject: [PATCH 05/19] Propagating theme.button down to the root level of IconButton --- components/button/IconButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/button/IconButton.js b/components/button/IconButton.js index c50496c3d..9f8eb2ab2 100644 --- a/components/button/IconButton.js +++ b/components/button/IconButton.js @@ -88,7 +88,7 @@ const factory = (ripple, FontIcon) => { } = this.props; const element = href ? 'a' : 'button'; const level = this.getLevel(); - const classes = classnames([theme.toggle], { + const classes = classnames(theme.button, [theme.toggle], { [theme[level]]: neutral, [theme.inverse]: inverse, }, className); From 923d8998665b0cdc2645b6bf3327f989a5c90b04 Mon Sep 17 00:00:00 2001 From: Allin Resposo Date: Thu, 11 Jan 2018 18:10:20 -0500 Subject: [PATCH 06/19] Update tabindex logic on tabs --- components/list/ListItem.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/list/ListItem.js b/components/list/ListItem.js index 4562dbf5a..2581ca54a 100644 --- a/components/list/ListItem.js +++ b/components/list/ListItem.js @@ -113,6 +113,7 @@ const factory = (ripple, ListItemLayout, ListItemContent) => { } = this.props; const children = this.groupChildren(); const content = ; + const tabIndexProp = onClick && !to ? { tabIndex } : {}; return (
    • { onMouseDown={onMouseDown} onTouchStart={onTouchStart} onKeyDown={this.handleEnter} - tabIndex={to || !onClick ? -1 : tabIndex} + {...tabIndexProp} > {to ? {content} : content} {children.ignored} From f180683aeabab97cde18c60126b31299d25a1e74 Mon Sep 17 00:00:00 2001 From: Alex Heitzmann Date: Tue, 30 Jan 2018 17:15:45 -0500 Subject: [PATCH 07/19] Add option to hide ProgressBar component from screen reader --- components/progress_bar/ProgressBar.d.ts | 10 ++++++++++ components/progress_bar/ProgressBar.js | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/components/progress_bar/ProgressBar.d.ts b/components/progress_bar/ProgressBar.d.ts index 90db36011..daf116fe9 100644 --- a/components/progress_bar/ProgressBar.d.ts +++ b/components/progress_bar/ProgressBar.d.ts @@ -47,6 +47,16 @@ export interface ProgressBarProps extends ReactToolbox.Props { * @default false */ disabled?: boolean; + /** + * Whether or not the progress bar should be hidden from the screen reader. + * + * Can be used if the caller wishes to provide more context for progress updates than just + * the percent. Also useful to work around an issue with IE11 + JAWS reading the aria-valuenow + * attribute instead of the aria-valuetext attribute on updates. + * + * @default false + */ + hiddenFromScreenReader?: boolean /** * Maximum value permitted. * @default 100 diff --git a/components/progress_bar/ProgressBar.js b/components/progress_bar/ProgressBar.js index 58eb44dfc..fc0520638 100644 --- a/components/progress_bar/ProgressBar.js +++ b/components/progress_bar/ProgressBar.js @@ -10,6 +10,7 @@ class ProgressBar extends Component { buffer: PropTypes.number, className: PropTypes.string, disabled: PropTypes.bool, + hiddenFromScreenReader: PropTypes.bool, max: PropTypes.number, min: PropTypes.number, mode: PropTypes.oneOf(['determinate', 'indeterminate']), @@ -36,6 +37,7 @@ class ProgressBar extends Component { mode: 'indeterminate', multicolor: false, type: 'linear', + hiddenFromScreenReader: false, value: 0, }; @@ -80,7 +82,18 @@ class ProgressBar extends Component { } render() { - const { className, disabled, max, min, mode, multicolor, type, theme, value } = this.props; + const { + className, + disabled, + hiddenFromScreenReader, + max, + min, + mode, + multicolor, + type, + theme, + value, + } = this.props; const _className = classnames(theme[type], { [theme.indeterminate]: mode === 'indeterminate', [theme.multicolor]: multicolor, @@ -95,6 +108,7 @@ class ProgressBar extends Component { aria-valuenow={value} aria-valuemin={min} aria-valuemax={max} + aria-hidden={hiddenFromScreenReader} className={_className} > {type === 'circular' ? this.renderCircular() : this.renderLinear()} From bd71d358b244a67aed8896f2ddb149f216a36007 Mon Sep 17 00:00:00 2001 From: Allin Resposo Date: Tue, 20 Feb 2018 17:11:40 -0500 Subject: [PATCH 08/19] Exit autocomplete if query and selection are both empty --- components/autocomplete/Autocomplete.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/autocomplete/Autocomplete.js b/components/autocomplete/Autocomplete.js index 099a03378..8143d11ea 100644 --- a/components/autocomplete/Autocomplete.js +++ b/components/autocomplete/Autocomplete.js @@ -146,6 +146,10 @@ const factory = (Chip, Input) => { ); if (event.which === 13) { + if (!this.state.query.trim().length && !this.state.active) { + events.pauseEvent(event) + return + } this.selectOrCreateActiveItem(event); } }; From 132d00aa5fddaa07da46d7117840350ccd73286b Mon Sep 17 00:00:00 2001 From: Allin Resposo Date: Tue, 20 Feb 2018 17:22:46 -0500 Subject: [PATCH 09/19] Move ListItem aria-label to anchor as needed --- components/list/ListItem.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/list/ListItem.js b/components/list/ListItem.js index 2581ca54a..b8716d66a 100644 --- a/components/list/ListItem.js +++ b/components/list/ListItem.js @@ -113,11 +113,13 @@ const factory = (ripple, ListItemLayout, ListItemContent) => { } = this.props; const children = this.groupChildren(); const content = ; - const tabIndexProp = onClick && !to ? { tabIndex } : {}; + const tabIndexProp = onClick && !to ? { + tabIndex, + 'aria-label': ariaLabel, + } : {}; return (
    • { onKeyDown={this.handleEnter} {...tabIndexProp} > - {to ? {content} : content} + {to ? ( + {content} + ) : content} {children.ignored} {altText ? {altText} : null}
    • From b27572310e0d1db57d5e67264da4891533de81aa Mon Sep 17 00:00:00 2001 From: Allin Resposo Date: Tue, 27 Mar 2018 16:32:20 -0400 Subject: [PATCH 10/19] Add aria-labelledby to radio and checkbox --- components/checkbox/Checkbox.js | 11 +++++++---- components/radio/RadioButton.js | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/components/checkbox/Checkbox.js b/components/checkbox/Checkbox.js index b209fb1a0..a17a2ac64 100644 --- a/components/checkbox/Checkbox.js +++ b/components/checkbox/Checkbox.js @@ -63,24 +63,27 @@ const factory = (Check) => { const className = classnames(theme.field, { [theme.disabled]: this.props.disabled, }, this.props.className); - const id = `field_${uuidv4()}`; + const inputId = `input_${uuidv4()}`; + const labelId = `label_${uuidv4()}`; return (