Skip to content

Commit 7e56cc2

Browse files
committed
(CDPE-3578) Add trailingButton* props and deprecate trailingIcon
This commit changes what we're doing a little bit with the button functionality in the Input component. We decided to leave the leading icon out of it all together and just add a trailing button. Now, to add a trailing button, users can either define the trailingButtonIcon prop and/or the trailingButtonText with the onClickTrailingButton prop to get the button going. I also added a trailingButtonProps prop so users can pass things like aria-label to the button. Also, trailingIcon is deprecated.
1 parent 736eb31 commit 7e56cc2

File tree

5 files changed

+51
-35
lines changed

5 files changed

+51
-35
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Next
22

3-
- [Input] Add iconButton and onClickIconButton props for show/hide functionality
3+
- [Input] Add trailingButton* props for show/hide functionality, deprecate trailingIcon
44

55
# 5.22.0 (2020-08-12)
66

packages/react-components/source/react/library/input/Input.js

+32-25
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ const propTypes = {
3636
error: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
3737
/** Optional icon rendered before input area */
3838
icon: PropTypes.string,
39-
/** Optional icon rendered after input area */
39+
/** @deprecated Optional icon rendered after input area */
4040
trailingIcon: PropTypes.string,
41-
/** Whether or not the icon is rendered as a button */
42-
iconButton: PropTypes.bool,
41+
/** Icon for rendered trailing button */
42+
trailingButtonIcon: PropTypes.string,
43+
/** Text for rendered trailing button. Can be used with or without trailingButtonIcon*/
44+
trailingButtonText: PropTypes.string,
4345
/** Optional additional className */
4446
className: PropTypes.string,
4547
/** Optional inline styles */
@@ -48,8 +50,8 @@ const propTypes = {
4850
inputRef: PropTypes.func,
4951
/** Change handler. Passed in order: new value, original event. Additionally, other event handlers and and props are propagated to the inner input element for use as needed */
5052
onChange: PropTypes.func,
51-
/** Function for button click (use iconButton to make icon clickable) */
52-
onClickIconButton: PropTypes.func,
53+
/** Function for trailing button click */
54+
onClickTrailingButton: PropTypes.func,
5355
};
5456

5557
const defaultProps = {
@@ -61,12 +63,15 @@ const defaultProps = {
6163
error: false,
6264
icon: null,
6365
trailingIcon: null,
66+
trailingButtonIcon: null,
67+
trailingButtonText: '',
68+
trailingButtonProps: {},
6469
iconButton: false,
6570
style: {},
6671
className: '',
6772
inputRef() {},
6873
onChange() {},
69-
onClickIconButton() {},
74+
onClickTrailingButton() {},
7075
};
7176

7277
/**
@@ -88,26 +93,23 @@ const Input = ({
8893
error,
8994
icon,
9095
trailingIcon,
91-
iconButton,
96+
trailingButtonIcon,
97+
trailingButtonText,
98+
trailingButtonProps,
9299
className,
93100
style,
94101
inputRef,
95102
onChange,
96-
onClickIconButton,
103+
onClickTrailingButton,
97104
...otherProps
98105
}) => {
99106
const isMultiline = type === 'multiline';
100107

101108
const Element = isMultiline ? 'textarea' : 'input';
102109

103-
const lIcon = iconButton ? (
104-
<Button
105-
className="rc-input-icon rc-input-button-icon leading edge"
106-
icon={icon}
107-
type="transparent"
108-
onClick={() => onClickIconButton()}
109-
/>
110-
) : (
110+
const showTrailingButton = !!trailingButtonIcon || !!trailingButtonText;
111+
112+
const lIcon = (
111113
<Icon
112114
className="rc-input-icon leading"
113115
width="16px"
@@ -116,26 +118,31 @@ const Input = ({
116118
/>
117119
);
118120

119-
const tIcon = iconButton ? (
120-
<Button
121-
className="rc-input-icon rc-input-button-icon trailing edge"
122-
icon={trailingIcon}
123-
type="transparent"
124-
onClick={() => onClickIconButton()}
125-
/>
126-
) : (
121+
/** trailingIcon is deprecated */
122+
const tIcon = (
127123
<Icon
128-
className="rc-input-icon trailing"
124+
className={`rc-input-icon trailing ${showTrailingButton && "with-trailing-button"}`}
129125
width="16px"
130126
height="16px"
131127
type={trailingIcon}
132128
/>
133129
);
134130

131+
const trailingButton = (
132+
<Button
133+
className="rc-input-icon rc-input-button-icon trailing edge"
134+
icon={trailingButtonIcon}
135+
type="transparent"
136+
onClick={() => onClickTrailingButton()}
137+
{...trailingButtonProps}
138+
>{trailingButtonText}</Button>
139+
)
140+
135141
return (
136142
<div className={classNames('rc-input-container', className)} style={style}>
137143
{icon && lIcon}
138144
{trailingIcon && tIcon}
145+
{showTrailingButton && trailingButton}
139146
<Element
140147
id={name}
141148
name={name}

packages/react-components/source/react/library/input/Input.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,12 @@ const type = state['input-ex13-show'] ? 'text' : 'password';
120120
name="input-ex13"
121121
type={type}
122122
value={state['input-ex13-value']}
123-
trailingIcon="eye"
124-
iconButton
123+
trailingButtonIcon="eye"
124+
trailingButtonProps={{"aria-label":"toggle show/hide text"}}
125125
placeholder="Use the trailing icon for showing/hiding passwords"
126126
style={exampleStyle}
127127
onChange={value => setState({ 'input-ex13-value': value })}
128-
onClickIconButton={value => setState({ 'input-ex13-show': !state['input-ex13-show']})}
128+
onClickTrailingButton={value => setState({ 'input-ex13-show': !state['input-ex13-show']})}
129129
/>
130130
</div>;
131131
```

packages/react-components/source/scss/library/components/forms/_input.scss

+4-4
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@
6666
left: $puppet-common-spacing-base * 2;
6767
}
6868

69-
.rc-input-icon.leading.edge {
70-
left: $puppet-common-spacing-base * 0;
71-
}
72-
7369
.rc-input-icon.trailing {
7470
right: $puppet-common-spacing-base * 2;
7571
}
@@ -78,6 +74,10 @@
7874
right: $puppet-common-spacing-base * 0;
7975
}
8076

77+
.rc-input-icon.trailing.with-trailing-button {
78+
right: $puppet-common-spacing-base * 9;
79+
}
80+
8181
.rc-input-icon.leading ~ .rc-input {
8282
padding-left: 31px;
8383
}

packages/react-components/test/input/input.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,18 @@ describe('<Input />', () => {
130130
).to.have.className('rc-input-simple');
131131
});
132132

133-
it('should respond to click events if trailingIcon, iconButton, and onClickButtonIcon are provided', () => {
133+
it('should respond to click events if trailingButtonIcon and onClickTrailingButton are provided', () => {
134134
const onClick = sinon.spy();
135-
const wrapper = mount(<Input {...requiredProps} trailingIcon="eye" iconButton onClickIconButton={onClick} />);
135+
const wrapper = mount(<Input {...requiredProps} trailingButtonIcon="eye" onClickTrailingButton={onClick} />);
136+
137+
wrapper.find('button').simulate('click');
138+
139+
expect(onClick.called).to.equal(true);
140+
});
141+
142+
it('should respond to click events if trailingButtonText and onClickTrailingButton are provided', () => {
143+
const onClick = sinon.spy();
144+
const wrapper = mount(<Input {...requiredProps} trailingButtonText="Click me" onClickTrailingButton={onClick} />);
136145

137146
wrapper.find('button').simulate('click');
138147

0 commit comments

Comments
 (0)