Skip to content

Commit

Permalink
[HDSG-186] Updating MonthPicker to better serve assistive devices, re…
Browse files Browse the repository at this point in the history
…move aXe error (#231)

* [HDSG-186] WIP. Adding container and local IDs, plus SR only spans with long month name.

* [HDSG-186] Updating the labels to remove aria-hidden, better relate title, buttons, checkbox grid.

* Master merge.

* Updating test to run properly with null hint on FormLabel.

* Removing unneeded ID from <FormLabel>

* [HDSG-186] Refactored classes, added ability to set heading level.

* [HDSG-186] Adding a ternary operator to aria-describedby, keyed off hint prop.

* Removing an extra inverse example, switched headingType to number prop type.

* [HDSG-186] Cleaning up dynamic classes, removing extra margins, changed prop headingType to headingLevel.
  • Loading branch information
1Copenut authored Jan 31, 2018
1 parent fc4915e commit ab5b02e
Show file tree
Hide file tree
Showing 3 changed files with 2,275 additions and 2,370 deletions.
51 changes: 41 additions & 10 deletions packages/core/src/components/MonthPicker/MonthPicker.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'core-js/fn/array/includes';
import Button from '../Button/Button';
import Choice from '../ChoiceList/Choice';
import FormLabel from '../FormLabel/FormLabel';
import PropTypes from 'prop-types';
import React from 'react';
import classNames from 'classnames';
import uniqueId from 'lodash.uniqueid';

/*
`<MonthPicker>`
Expand Down Expand Up @@ -32,6 +34,8 @@ const monthNumbers = (() => {
export class MonthPicker extends React.PureComponent {
constructor(props) {
super(props);
this.hintId = uniqueId('monthpicker_hint_');
this.labelId = uniqueId('monthpicker_label_');
this.months = getMonthNames(props.locale);
this.monthsLong = getMonthNames(props.locale, false);

Expand Down Expand Up @@ -109,14 +113,15 @@ export class MonthPicker extends React.PureComponent {
{this.months.map((month, i) => (
<li key={month}>
<Choice
name={name}
value={i + 1}
aria-describedby={this.props.hint ? this.hintId : null}
aria-label={this.monthsLong[i]}
checked={selectedMonths.includes(i + 1)}
onChange={e => this.handleChange(e)}
className="ds-c-month-picker__month"
disabled={disabledMonths.includes(i + 1)}
inversed={inversed}
aria-label={this.monthsLong[i]}
onChange={e => this.handleChange(e)}
name={name}
value={i + 1}
>
{month}
</Choice>
Expand All @@ -129,6 +134,7 @@ export class MonthPicker extends React.PureComponent {
renderButton(text, onClick) {
return (
<Button
aria-describedby={this.labelId}
size="small"
className="ds-u-margin-right--1"
onClick={onClick}
Expand All @@ -147,10 +153,10 @@ export class MonthPicker extends React.PureComponent {
);
return (
<FormLabel
className="ds-u-visibility--screen-reader"
labelClassName={classes}
component="legend"
errorMessage={this.props.errorMessage}
hint={this.props.hint}
requirementLabel={this.props.requirementLabel}
inversed={this.props.inversed}
>
Expand All @@ -161,21 +167,42 @@ export class MonthPicker extends React.PureComponent {

render() {
const { selectAllText, clearAllText } = this.props;
const Heading = this.props.headingLevel
? `h${this.props.headingLevel}`
: `h4`;
const classes = classNames(
'ds-c-month-picker',
'ds-c-fieldset',
'ds-u-margin-y--3',
this.props.className
);
return (
<fieldset className={classes}>
{this.renderLabel()}
<div className="ds-u-margin-y--3">
<div className={classes}>
<div>
<Heading
className="ds-c-label ds-u-font-weight--bold ds-u-margin--0"
id={this.labelId}
>
{this.props.label}
</Heading>
{this.props.hint ? (
<p
className="ds-c-label ds-c-field__hint ds-u-margin--0"
id={this.hintId}
>
{this.props.hint}
</p>
) : null}
</div>
<div className="ds-u-margin-top--3">
{this.renderButton(selectAllText, () => this.handleSelectAll())}
{this.renderButton(clearAllText, () => this.handleClearAll())}
</div>
<div className="ds-c-month-picker__months">{this.renderMonths()}</div>
</fieldset>
<fieldset className="ds-c-fieldset">
{this.renderLabel()}
<div className="ds-c-month-picker__months">{this.renderMonths()}</div>
</fieldset>
</div>
);
}
}
Expand Down Expand Up @@ -221,6 +248,10 @@ MonthPicker.propTypes = {
* Additional hint text to display
*/
hint: PropTypes.node,
/**
* Heading type to override default `<h4>` in title block
*/
headingLevel: PropTypes.number,
/**
* Text showing the requirement ("Required", "Optional", etc.). See [Required and Optional Fields]({{root}}/guidelines/forms/#required-and-optional-fields).
*/
Expand Down
31 changes: 27 additions & 4 deletions packages/core/src/components/MonthPicker/MonthPicker.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,40 @@ describe('MonthPicker', () => {
expect(onClearAll).toHaveBeenCalled();
});

it('renders a title block with hint', () => {
const { wrapper } = renderMonthPicker({
label: 'Select a month',
hint: 'Tips and tricks'
});
const title = wrapper.find('h4.ds-c-label');
const hint = wrapper.find('p.ds-c-field__hint');
expect(title.exists()).toEqual(true);
expect(title.text()).toEqual('Select a month');
expect(hint.exists()).toEqual(true);
expect(hint.text()).toEqual('Tips and tricks');
});

it('renders a title block without hint', () => {
const { wrapper } = renderMonthPicker({
label: 'Select a preference',
headingLevel: 3
});
const title = wrapper.find('h3.ds-c-label');
const hint = wrapper.find('p.ds-c-field__hint');
expect(title.exists()).toEqual(true);
expect(title.text()).toEqual('Select a preference');
expect(hint.exists()).toEqual(false);
});

it('renders a FormLabel with correct props', () => {
const { wrapper, props } = renderMonthPicker({
labelClassName: 'ds-u-color--primary',
errorMessage: 'Error!',
hint: 'Tips and tricks'
errorMessage: 'Error!'
});
const label = wrapper.find('FormLabel');
expect(label.props()).toMatchObject({
labelClassName: 'ds-u-font-weight--bold ds-u-color--primary',
errorMessage: props.errorMessage,
hint: props.hint
errorMessage: props.errorMessage
});
});

Expand Down
Loading

0 comments on commit ab5b02e

Please sign in to comment.