diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55fc299..bf64854 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Change Log
+## 2.1.2
+
+* Add htmlFor/id attribute to labels associating them to inputs
+
## 2.1.1
* Increase contrast in disabled mini button text
diff --git a/src/components/AutocompleteInput.jsx b/src/components/AutocompleteInput.jsx
index 135e27b..1aec5c7 100644
--- a/src/components/AutocompleteInput.jsx
+++ b/src/components/AutocompleteInput.jsx
@@ -480,6 +480,7 @@ export default class AutocompleteInput extends Component {
asText,
embedded,
readOnly,
+ id,
} = this.props;
const {
@@ -492,6 +493,7 @@ export default class AutocompleteInput extends Component {
readOnly={readOnly}
value={getDisplayName(value)}
embedded={embedded}
+ id={id}
/>
);
}
diff --git a/src/components/CheckboxInput.jsx b/src/components/CheckboxInput.jsx
index eeff357..93be7f7 100644
--- a/src/components/CheckboxInput.jsx
+++ b/src/components/CheckboxInput.jsx
@@ -116,14 +116,12 @@ export default class CheckboxInput extends Component {
);
}
- // FIXME: Don't break jsx-a11y/label-has-associated-control.
-
/* eslint-disable
- jsx-a11y/label-has-associated-control,
+ jsx-a11y/no-static-element-interactions,
jsx-a11y/no-noninteractive-element-interactions,
jsx-a11y/click-events-have-key-events */
return (
-
+
);
/* eslint-enable
- jsx-a11y/label-has-associated-control,
+ jsx-a11y/no-static-element-interactions,
jsx-a11y/no-noninteractive-element-interactions,
jsx-a11y/click-events-have-key-events */
}
diff --git a/src/components/CustomCompoundInput.jsx b/src/components/CustomCompoundInput.jsx
index a322649..2b72d26 100644
--- a/src/components/CustomCompoundInput.jsx
+++ b/src/components/CustomCompoundInput.jsx
@@ -6,11 +6,14 @@ import get from 'lodash/get';
import { getPath, pathPropType } from '../helpers/pathHelpers';
import { isInput } from '../helpers/inputHelpers';
import styles from '../../styles/cspace-input/CompoundInput.css';
+import labelToLegend from '../helpers/labelToLegend';
const propTypes = {
children: PropTypes.node,
className: PropTypes.string,
defaultChildSubpath: pathPropType,
+ id: PropTypes.string,
+ label: PropTypes.node,
name: PropTypes.string,
// TODO: Stop using propTypes in isInput. Until then, these unused props need to be declared so
// this component is recognized as an input.
@@ -29,10 +32,12 @@ const defaultProps = {
children: undefined,
className: undefined,
defaultChildSubpath: undefined,
+ label: undefined,
name: undefined,
parentPath: undefined,
subpath: undefined,
readOnly: undefined,
+ id: undefined,
value: {},
};
@@ -62,6 +67,7 @@ export default class CustomCompoundInput extends Component {
decorateInputs(children) {
const {
readOnly,
+ id: parentId,
} = this.props;
return React.Children.map(children, (child) => {
@@ -88,12 +94,19 @@ export default class CustomCompoundInput extends Component {
subpath = defaultChildSubpath;
}
- return React.cloneElement(child, {
+ const overrides = {
readOnly,
subpath,
parentPath: getPath(this.props),
value: getChildValue(value, subpath, name),
- });
+ };
+
+ // Propagate id to inputs that don't have one
+ if (!child.props.id && parentId && name) {
+ overrides.id = `${parentId}-${name}`;
+ }
+
+ return React.cloneElement(child, overrides);
}
return React.cloneElement(child, {
@@ -106,6 +119,7 @@ export default class CustomCompoundInput extends Component {
const {
children,
className,
+ label,
name,
readOnly,
} = this.props;
@@ -114,11 +128,14 @@ export default class CustomCompoundInput extends Component {
[styles.readOnly]: readOnly,
});
+ const legend = labelToLegend(label);
+
return (
);
@@ -127,3 +144,4 @@ export default class CustomCompoundInput extends Component {
CustomCompoundInput.propTypes = propTypes;
CustomCompoundInput.defaultProps = defaultProps;
+CustomCompoundInput.useLegend = true;
diff --git a/src/components/InputTable.jsx b/src/components/InputTable.jsx
index 81cda21..3aed2c7 100644
--- a/src/components/InputTable.jsx
+++ b/src/components/InputTable.jsx
@@ -3,10 +3,13 @@ import PropTypes from 'prop-types';
import InputTableHeader from './InputTableHeader';
import InputTableRow from './InputTableRow';
import styles from '../../styles/cspace-input/InputTable.css';
+import labelToLegend from '../helpers/labelToLegend';
const propTypes = {
children: PropTypes.node,
embedded: PropTypes.bool,
+ id: PropTypes.string,
+ label: PropTypes.node,
renderLabel: PropTypes.func,
renderAriaLabel: PropTypes.func,
};
@@ -14,6 +17,8 @@ const propTypes = {
const defaultProps = {
children: undefined,
embedded: undefined,
+ id: undefined,
+ label: undefined,
renderLabel: undefined,
renderAriaLabel: undefined,
};
@@ -22,12 +27,17 @@ export default function InputTable(props) {
const {
children,
embedded,
+ id,
+ label,
renderLabel,
renderAriaLabel,
} = props;
+ const legend = labelToLegend(label);
+
return (
-
+
+
);
}
InputTable.propTypes = propTypes;
InputTable.defaultProps = defaultProps;
+InputTable.useLegend = true;
diff --git a/src/components/Label.jsx b/src/components/Label.jsx
index 9e47cbf..46c5733 100644
--- a/src/components/Label.jsx
+++ b/src/components/Label.jsx
@@ -6,12 +6,16 @@ const propTypes = {
children: PropTypes.node,
readOnly: PropTypes.bool,
required: PropTypes.bool,
+ htmlFor: PropTypes.string,
+ id: PropTypes.string,
};
const defaultProps = {
children: undefined,
readOnly: undefined,
required: undefined,
+ htmlFor: undefined,
+ id: undefined,
};
/**
@@ -22,14 +26,14 @@ export default function Label(props) {
children,
readOnly,
required,
+ htmlFor,
+ id,
} = props;
const className = (required && !readOnly) ? styles.required : styles.common;
return (
- // FIXME: Set the htmlFor prop to associate the labeled control.
- // eslint-disable-next-line jsx-a11y/label-has-associated-control
-