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

Commit

Permalink
feat(text-field): Add support for leading/trailing icons at the same …
Browse files Browse the repository at this point in the history
…time (#3451)

BREAKING CHANGE: Component API's for interacting with icons has changed. Please refer to the documentation.
  • Loading branch information
williamernest authored Sep 12, 2018
1 parent 6b6370d commit 6b3cfe5
Show file tree
Hide file tree
Showing 18 changed files with 872 additions and 64 deletions.
17 changes: 10 additions & 7 deletions packages/mdc-textfield/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ See [here](helper-text/) for more information on using helper text.
Leading and trailing icons can be added within the default or outlined variant of MDC Text Field as visual indicators as
well as interaction targets. See [here](icon/) for more information on using icons.


### HTML5 Validation

`MDCTextFieldFoundation` provides validity styling by using the `:invalid` and `:required` attributes provided
Expand Down Expand Up @@ -237,10 +236,12 @@ Property | Value Type | Description
`disabled` | boolean | Proxies to the foundation's `isDisabled`/`setDisabled` methods.
`useNativeValidation` | boolean (write-only) | Proxies to the foundation's `setUseNativeValidation` method.
`valid` | boolean | Proxies to the foundation's `isValid`/`setValid` methods.
`helperTextContent` | string (write-only) | Proxies to the foundation's `setHelperTextContent` method when set.
`iconAriaLabel` | string (write-only) | Proxies to the foundation's `setIconAriaLabel` method when set.
`iconContent` | string (write-only) | Proxies to the foundation's `setIconContent` method when set.
`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.
`helperTextContent` | string (write-only)| Proxies to the foundation's `setHelperTextContent` method when set.
`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.
`leadingIconAriaLabel` | string (write-only) | Proxies to the foundation's `setLeadingIconAriaLabel` method.
`trailingIconAriaLabel` | string (write-only) | Proxies to the foundation's `setTrailingIconAriaLabel` method.
`leadingIconContent` | string (write-only) | Proxies to the foundation's `setLeadingIconContent` method.
`trailingIconContent` | string (write-only) | Proxies to the foundation's `setTrailingIconContent` method.

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

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

`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`.
16 changes: 15 additions & 1 deletion packages/mdc-textfield/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,13 @@
@include mdc-text-field-caret-color($mdc-text-field-error);

&.mdc-text-field--with-trailing-icon {
@include mdc-text-field-icon-color($mdc-text-field-error);
&:not(.mdc-text-field--with-leading-icon) {
@include mdc-text-field-icon-color($mdc-text-field-error);
}

&.mdc-text-field--with-leading-icon {
@include mdc-text-field-icon-color($mdc-text-field-error, /* styleSecondIcon */ true);
}
}

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

@mixin mdc-text-field-with-both-icons_ {
@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);
}

@mixin mdc-text-field-dense-with-both-icons_ {
@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);
}

