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): Added support for character counter. (#4244)
Browse files Browse the repository at this point in the history
  • Loading branch information
abhiomkar authored Jan 31, 2019
1 parent 4bc18d1 commit 0bcc0e7
Show file tree
Hide file tree
Showing 50 changed files with 1,728 additions and 374 deletions.
56 changes: 54 additions & 2 deletions packages/mdc-textfield/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,58 @@ Add class name `mdc-text-field--no-label` and remove the label element from the
### Text Field with Helper Text

The helper text provides supplemental information and/or validation messages to users. It appears on input field focus
and disappears on input field blur by default, or it can be persistent.
See [here](helper-text/) for more information on using helper text.
and disappears on input field blur by default, or it can be persistent. Helper text should be rendered inside `.mdc-text-field-helper-line` element
which is immediate sibling of `.mdc-text-field`. See [here](helper-text/) for more information on using helper text.

```html
<div class="mdc-text-field">
<input type="text" id="my-text-field" class="mdc-text-field__input">
<label class="mdc-floating-label" for="my-text-field">My Label</label>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-text-field-helper-line">
<div class="mdc-text-field-helper-text">helper text</div>
</div>
```

### Text Field with Character Counter

Character counter is used if there is a character limit. It displays the ratio of characters used and the total character limit.
Helper text should be rendered inside `.mdc-text-field-helper-line` element which is immediate sibling of `.mdc-text-field`.
See [here](character-counter/) for more information on using character counter.

```html
<div class="mdc-text-field">
<input type="text" id="my-text-field" class="mdc-text-field__input" maxlength="10">
<label class="mdc-floating-label" for="my-text-field">My Label</label>
<div class="mdc-line-ripple"></div>
</div>
<div class="mdc-text-field-helper-line">

This comment has been minimized.

Copy link
@jamesmfriedman

jamesmfriedman Feb 7, 2019

Contributor

This is a breaking change that wasn't communicated anywhere! All existing helper text no longer works unless its wrapped.

<div class="mdc-text-field-character-counter">0 / 10</div>
</div>
```

### Multi-line Text Field (Textarea) with Character Counter

The layout structure of character counter for multi-line text field (textarea) is slightly different since it is rendered
inside of text field component.

```html
<div class="mdc-text-field mdc-text-field--textarea">
<div class="mdc-text-field-character-counter">0 / 140</div>
<textarea id="textarea" class="mdc-text-field__input" rows="8" cols="40" maxlength="140"></textarea>
<div class="mdc-notched-outline">
<div class="mdc-notched-outline__leading"></div>
<div class="mdc-notched-outline__notch">
<label for="textarea" class="mdc-floating-label">Textarea Label</label>
</div>
<div class="mdc-notched-outline__trailing"></div>
</div>
</div>
```

Helper text and Character counter are optional subcomponents of text field that can co-exist independently.
It is recommended that `.mdc-text-field` and `.mdc-text-field-helper-line` elements have same width for correct layout.

### Text Field with Leading and Trailing Icons

Expand Down Expand Up @@ -221,6 +271,7 @@ CSS Class | Description
`mdc-text-field--with-trailing-icon` | Styles the text field as a text field with a trailing icon.
`mdc-text-field--focused` | Styles the text field as a text field in focus.
`mdc-text-field--no-label` | Styles the text field that has no label.
`mdc-text-field-helper-line` | Styles the container of helper text and character counter elements.

#### Deprecation Notice

Expand Down Expand Up @@ -351,6 +402,7 @@ Method Signature | Description
`isDisabled() => boolean` | Returns whether or not the input is disabled.
`setDisabled(disabled: boolean) => void` | Updates the input's disabled state.
`handleTextFieldInteraction(evt: Event) => void` | Handles click and keydown events originating from inside the Text Field component.
`handleInput() => void` | Handles text input and textarea input event.
`handleValidationAttributeChange(attributesList: !Array<string>) => void` | Handles validation attribute changes.
`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.
Expand Down
16 changes: 12 additions & 4 deletions packages/mdc-textfield/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
@import "@material/shape/mixins";
@import "@material/shape/functions";
@import "helper-text/mixins";
@import "character-counter/mixins";
@import "icon/mixins";
@import "icon/variables";
@import "./variables";
Expand Down Expand Up @@ -134,6 +135,7 @@
@include mdc-text-field-ink-color_($mdc-text-field-disabled-ink-color);
@include mdc-text-field-label-ink-color_($mdc-text-field-disabled-label-color);
@include mdc-text-field-helper-text-color_($mdc-text-field-disabled-helper-text-color);
@include mdc-text-field-character-counter-color_($mdc-text-field-disabled-helper-text-color);
@include mdc-text-field-icon-color_($mdc-text-field-disabled-icon);
@include mdc-text-field-fullwidth-bottom-line-color_($mdc-text-field-fullwidth-bottom-line-color);
@include mdc-text-field-fill-color_($mdc-text-field-disabled-background);
Expand Down Expand Up @@ -164,7 +166,7 @@
}
}

+ .mdc-text-field-helper-text--validation-msg {
+ .mdc-text-field-helper-line .mdc-text-field-helper-text--validation-msg {
opacity: 1;
}
}
Expand All @@ -176,7 +178,7 @@
@include mdc-theme-prop(color, $mdc-text-field-error);
}

+ .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg) {
+ .mdc-text-field-helper-line .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg) {
opacity: 1;
}
}
Expand Down Expand Up @@ -221,8 +223,8 @@
@include mdc-rtl-reflexive-property(padding, $radius-pixels + $mdc-notched-outline-padding, 0);
}

+ .mdc-text-field-helper-text {
@include mdc-rtl-reflexive-property(margin, $radius-pixels + $mdc-notched-outline-padding, $mdc-text-field-label-offset);
+ .mdc-text-field-helper-line {
@include mdc-rtl-reflexive-property(padding, $radius-pixels + $mdc-notched-outline-padding, $radius-pixels);
}
}
}
Expand Down Expand Up @@ -456,6 +458,7 @@
@include mdc-states-base-color(transparent);
@include mdc-text-field-fill-color(transparent);
@include mdc-notched-outline-floating-label-float-position($mdc-text-field-outlined-label-position-y, 0%);
@include mdc-text-field-character-counter-position(16px, 13px);

$padding-inset: 16px;

Expand All @@ -474,6 +477,11 @@
border: none;
}

.mdc-text-field-character-counter + .mdc-text-field__input {
margin-bottom: 28px; // Leaves space for character counter if it exists.
padding-bottom: 0;
}

.mdc-floating-label {
top: 17px;
bottom: auto;
Expand Down
1 change: 1 addition & 0 deletions packages/mdc-textfield/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ $mdc-text-field-outlined-dense-label-position-y: 120% !default;
$mdc-text-field-outlined-with-leading-icon-label-position-x: 0 !default;
$mdc-text-field-outlined-dense-with-leading-icon-label-position-x: 21px !default;
$mdc-text-field-textarea-label-position-y: 130% !default;
$mdc-text-field-helper-line-padding: 16px;
// Note that the scale factor is an eyeballed approximation of what's shown in the mocks.
3 changes: 3 additions & 0 deletions packages/mdc-textfield/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

/* eslint-disable no-unused-vars */
import MDCTextFieldHelperTextFoundation from './helper-text/foundation';
/* eslint-disable no-unused-vars */
import MDCTextFieldCharacterCounterFoundation from './character-counter/foundation';
import MDCTextFieldIconFoundation from './icon/foundation';

/* eslint no-unused-vars: [2, {"args": "none"}] */
Expand All @@ -43,6 +45,7 @@ let NativeInputType;
/**
* @typedef {{
* helperText: (!MDCTextFieldHelperTextFoundation|undefined),
* characterCounter: (!MDCTextFieldCharacterCounterFoundation|undefined),
* leadingIcon: (!MDCTextFieldIconFoundation|undefined),
* trailingIcon: (!MDCTextFieldIconFoundation|undefined),
* }}
Expand Down
82 changes: 82 additions & 0 deletions packages/mdc-textfield/character-counter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<!--docs:
title: "Text Field Character Counter"
layout: detail
section: components
excerpt: "Character counter displays the ratio of characters used and the total character limit"
iconId: text_field
path: /catalog/input-controls/text-field/character-counter/
-->

# Text Field Character Counter

Character counter is used if there is a character limit. It displays the ratio of characters used and the total character limit.

## Design & API Documentation

<ul class="icon-list">
<li class="icon-list-item icon-list-item--spec">
<a href="https://material.io/go/design-text-fields#text-fields-layout">Material Design guidelines: Text Fields Layout</a>
</li>
</ul>

## Basic Usage

### HTML Structure

```html
<div class="mdc-text-field-character-counter">0 / 140</div>
```

> NOTE: Place this inside `.mdc-text-field-helper-line` for single line mdc text field which is an immediate sibling of `.mdc-text-field` and
> place it as first element of `.mdc-text-field` for multi-line text field variant (textarea).
### Styles

```scss
@import "@material/textfield/character-counter/mdc-text-field-character-counter";
```

### JavaScript Instantiation

```js
import {MDCTextFieldCharacterCounter} from '@material/textfield/character-counter';

const characterCounter = new MDCTextFieldCharacterCounter(document.querySelector('.mdc-text-field-character-counter'));
```

## Style Customization

### CSS Classes

CSS Class | Description
--- | ---
`mdc-text-field-character-counter` | Mandatory.

### Sass Mixins

Mixin | Description
--- | ---
`mdc-text-field-character-counter-color($color)` | Customizes the color of the character counter associated with text field.
`mdc-text-field-character-counter-position($xOffset, $yOffset)` | Positions the character counter element inside text field. Used only for textarea variant.

## `MDCTextFieldCharacterCounter` Properties and Methods

Property | Value Type | Description
--- | --- | ---
`foundation` | `MDCTextFieldCharacterCounterFoundation` | Returns the character counter's foundation. This allows the parent `MDCTextField` component to access the public methods on the `MDCTextFieldCharacterCounterFoundation` class.

## Usage Within Frameworks

If you are using a JavaScript framework, such as React or Angular, you can create a Character Counter for your framework. Depending on your needs, you can use the _Simple Approach: Wrapping MDC Web Vanilla Components_, or the _Advanced Approach: Using Foundations and Adapters_. Please follow the instructions [here](../../../docs/integrating-into-frameworks.md).

### `MDCTextFieldCharacterCounterAdapter`

Method Signature | Description
--- | ---
`setContent(content: string) => void` | Sets the text content of character counter element.

### `MDCTextFieldCharacterCounterFoundation`

Method Signature | Description
--- | ---
`setCounterValue(currentLength: number, maxLength: number) => void` | Sets the character counter values including characters used and total character limit.
51 changes: 51 additions & 0 deletions packages/mdc-textfield/character-counter/_mixins.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Copyright 2019 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

@import "@material/rtl/mixins";

// Public mixins

@mixin mdc-text-field-character-counter-color($color) {
&:not(.mdc-text-field--disabled) {
@include mdc-text-field-character-counter-color_($color);
}
}

@mixin mdc-text-field-character-counter-position($xOffset, $yOffset) {
.mdc-text-field-character-counter {
@include mdc-rtl-reflexive-position(right, $xOffset);

position: absolute;
bottom: $yOffset;
}
}

// Private mixins

@mixin mdc-text-field-character-counter-color_($color) {
// Character counter is placed inside mdc-textfield element (for textarea variant ) or
// inside helper line which is sibling to mdc-textfield.
.mdc-text-field-character-counter,
+ .mdc-text-field-helper-line .mdc-text-field-character-counter {
@include mdc-theme-prop(color, $color);
}
}
44 changes: 44 additions & 0 deletions packages/mdc-textfield/character-counter/adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @license
* Copyright 2019 Google Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/* eslint no-unused-vars: [2, {"args": "none"}] */

/**
* Adapter for MDC Text Field Character Counter.
*
* Defines the shape of the adapter expected by the foundation. Implement this
* adapter to integrate the TextField character counter into your framework. See
* https://github.com/material-components/material-components-web/blob/master/docs/authoring-components.md
* for more information.
*
* @record
*/
class MDCTextFieldCharacterCounterAdapter {
/**
* Sets the text content of character counter element.
* @param {string} content
*/
setContent(content) {}
}

export default MDCTextFieldCharacterCounterAdapter;
34 changes: 34 additions & 0 deletions packages/mdc-textfield/character-counter/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @license
* Copyright 2019 Google Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/** @enum {string} */
const cssClasses = {
ROOT: 'mdc-text-field-character-counter',
};

/** @enum {string} */
const strings = {
ROOT_SELECTOR: `.${cssClasses.ROOT}`,
};

export {strings, cssClasses};
Loading

0 comments on commit 0bcc0e7

Please sign in to comment.