Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 6b3cfe5

Browse files
authoredSep 12, 2018
feat(text-field): Add support for leading/trailing icons at the same time (#3451)
BREAKING CHANGE: Component API's for interacting with icons has changed. Please refer to the documentation.
1 parent 6b6370d commit 6b3cfe5

18 files changed

+872
-64
lines changed
 

‎packages/mdc-textfield/README.md

+10-7
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ See [here](helper-text/) for more information on using helper text.
129129
Leading and trailing icons can be added within the default or outlined variant of MDC Text Field as visual indicators as
130130
well as interaction targets. See [here](icon/) for more information on using icons.
131131

132-
133132
### HTML5 Validation
134133

135134
`MDCTextFieldFoundation` provides validity styling by using the `:invalid` and `:required` attributes provided
@@ -237,10 +236,12 @@ Property | Value Type | Description
237236
`disabled` | boolean | Proxies to the foundation's `isDisabled`/`setDisabled` methods.
238237
`useNativeValidation` | boolean (write-only) | Proxies to the foundation's `setUseNativeValidation` method.
239238
`valid` | boolean | Proxies to the foundation's `isValid`/`setValid` methods.
240-
`helperTextContent` | string (write-only) | Proxies to the foundation's `setHelperTextContent` method when set.
241-
`iconAriaLabel` | string (write-only) | Proxies to the foundation's `setIconAriaLabel` method when set.
242-
`iconContent` | string (write-only) | Proxies to the foundation's `setIconContent` method when set.
243-
`ripple` | `MDCRipple` (read-only) | The `MDCRipple` instance for the root element that `MDCTextField` initializes; this only applies to the default Text Field, and is `null` for other variants.
239+
`helperTextContent` | string (write-only)| Proxies to the foundation's `setHelperTextContent` method when set.
240+
`ripple` | `MDCRipple` (write-only) | The `MDCRipple` instance for the root element that `MDCTextField` initializes; this only applies to the default Text Field, and is `null` for other variants.
241+
`leadingIconAriaLabel` | string (write-only) | Proxies to the foundation's `setLeadingIconAriaLabel` method.
242+
`trailingIconAriaLabel` | string (write-only) | Proxies to the foundation's `setTrailingIconAriaLabel` method.
243+
`leadingIconContent` | string (write-only) | Proxies to the foundation's `setLeadingIconContent` method.
244+
`trailingIconContent` | string (write-only) | Proxies to the foundation's `setTrailingIconContent` method.
244245

245246
In addition to the above, the following properties proxy to the `input` element's properties of the same name:
246247

@@ -304,8 +305,10 @@ Method Signature | Description
304305
`activateFocus() => void` | Activates the focus state of the Text Field. Normally called in response to the input focus event.
305306
`deactivateFocus() => void` | Deactivates the focus state of the Text Field. Normally called in response to the input blur event.
306307
`setHelperTextContent(content: string) => void` | Sets the content of the helper text.
307-
`setIconAriaLabel(label: string) => void` | Sets the aria label of the icon.
308-
`setIconContent(content: string) => void` | Sets the text content of the icon.
308+
`setLeadingIconAriaLabel(label: string) => void` | Sets the aria label of the leading icon.
309+
`setLeadingIconContent(content: string) => void` | Sets the text content of the leading icon.
310+
`setTrailingIconAriaLabel(label: string) => void` | Sets the aria label of the trailing icon.
311+
`setTrailingIconContent(content: string) => void` | Sets the text content of the trailing icon.
309312
`notchOutline(openNotch: boolean) => void` | Opens/closes the notched outline.
310313

311314
`MDCTextFieldFoundation` supports multiple optional sub-elements: helper text and icon. The foundations of these sub-elements must be passed in as constructor arguments to `MDCTextFieldFoundation`.

‎packages/mdc-textfield/_mixins.scss

+15-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,13 @@
166166
@include mdc-text-field-caret-color($mdc-text-field-error);
167167

168168
&.mdc-text-field--with-trailing-icon {
169-
@include mdc-text-field-icon-color($mdc-text-field-error);
169+
&:not(.mdc-text-field--with-leading-icon) {
170+
@include mdc-text-field-icon-color($mdc-text-field-error);
171+
}
172+
173+
&.mdc-text-field--with-leading-icon {
174+
@include mdc-text-field-icon-color($mdc-text-field-error, /* styleSecondIcon */ true);
175+
}
170176
}
171177

172178
+ .mdc-text-field-helper-text--validation-msg {
@@ -382,6 +388,14 @@
382388
@include mdc-text-field-icon-horizontal-position_(right, $mdc-text-field-dense-icon-position, $mdc-text-field-dense-icon-padding);
383389
}
384390

391+
@mixin mdc-text-field-with-both-icons_ {
392+
@include mdc-text-field-icon-horizontal-position-two-icons_($mdc-text-field-icon-position, $mdc-text-field-icon-padding, $mdc-text-field-trailing-icon-position, $mdc-text-field-icon-padding);
393+
}
394+
395+
@mixin mdc-text-field-dense-with-both-icons_ {
396+
@include mdc-text-field-icon-horizontal-position-two-icons_($mdc-text-field-dense-icon-position, $mdc-text-field-dense-icon-padding, $mdc-text-field-dense-icon-position, $mdc-text-field-dense-icon-padding);
397+
}
398+
385399
// Full Width
386400
@mixin mdc-text-field-fullwidth_ {
387401
width: 100%;

‎packages/mdc-textfield/adapter.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ let NativeInputType;
4343
/**
4444
* @typedef {{
4545
* helperText: (!MDCTextFieldHelperTextFoundation|undefined),
46-
* icon: (!MDCTextFieldIconFoundation|undefined),
46+
* leadingIcon: (!MDCTextFieldIconFoundation|undefined),
47+
* trailingIcon: (!MDCTextFieldIconFoundation|undefined),
4748
* }}
4849
*/
4950
let FoundationMapType;

‎packages/mdc-textfield/constants.js

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const cssClasses = {
4040
INVALID: 'mdc-text-field--invalid',
4141
TEXTAREA: 'mdc-text-field--textarea',
4242
OUTLINED: 'mdc-text-field--outlined',
43+
WITH_LEADING_ICON: 'mdc-text-field--with-leading-icon',
4344
};
4445

4546
/** @enum {number} */

‎packages/mdc-textfield/foundation.js

+38-11
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ class MDCTextFieldFoundation extends MDCFoundation {
110110
/** @type {!MDCTextFieldHelperTextFoundation|undefined} */
111111
this.helperText_ = foundationMap.helperText;
112112
/** @type {!MDCTextFieldIconFoundation|undefined} */
113-
this.icon_ = foundationMap.icon;
113+
this.leadingIcon_ = foundationMap.leadingIcon;
114+
/** @type {!MDCTextFieldIconFoundation|undefined} */
115+
this.trailingIcon_ = foundationMap.trailingIcon;
114116

115117
/** @private {boolean} */
116118
this.isFocused_ = false;
@@ -352,22 +354,42 @@ class MDCTextFieldFoundation extends MDCFoundation {
352354
}
353355

354356
/**
355-
* Sets the aria label of the icon.
357+
* Sets the aria label of the leading icon.
358+
* @param {string} label
359+
*/
360+
setLeadingIconAriaLabel(label) {
361+
if (this.leadingIcon_) {
362+
this.leadingIcon_.setAriaLabel(label);
363+
}
364+
}
365+
366+
/**
367+
* Sets the text content of the leading icon.
368+
* @param {string} content
369+
*/
370+
setLeadingIconContent(content) {
371+
if (this.leadingIcon_) {
372+
this.leadingIcon_.setContent(content);
373+
}
374+
}
375+
376+
/**
377+
* Sets the aria label of the trailing icon.
356378
* @param {string} label
357379
*/
358-
setIconAriaLabel(label) {
359-
if (this.icon_) {
360-
this.icon_.setAriaLabel(label);
380+
setTrailingIconAriaLabel(label) {
381+
if (this.trailingIcon_) {
382+
this.trailingIcon_.setAriaLabel(label);
361383
}
362384
}
363385

364386
/**
365-
* Sets the text content of the icon.
387+
* Sets the text content of the trailing icon.
366388
* @param {string} content
367389
*/
368-
setIconContent(content) {
369-
if (this.icon_) {
370-
this.icon_.setContent(content);
390+
setTrailingIconContent(content) {
391+
if (this.trailingIcon_) {
392+
this.trailingIcon_.setContent(content);
371393
}
372394
}
373395

@@ -432,8 +454,13 @@ class MDCTextFieldFoundation extends MDCFoundation {
432454
} else {
433455
this.adapter_.removeClass(DISABLED);
434456
}
435-
if (this.icon_) {
436-
this.icon_.setDisabled(isDisabled);
457+
458+
if (this.leadingIcon_) {
459+
this.leadingIcon_.setDisabled(isDisabled);
460+
}
461+
462+
if (this.trailingIcon_) {
463+
this.trailingIcon_.setDisabled(isDisabled);
437464
}
438465
}
439466

‎packages/mdc-textfield/icon/README.md

+40-7
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@ const icon = new MDCTextFieldIcon(document.querySelector('.mdc-text-field-icon')
4242
```
4343
## Variants
4444

45-
Leading and trailing icons can be applied to text fields styled as `mdc-text-field--box` or `mdc-text-field--outlined`. To add an icon, add the relevant class (either `mdc-text-field--with-leading-icon` or `mdc-text-field--with-trailing-icon`) to the root element, add an `i` element with your preferred icon, and give it a class of `mdc-text-field__icon`.
45+
Leading and trailing icons can be applied to default or `mdc-text-field--outlined` Text Fields. To add an icon, add the relevant class (`mdc-text-field--with-leading-icon` and/or `mdc-text-field--with-trailing-icon`) to the root element, add an `i` element with your preferred icon, and give it a class of `mdc-text-field__icon`. If using 2 icons at the same time, the first icon inside the `mdc-text-field` element will be interpreted as the leading icon and the second icon will be interpreted as the trailing icon.
46+
47+
> **NOTE:** if you would like to display un-clickable icons, simply omit `tabindex="0"` and `role="button"`, and the CSS will ensure the cursor is set to default, and that interacting with an icon doesn't do anything unexpected.
4648
4749
### Leading icon
4850

49-
In text field box:
51+
In text field:
52+
5053
```html
5154
<div class="mdc-text-field mdc-text-field--with-leading-icon">
5255
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">event</i>
@@ -57,6 +60,7 @@ In text field box:
5760
```
5861

5962
In outlined text field:
63+
6064
```html
6165
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon">
6266
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">event</i>
@@ -73,7 +77,8 @@ In outlined text field:
7377

7478
### Trailing icon
7579

76-
In text field box:
80+
In text field:
81+
7782
```html
7883
<div class="mdc-text-field mdc-text-field--with-trailing-icon">
7984
<input type="text" id="my-input" class="mdc-text-field__input">
@@ -84,6 +89,7 @@ In text field box:
8489
```
8590

8691
In outlined text field:
92+
8793
```html
8894
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-trailing-icon">
8995
<input type="text" id="my-input" class="mdc-text-field__input">
@@ -98,9 +104,36 @@ In outlined text field:
98104
</div>
99105
```
100106

101-
>**NOTE:** if you would like to display un-clickable icons, simply remove `tabindex="0"` and `role="button"`,
102-
and the CSS will ensure the cursor is set to default, and that interacting with an icon doesn't
103-
do anything unexpected.
107+
### Leading and Trailing icons
108+
109+
In text field:
110+
111+
```html
112+
<div class="mdc-text-field mdc-text-field--with-leading-icon mdc-text-field--with-trailing-icon">
113+
<i class="material-icons mdc-text-field__icon">phone</i>
114+
<input type="text" id="my-input" class="mdc-text-field__input">
115+
<label for="my-input" class="mdc-floating-label">Phone Number</label>
116+
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">event</i>
117+
<div class="mdc-line-ripple"></div>
118+
</div>
119+
```
120+
121+
In outlined text field:
122+
123+
```html
124+
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon mdc-text-field--with-trailing-icon">
125+
<i class="material-icons mdc-text-field__icon">phone</i>
126+
<input type="text" id="my-input" class="mdc-text-field__input">
127+
<label for="my-input" class="mdc-floating-label">Phone Number</label>
128+
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">clear</i>
129+
<div class="mdc-notched-outline">
130+
<svg>
131+
<path class="mdc-notched-outline__path"/>
132+
</svg>
133+
</div>
134+
<div class="mdc-notched-outline__idle"></div>
135+
</div>
136+
```
104137

105138
## Style Customization
106139

@@ -114,7 +147,7 @@ CSS Class | Description
114147

115148
Mixin | Description
116149
--- | ---
117-
`mdc-text-field-icon-color($color)` | Customizes the color for the leading/trailing icons.
150+
`mdc-text-field-icon-color($color, $styleSecondIcon: false)` | Customizes the color for the leading/trailing icons. If the `$styleSecondIcon` is `true` it will output the color to only apply to a trailing icon when used with a leading icon.
118151

119152
## `MDCTextFieldIcon` Properties and Methods
120153

‎packages/mdc-textfield/icon/_mixins.scss

+33-6
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222

2323
// Public mixins
2424

25-
@mixin mdc-text-field-icon-color($color) {
25+
@mixin mdc-text-field-icon-color($color, $styleSecondIcon: false) {
2626
&:not(.mdc-text-field--disabled) {
27-
@include mdc-text-field-icon-color_($color);
27+
@include mdc-text-field-icon-color_($color, $styleSecondIcon);
2828
}
2929
}
3030

@@ -46,17 +46,44 @@
4646
}
4747
}
4848

49-
// Only move the label's position to allow room for the icon, if the icon is on the same
50-
// side as the label. Aka the icon is on left side in a LTR context.
49+
// Only move the label's position to allow room for the icon, if the icon is on the same side as the label.
50+
// E.g., the icon is on left side in LTR context.
5151
@if ($position-property == left) {
5252
.mdc-floating-label {
5353
@include mdc-rtl-reflexive-position($position-property, $padding);
5454
}
5555
}
5656
}
5757

58-
@mixin mdc-text-field-icon-color_($color) {
58+
@mixin mdc-text-field-icon-horizontal-position-two-icons_($position-left, $padding-left, $position-right, $padding-right) {
5959
.mdc-text-field__icon {
60-
@include mdc-theme-prop(color, $color);
60+
@include mdc-rtl-reflexive(left, $position-left, right, auto);
61+
62+
~ .mdc-text-field__icon {
63+
@include mdc-rtl-reflexive(right, $position-right, left, auto);
64+
}
65+
}
66+
67+
// Move the input's position, to allow room for the icons.
68+
.mdc-text-field__input {
69+
@include mdc-rtl-reflexive-property(padding, $padding-left, $padding-right);
70+
}
71+
72+
// Only move the label's position to allow room for the icon, if the icon is on the same
73+
// side as the label. Aka the icon is on left side in a LTR context.
74+
.mdc-floating-label {
75+
@include mdc-rtl-reflexive(left, $padding-left, right, auto);
76+
}
77+
}
78+
79+
@mixin mdc-text-field-icon-color_($color, $styleSecondIcon: false) {
80+
.mdc-text-field__icon {
81+
@if ($styleSecondIcon) {
82+
~ .mdc-text-field__icon { // Selects the second instance of this class regardless of element type.
83+
@include mdc-theme-prop(color, $color);
84+
}
85+
} @else {
86+
@include mdc-theme-prop(color, $color);
87+
}
6188
}
6289
}

0 commit comments

Comments
 (0)