Skip to content

Commit

Permalink
[HDSG-193] Add tiny and medium modifiers for input widths (#250)
Browse files Browse the repository at this point in the history
* Add tiny and medium modifiers for input widths

* Remove mistaken inverse modifiers from example

* Make sizes variables, change name from 'tiny' to 'small', add size prop to TextField, Select, and ChoiceList

* remove console.log from test

* Update textfield snapshot

* Add examples to Select and ChoiceList, simplify class logic, better proptypes

* Add built JS files and make small selec examples have better options
  • Loading branch information
hannaliebl authored Mar 6, 2018
1 parent 2d60059 commit 94b41eb
Show file tree
Hide file tree
Showing 15 changed files with 215 additions and 30 deletions.
8 changes: 7 additions & 1 deletion packages/core/dist/components/ChoiceList/ChoiceList.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ var ChoiceList = exports.ChoiceList = function (_React$PureComponent) {
}, {
key: 'select',
value: function select(selectProps, options) {
var classes = this.props.size && 'ds-c-field--' + this.props.size;
return _react2.default.createElement(
_Select2.default,
_extends({
Expand All @@ -152,7 +153,8 @@ var ChoiceList = exports.ChoiceList = function (_React$PureComponent) {
inversed: this.props.inversed,
name: this.props.name,
onBlur: this.props.onBlur,
onChange: this.props.onChange
onChange: this.props.onChange,
className: classes
}, selectProps),
options
);
Expand Down Expand Up @@ -268,6 +270,10 @@ ChoiceList.propTypes = {
name: _propTypes2.default.string.isRequired,
onBlur: _propTypes2.default.func,
onChange: _propTypes2.default.func,
/**
* If the component renders a select, set the max-width of the input either to `'small'` or `'medium'`.
*/
size: _propTypes2.default.oneOf(['small', 'medium']),
/**
* You can manually set the `type` if you prefer things to be less magical.
* Otherwise, the type will be inferred by the other `props`, based
Expand Down
9 changes: 7 additions & 2 deletions packages/core/dist/components/ChoiceList/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ var Select = function Select(props) {
className = props.className,
id = props.id,
inversed = props.inversed,
selectProps = _objectWithoutProperties(props, ['children', 'className', 'id', 'inversed']);
size = props.size,
selectProps = _objectWithoutProperties(props, ['children', 'className', 'id', 'inversed', 'size']);
/* eslint-enable prefer-const */

var classes = (0, _classnames2.default)('ds-c-field', { 'ds-c-field--inverse': inversed }, className);
var classes = (0, _classnames2.default)('ds-c-field', { 'ds-c-field--inverse': inversed }, className, size && 'ds-c-field--' + size);

if (!id) {
id = (0, _lodash2.default)('select_' + selectProps.name + '_');
Expand Down Expand Up @@ -95,6 +96,10 @@ Select.propTypes = {
name: _propTypes2.default.string.isRequired,
onBlur: _propTypes2.default.func,
onChange: _propTypes2.default.func,
/**
* Set the max-width of the input either to `'small'` or `'medium'`.
*/
size: _propTypes2.default.oneOf(['small', 'medium']),
/**
* Sets the field's `value`. Use this in combination with `onChange`
* for a controlled component; otherwise, set `defaultValue`.
Expand Down
94 changes: 83 additions & 11 deletions packages/core/dist/components/TextField/TextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,60 @@ var TextField = exports.TextField = function (_React$PureComponent) {
}

_createClass(TextField, [{
key: 'ariaLabel',
value: function ariaLabel() {
if (this.props.ariaLabel) {
return this.props.ariaLabel;
} else if (this.props.mask === 'currency') {
return this.props.label + '. Enter amount in dollars.';
}
}

/**
* @param {React.Component} field
* @returns {React.Component} The input field, optionally including mask
* markup if a mask is present
*/

}, {
key: 'renderFieldAndMask',
value: function renderFieldAndMask(field) {
var maskName = this.props.mask;

return maskName ? _react2.default.createElement(
'div',
{ className: 'ds-c-field-mask ds-c-field-mask--' + maskName },
this.renderMask(),
field
) : field;
}

/**
* UI overlayed on top of a field to support certain masks
*/

}, {
key: 'renderMask',
value: function renderMask() {
if (this.props.mask) {
var content = {
currency: '$'
};

return _react2.default.createElement(
'div',
{
className: 'ds-c-field__before ds-c-field__before--' + this.props.mask
},
content[this.props.mask]
);
}
}
}, {
key: 'render',
value: function render() {
var _props = this.props,
ariaLabel = _props.ariaLabel,
className = _props.className,
labelClassName = _props.labelClassName,
fieldClassName = _props.fieldClassName,
Expand All @@ -68,21 +119,33 @@ var TextField = exports.TextField = function (_React$PureComponent) {
requirementLabel = _props.requirementLabel,
inversed = _props.inversed,
rows = _props.rows,
mask = _props.mask,
multiline = _props.multiline,
label = _props.label,
fieldRef = _props.fieldRef,
size = _props.size,
type = _props.type,
fieldProps = _objectWithoutProperties(_props, ['className', 'labelClassName', 'fieldClassName', 'errorMessage', 'hint', 'id', 'requirementLabel', 'inversed', 'rows', 'multiline', 'label', 'fieldRef', 'type']);
fieldProps = _objectWithoutProperties(_props, ['ariaLabel', 'className', 'labelClassName', 'fieldClassName', 'errorMessage', 'hint', 'id', 'requirementLabel', 'inversed', 'rows', 'mask', 'multiline', 'label', 'fieldRef', 'size', 'type']);

var FieldComponent = multiline ? 'textarea' : 'input';
var _rows = multiline && rows ? rows : undefined;

var classes = (0, _classnames2.default)('ds-u-clearfix', // fixes issue where the label's margin is collapsed
className);
var fieldClasses = (0, _classnames2.default)('ds-c-field', {

var fieldClasses = (0, _classnames2.default)('ds-c-field', mask && 'ds-c-field--' + mask, {
'ds-c-field--error': typeof errorMessage === 'string',
'ds-c-field--inverse': inversed
}, fieldClassName);
}, fieldClassName, size && 'ds-c-field--' + size);

var field = _react2.default.createElement(FieldComponent, _extends({
'aria-label': this.ariaLabel(),
className: fieldClasses,
id: this.id,
ref: fieldRef,
rows: _rows,
type: multiline ? undefined : type
}, fieldProps));

return _react2.default.createElement(
'div',
Expand All @@ -99,13 +162,7 @@ var TextField = exports.TextField = function (_React$PureComponent) {
},
label
),
_react2.default.createElement(FieldComponent, _extends({
className: fieldClasses,
id: this.id,
ref: fieldRef,
rows: _rows,
type: multiline ? undefined : type
}, fieldProps))
this.renderFieldAndMask(field, mask)
);
}
}]);
Expand All @@ -118,6 +175,11 @@ TextField.defaultProps = {
};

TextField.propTypes = {
/**
* Apply an `aria-label` to the text field to provide additional
* context to assistive devices.
*/
ariaLabel: _propTypes2.default.string,
/**
* Additional classes to be added to the root `div` element
*/
Expand Down Expand Up @@ -161,6 +223,12 @@ TextField.propTypes = {
* Additional classes to be added to the label
*/
labelClassName: _propTypes2.default.string,
/**
* Apply formatting to the field that's unique to the value
* you expect to be entered. Depending on the mask, the
* field's appearance and functionality may be affected.
*/
mask: _propTypes2.default.oneOf(['currency']),
/**
* `max` HTML input attribute
*/
Expand All @@ -170,7 +238,7 @@ TextField.propTypes = {
*/
min: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),
/**
* Whether or not the textfield is a multiline textfield
* Whether or not the text field is a multiline text field
*/
multiline: _propTypes2.default.bool,
name: _propTypes2.default.string.isRequired,
Expand All @@ -181,6 +249,10 @@ TextField.propTypes = {
* applicable if this is a multiline field.
*/
rows: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),
/**
* Set the max-width of the input either to `'small'` or `'medium'`.
*/
size: _propTypes2.default.oneOf(['small', 'medium']),
/**
* Any valid `input` [type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
*/
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/components/ChoiceList/ChoiceList.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,27 @@ ReactDOM.render(
label="Select example"
name="select_choices_field"
/>
<ChoiceList
choices={[
{ label: 'A', value: 'A' },
{ defaultChecked: true, label: 'B', value: 'B' },
{ label: 'C', value: 'C' },
{ label: 'D', value: 'D' },
{ label: 'E', value: 'E' },
{ label: 'F', value: 'F' },
{ label: 'G', value: 'G' },
{ label: 'H', value: 'H' }
]}
size="small"
label="Small select example"
name="small_select_choices_field"
/>
<ChoiceList
choices={options()}
size="medium"
label="Medium select example"
name="medium_select_choices_field"
/>
</div>,
document.getElementById('js-example')
);
Expand Down Expand Up @@ -70,5 +91,6 @@ function choices() {
function options() {
const options = generateChoices(8);
options[1].defaultChecked = true;
console.log(options);
return options;
}
6 changes: 6 additions & 0 deletions packages/core/src/components/ChoiceList/ChoiceList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class ChoiceList extends React.PureComponent {
* @param {array} options - <option> components
*/
select(selectProps, options) {
const classes = this.props.size && `ds-c-field--${this.props.size}`;
return (
<Select
disabled={this.props.disabled}
Expand All @@ -89,6 +90,7 @@ export class ChoiceList extends React.PureComponent {
name={this.props.name}
onBlur={this.props.onBlur}
onChange={this.props.onChange}
className={classes}
{...selectProps}
>
{options}
Expand Down Expand Up @@ -202,6 +204,10 @@ ChoiceList.propTypes = {
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func,
/**
* If the component renders a select, set the max-width of the input either to `'small'` or `'medium'`.
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* You can manually set the `type` if you prefer things to be less magical.
* Otherwise, the type will be inferred by the other `props`, based
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/components/ChoiceList/ChoiceList.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@ describe('ChoiceList', () => {
expect(selectId).toBe(labelId);
});

it('adds size classes to root element', () => {
props.size = 'small';
const data = shallowRender(props);

expect(data.wrapper.find('Select').hasClass('ds-c-field--small')).toBe(
true
);
});

it('is disabled', () => {
props.disabled = true;
const data = shallowRender(props);
Expand Down
35 changes: 26 additions & 9 deletions packages/core/src/components/ChoiceList/Select.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,31 @@ import ReactDOM from 'react-dom';
import Select from './Select';

ReactDOM.render(
<Select defaultValue="2" name="select-demo">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
<option value="4">Option 4</option>
<option value="5">Option 5</option>
<option value="6">Option 6</option>
<option value="7">Option 7</option>
</Select>,
<div>
<Select defaultValue="2" name="select-demo">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
<option value="4">Option 4</option>
<option value="5">Option 5</option>
<option value="6">Option 6</option>
<option value="7">Option 7</option>
</Select>
<h4>Small size modifier</h4>
<Select defaultValue="Jr." size="small" name="small-select-demo">
<option value="Jr.">Jr.</option>
<option value="Sr.">Sr.</option>
</Select>
<h4>Medium size modifier</h4>
<Select defaultValue="2" size="medium" name="medium-select-demo">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
<option value="4">Option 4</option>
<option value="5">Option 5</option>
<option value="6">Option 6</option>
<option value="7">Option 7</option>
</Select>
</div>,
document.getElementById('js-example')
);
12 changes: 8 additions & 4 deletions packages/core/src/components/ChoiceList/Select.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ export const Select = function(props) {
className,
id,
inversed,
size,
...selectProps
} = props;
/* eslint-enable prefer-const */

const classes = classNames(
'ds-c-field',
{ 'ds-c-field--inverse': inversed },
className
className,
size && `ds-c-field--${size}`
);

if (!id) {
Expand Down Expand Up @@ -68,9 +70,7 @@ Select.propTypes = {
if (props[propName]) {
/* eslint-disable quotes */
return new Error(
`'${propName}' supplied to '${
componentName
}'. [A11Y]: Users often don’t` +
`'${propName}' supplied to '${componentName}'. [A11Y]: Users often don’t` +
` understand how to select multiple items from dropdowns. Use checkboxes instead.`
);
/* eslint-enable */
Expand All @@ -82,6 +82,10 @@ Select.propTypes = {
name: PropTypes.string.isRequired,
onBlur: PropTypes.func,
onChange: PropTypes.func,
/**
* Set the max-width of the input either to `'small'` or `'medium'`.
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* Sets the field's `value`. Use this in combination with `onChange`
* for a controlled component; otherwise, set `defaultValue`.
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/components/ChoiceList/Select.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ describe('Select', () => {
expect(data.wrapper.hasClass('ds-c-field')).toBe(true);
});

it('adds size classes to root element', () => {
const mediumData = shallowRender({ size: 'medium' });
const smallData = shallowRender({ size: 'small' });

expect(mediumData.wrapper.hasClass('ds-c-field--medium')).toBe(true);
expect(smallData.wrapper.hasClass('ds-c-field--small')).toBe(true);
});

it('is disabled', () => {
const data = shallowRender({ disabled: true });

Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/components/TextField/TextField.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ ReactDOM.render(
name="single_example"
requirementLabel="Optional"
/>
<TextField label="Small size modifier" name="small_example" size="small" />
<TextField
label="Medium size modifier"
name="medium_example"
size="medium"
/>
<TextField
errorMessage="Error message example"
hint="Example of a multiline field with an error"
Expand Down
Loading

0 comments on commit 94b41eb

Please sign in to comment.