// Full Width
@mixin mdc-text-field-fullwidth_ {
width: 100%;
Expand Down
3 changes: 2 additions & 1 deletion packages/mdc-textfield/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ let NativeInputType;
/**
* @typedef {{
* helperText: (!MDCTextFieldHelperTextFoundation|undefined),
* icon: (!MDCTextFieldIconFoundation|undefined),
* leadingIcon: (!MDCTextFieldIconFoundation|undefined),
* trailingIcon: (!MDCTextFieldIconFoundation|undefined),
* }}
*/
let FoundationMapType;
Expand Down
1 change: 1 addition & 0 deletions packages/mdc-textfield/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const cssClasses = {
INVALID: 'mdc-text-field--invalid',
TEXTAREA: 'mdc-text-field--textarea',
OUTLINED: 'mdc-text-field--outlined',
WITH_LEADING_ICON: 'mdc-text-field--with-leading-icon',
};

/** @enum {number} */
Expand Down
49 changes: 38 additions & 11 deletions packages/mdc-textfield/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ class MDCTextFieldFoundation extends MDCFoundation {
/** @type {!MDCTextFieldHelperTextFoundation|undefined} */
this.helperText_ = foundationMap.helperText;
/** @type {!MDCTextFieldIconFoundation|undefined} */
this.icon_ = foundationMap.icon;
this.leadingIcon_ = foundationMap.leadingIcon;
/** @type {!MDCTextFieldIconFoundation|undefined} */
this.trailingIcon_ = foundationMap.trailingIcon;

/** @private {boolean} */
this.isFocused_ = false;
Expand Down Expand Up @@ -352,22 +354,42 @@ class MDCTextFieldFoundation extends MDCFoundation {
}

/**
* Sets the aria label of the icon.
* Sets the aria label of the leading icon.
* @param {string} label
*/
setLeadingIconAriaLabel(label) {
if (this.leadingIcon_) {
this.leadingIcon_.setAriaLabel(label);
}
}

/**
* Sets the text content of the leading icon.
* @param {string} content
*/
setLeadingIconContent(content) {
if (this.leadingIcon_) {
this.leadingIcon_.setContent(content);
}
}

/**
* Sets the aria label of the trailing icon.
* @param {string} label
*/
setIconAriaLabel(label) {
if (this.icon_) {
this.icon_.setAriaLabel(label);
setTrailingIconAriaLabel(label) {
if (this.trailingIcon_) {
this.trailingIcon_.setAriaLabel(label);
}
}

/**
* Sets the text content of the icon.
* Sets the text content of the trailing icon.
* @param {string} content
*/
setIconContent(content) {
if (this.icon_) {
this.icon_.setContent(content);
setTrailingIconContent(content) {
if (this.trailingIcon_) {
this.trailingIcon_.setContent(content);
}
}

Expand Down Expand Up @@ -432,8 +454,13 @@ class MDCTextFieldFoundation extends MDCFoundation {
} else {
this.adapter_.removeClass(DISABLED);
}
if (this.icon_) {
this.icon_.setDisabled(isDisabled);

if (this.leadingIcon_) {
this.leadingIcon_.setDisabled(isDisabled);
}

if (this.trailingIcon_) {
this.trailingIcon_.setDisabled(isDisabled);
}
}

Expand Down
47 changes: 40 additions & 7 deletions packages/mdc-textfield/icon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ const icon = new MDCTextFieldIcon(document.querySelector('.mdc-text-field-icon')
```
## Variants

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`.
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.

> **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.
### Leading icon

In text field box:
In text field:

```html
<div class="mdc-text-field mdc-text-field--with-leading-icon">
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">event</i>
Expand All @@ -57,6 +60,7 @@ In text field box:
```

In outlined text field:

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

### Trailing icon

In text field box:
In text field:

```html
<div class="mdc-text-field mdc-text-field--with-trailing-icon">
<input type="text" id="my-input" class="mdc-text-field__input">
Expand All @@ -84,6 +89,7 @@ In text field box:
```

In outlined text field:

```html
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-trailing-icon">
<input type="text" id="my-input" class="mdc-text-field__input">
Expand All @@ -98,9 +104,36 @@ In outlined text field:
</div>
```

>**NOTE:** if you would like to display un-clickable icons, simply remove `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.
### Leading and Trailing icons

In text field:

```html
<div class="mdc-text-field mdc-text-field--with-leading-icon mdc-text-field--with-trailing-icon">
<i class="material-icons mdc-text-field__icon">phone</i>
<input type="text" id="my-input" class="mdc-text-field__input">
<label for="my-input" class="mdc-floating-label">Phone Number</label>
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">event</i>
<div class="mdc-line-ripple"></div>
</div>
```

In outlined text field:

```html
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon mdc-text-field--with-trailing-icon">
<i class="material-icons mdc-text-field__icon">phone</i>
<input type="text" id="my-input" class="mdc-text-field__input">
<label for="my-input" class="mdc-floating-label">Phone Number</label>
<i class="material-icons mdc-text-field__icon" tabindex="0" role="button">clear</i>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"/>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
```

## Style Customization

Expand All @@ -114,7 +147,7 @@ CSS Class | Description

Mixin | Description
--- | ---
`mdc-text-field-icon-color($color)` | Customizes the color for the leading/trailing icons.
`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.

## `MDCTextFieldIcon` Properties and Methods

Expand Down
39 changes: 33 additions & 6 deletions packages/mdc-textfield/icon/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@

// Public mixins

@mixin mdc-text-field-icon-color($color) {
@mixin mdc-text-field-icon-color($color, $styleSecondIcon: false) {
&:not(.mdc-text-field--disabled) {
@include mdc-text-field-icon-color_($color);
@include mdc-text-field-icon-color_($color, $styleSecondIcon);
}
}

Expand All @@ -46,17 +46,44 @@
}
}

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

@mixin mdc-text-field-icon-color_($color) {
@mixin mdc-text-field-icon-horizontal-position-two-icons_($position-left, $padding-left, $position-right, $padding-right) {
.mdc-text-field__icon {
@include mdc-theme-prop(color, $color);
@include mdc-rtl-reflexive(left, $position-left, right, auto);

~ .mdc-text-field__icon {
@include mdc-rtl-reflexive(right, $position-right, left, auto);
}
}

// Move the input's position, to allow room for the icons.
.mdc-text-field__input {
@include mdc-rtl-reflexive-property(padding, $padding-left, $padding-right);
}

// Only move the label's position to allow room for the icon, if the icon is on the same
// side as the label. Aka the icon is on left side in a LTR context.
.mdc-floating-label {
@include mdc-rtl-reflexive(left, $padding-left, right, auto);
}
}

@mixin mdc-text-field-icon-color_($color, $styleSecondIcon: false) {
.mdc-text-field__icon {
@if ($styleSecondIcon) {
~ .mdc-text-field__icon { // Selects the second instance of this class regardless of element type.
@include mdc-theme-prop(color, $color);
}
} @else {
@include mdc-theme-prop(color, $color);
}
}
}
Loading

0 comments on commit 6b3cfe5

Please sign in to comment.