feat(MdInput): README.md improvements and autofill support.

* Change the CSS to allow for autofill reactions; it works!
* Add a lot of examples and information to the README.md
* Add support for `warn` color to the labels.
This commit is contained in:
Hans Larsen
2016-03-31 14:52:00 -07:00
parent 5a6657a4fb
commit b711c2b673
7 changed files with 239 additions and 42 deletions
+83 -4
View File
@@ -2,7 +2,10 @@
Inputs are the basic input component of Material 2. The spec can be found [here](https://www.google.com/design/spec/components/text-fields.html).
### Screenshots
## Notes
* The `<md-input>` component fully support two-way binding of `ngModel`, as if it was a normal `<input>`.
@@ -12,22 +15,27 @@ At the time of writing this README, the `[type]` attribute is copied to the actu
The valid `type` attribute values are any supported by your browser, with the exception of `file`, `checkbox` and `radio`. File inputs aren't supported for now, while check boxes and radio buttons have their own components.
## Prefix and Suffix
You can include HTML before, and after the input tag, as prefix or suffix. It will be underlined as per the Material specification, and clicking it will focus the input.
To add a prefix, use the `md-prefix` attribute on the element. Similarly, to add a suffix, use the `md-suffix` attribute. For example, in a template:
#### Example
```html
<md-input type="number" placeholder="amount">
<span md-prefix>$</span>
<md-input placeholder="amount" align="end">
<span md-prefix>$&nbsp;</span>
<span md-suffix>.00</span>
</md-input>
```
Will result in this:
!!!! INSERT SCREENSHOT HERE.
<img src="https://material.angularjs.org/material2_assets/input/prefix-suffix.png">
## Hint Labels
@@ -38,5 +46,76 @@ You specify a hint-label in one of two ways; either using the `hintLabel` attrib
Specifying a side twice will result in an exception during initialization.
#### Example
A simple character counter can be made like the following:
```html
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
value="Hello world. How are you?"
#characterCountHintExample>
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
</md-input>
```
<img src="https://material.angularjs.org/material2_assets/input/character-count.png">
## Divider Color
The divider (line under the <md-input> content) color can be changed by using the `dividerColor` attribute. A value of `primary` is the default and will correspond to your theme primary color. Alternatively, you can specify `accent` or `warn`.
#### Example
^((please not that this example has been doctored to show the colors; they would normally show only on focus)^)
<img src="https://material.angularjs.org/material2_assets/input/divider-colors.png">
## Labelling
You can label the `<md-input>` as you would a regular `<input>`.
## Full Forms
You can make a full form using inputs, and it will support autofill natively.
#### Example
```html
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Basic</md-toolbar>
<md-card-content>
<form>
<md-input class="demo-full-width" placeholder="Company (disabled)" disabled value="Google">
</md-input>
<table style="width: 100%" cellspacing="0"><tr>
<td><md-input placeholder="First name" style="width: 100%"></md-input></td>
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
</tr></table>
<p>
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
</p>
<table style="width: 100%" cellspacing="0"><tr>
<td><md-input class="demo-full-width" placeholder="City"></md-input></td>
<td><md-input class="demo-full-width" placeholder="State"></md-input></td>
<td><md-input #postalCode class="demo-full-width" maxLength="5"
placeholder="Postal Code"
value="94043">
<md-hint align="end">{{postalCode.characterCount}} / 5</md-hint>
</md-input></td>
</tr></table>
</form>
</md-card-content>
</md-card>
```
Will result in this:
<img src="https://material.angularjs.org/material2_assets/input/full-form.png">
+33 -29
View File
@@ -2,35 +2,38 @@
<div class="md-input-table">
<div class="md-input-prefix"><ng-content select="[md-prefix]"></ng-content></div>
<label class="md-input-placeholder"
[attr.for]="id"
[class.md-empty]="empty"
[class.md-focused]="focused"
[class.md-float]="floatingPlaceholder"
[class.md-accent]="dividerColor == 'accent'"
*ngIf="hasPlaceholder()">
<ng-content select="md-placeholder"></ng-content>
{{placeholder}}
<span class="md-placeholder-required" *ngIf="required">*</span>
</label>
<div class="md-input-infix">
<input #input
aria-target
class="md-input-element"
[class.md-end]="align == 'end'"
[attr.aria-label]="ariaLabel"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-disabled]="ariaDisabled"
[attr.aria-required]="ariaRequired"
[attr.aria-invalid]="ariaInvalid"
[id]="id"
[disabled]="disabled"
[required]="required"
[attr.maxlength]="maxLength"
[type]="type"
(focus)="onFocus()"
(blur)="onBlur()"
[(ngModel)]="value">
<input #input
aria-target
class="md-input-element"
[class.md-end]="align == 'end'"
[attr.aria-label]="ariaLabel"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-disabled]="ariaDisabled"
[attr.aria-required]="ariaRequired"
[attr.aria-invalid]="ariaInvalid"
[id]="id"
[disabled]="disabled"
[required]="required"
[attr.maxlength]="maxLength"
[type]="type"
(focus)="onFocus()"
(blur)="onBlur()"
[(ngModel)]="value">
<label class="md-input-placeholder"
[attr.for]="id"
[class.md-empty]="empty"
[class.md-focused]="focused"
[class.md-float]="floatingPlaceholder"
[class.md-accent]="dividerColor == 'accent'"
[class.md-warn]="dividerColor == 'warn'"
*ngIf="hasPlaceholder()">
<ng-content select="md-placeholder"></ng-content>
{{placeholder}}
<span class="md-placeholder-required" *ngIf="required">*</span>
</label>
</div>
<div class="md-input-suffix"><ng-content select="[md-suffix]"></ng-content></div>
</div>
@@ -39,7 +42,8 @@
[class.md-disabled]="disabled">
<span class="md-input-ripple"
[class.md-focused]="focused"
[class.md-accent]="dividerColor == 'accent'"></span>
[class.md-accent]="dividerColor == 'accent'"
[class.md-warn]="dividerColor == 'warn'"></span>
</div>
<div *ngIf="hintLabel != ''" class="md-hint">{{hintLabel}}</div>
+51 -7
View File
@@ -11,6 +11,7 @@ $md-input-required-placeholder-color: md-color($md-accent);
// Underline colors.
$md-input-underline-color: md-color($md-foreground, hint-text);
$md-input-underline-color-accent: md-color($md-accent);
$md-input-underline-color-warn: md-color($md-warn);
$md-input-underline-disabled-color: md-color($md-foreground, hint-text);
$md-input-underline-focused-color: md-color($md-primary);
@@ -18,11 +19,29 @@ $md-input-underline-focused-color: md-color($md-primary);
$md-input-underline-disabled-background-image: linear-gradient(to right,
rgba(0,0,0,0.26) 0%, rgba(0,0,0,0.26) 33%, transparent 0%);
/**
* Applies a floating placeholder above the input itself.
*/
%md-input-placeholder-floating {
visibility: visible;
padding-bottom: 5px;
transform: translateY(-100%) scale(0.75);
.md-placeholder-required {
color: $md-input-required-placeholder-color;
}
}
:host {
display: inline-block;
position: relative;
font-family: $md-font-family;
// To avoid problems with text-align.
text-align: left;
// Global wrapper. We need to apply margin to the element for spacing, but
// cannot apply it to the host element directly.
.md-input-wrapper {
@@ -61,18 +80,32 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
}
}
.md-input-infix {
position: relative;
}
// The placeholder label. This is invisible unless it is. The logic to show it is
// basically `empty || (float && (!empty || focused))`. Float is dependent on the
// `floatingPlaceholder` input.
.md-input-placeholder {
// The placeholder is after the <input>, but needs to be aligned top-left of the
// infix <div>.
position: absolute;
left: 0;
top: 0;
visibility: hidden;
font-size: 100%;
pointer-events: none; // We shouldn't catch mouse events (let them through).
color: $md-input-placeholder-color;
z-index: 1;
// Put ellipsis text overflow.
width: 100%;
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow-x: hidden;
transform: translateY(0);
transform-origin: bottom left;
@@ -87,13 +120,7 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
// Show the placeholder above the input when it's not empty, or focused.
&.md-float:not(.md-empty), &.md-float.md-focused {
visibility: visible;
padding-bottom: 5px;
transform: translateY(-100%) scale(0.75);
.md-placeholder-required {
color: $md-input-required-placeholder-color;
}
@extend %md-input-placeholder-floating;
}
// :focus is applied to the input, but we apply md-focused to the other elements
@@ -104,9 +131,21 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
&.md-accent {
color: $md-input-underline-color-accent;
}
&.md-warn {
color: $md-input-underline-color-warn;
}
}
}
// Pseudo-class for Chrome and Safari auto-fill to move the placeholder to
// the floating position. This is necessary because these browsers do not actually
// fire any events when a form auto-fill is occurring.
// Once the autofill is committed, a change event happen and the regular md-input
// classes take over to fulfill this behaviour.
input:-webkit-autofill + .md-input-placeholder {
@extend %md-input-placeholder-floating;
}
// The underline is what's shown under the input, its prefix and its suffix.
// The ripple is the blue animation coming on top of it.
.md-input-underline {
@@ -140,6 +179,9 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
&.md-accent {
background-color: $md-input-underline-color-accent;
}
&.md-warn {
background-color: $md-input-underline-color-warn;
}
&.md-focused {
opacity: 1;
@@ -164,6 +206,8 @@ $md-input-underline-disabled-background-image: linear-gradient(to right,
// RTL support.
:host-context([dir="rtl"]) {
text-align: right;
.md-input-placeholder {
transform-origin: bottom right;
}
+1 -1
View File
@@ -131,7 +131,7 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
*/
@Input() @OneOf(['start', 'end']) align: string = 'start';
@Input() @BooleanFieldValue() disabled: boolean = false;
@Input() @OneOf(['primary', 'accent']) dividerColor: string = 'primary';
@Input() @OneOf(['primary', 'accent', 'warn']) dividerColor: string = 'primary';
@Input() @BooleanFieldValue() floatingPlaceholder: boolean = true;
@Input() hintLabel: string = '';
@Input() id: string = `md-input-${nextUniqueId++}`;
+60
View File
@@ -1,3 +1,63 @@
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Basic</md-toolbar>
<md-card-content>
<form>
<md-input class="demo-full-width" placeholder="Company (disabled)" disabled value="Google">
</md-input>
<table style="width: 100%" cellspacing="0"><tr>
<td><md-input placeholder="First name" style="width: 100%"></md-input></td>
<td><md-input placeholder="Long Last Name That Will Be Truncated" style="width: 100%"></md-input></td>
</tr></table>
<p>
<md-input class="demo-full-width" placeholder="Address" value="1600 Amphitheatre Pkway"></md-input>
<md-input class="demo-full-width" placeholder="Address 2"></md-input>
</p>
<table style="width: 100%" cellspacing="0"><tr>
<td><md-input class="demo-full-width" placeholder="City" value="Mountain View"></md-input></td>
<td><md-input class="demo-full-width" placeholder="State" maxLength="2" value="CA"></md-input></td>
<td><md-input #postalCode class="demo-full-width" maxLength="5"
placeholder="Postal Code"
value="94043">
<md-hint align="end">{{postalCode.characterCount}} / 5</md-hint>
</md-input></td>
</tr></table>
</form>
</md-card-content>
</md-card>
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Prefix + Suffix</md-toolbar>
<md-card-content>
<md-input placeholder="amount" align="end">
<span md-prefix>$&nbsp;</span>
<span md-suffix>.00</span>
</md-input>
</md-card-content>
</md-card>
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Divider Colors</md-toolbar>
<md-card-content>
<md-input dividerColor="primary" placeholder="Default Color" value="example"></md-input>
<md-input dividerColor="accent" placeholder="Accent Color" value="example"></md-input>
<md-input dividerColor="warn" placeholder="Warn Color" value="example"></md-input>
</md-card-content>
</md-card>
<md-card class="demo-card demo-basic">
<md-toolbar color="primary">Hints</md-toolbar>
<md-card-content>
<p>
<md-input placeholder="Character count (100 max)" maxLength="100" class="demo-full-width"
value="Hello world. How are you?"
#characterCountHintExample>
<md-hint align="end">{{characterCountHintExample.characterCount}} / 100</md-hint>
</md-input>
</p>
</md-card-content>
</md-card>
<md-card class="demo-card">
<md-card-title>
Hello <md-input [(ngModel)]="name" type="string" placeholder="First name"></md-input>,
+9
View File
@@ -1,6 +1,15 @@
@import 'default-theme';
@import 'variables';
.demo-basic {
padding: 0;
}
.demo-basic md-card-content {
padding: 16px;
}
.demo-full-width {
width: 100%;
}
.demo-icons {
font-size: 100%;
+2 -1
View File
@@ -3,6 +3,7 @@ import {MD_INPUT_DIRECTIVES} from '../../components/input/input';
import {MdButton} from '../../components/button/button';
import {MdCard} from '../../components/card/card';
import {MdCheckbox} from '../../components/checkbox/checkbox';
import {MdToolbar} from '../../components/toolbar/toolbar';
let max = 5;
@@ -11,7 +12,7 @@ let max = 5;
selector: 'input-demo',
templateUrl: 'demo-app/input/input-demo.html',
styleUrls: ['demo-app/input/input-demo.css'],
directives: [MdCard, MdCheckbox, MdButton, MD_INPUT_DIRECTIVES]
directives: [MdCard, MdCheckbox, MdButton, MdToolbar, MD_INPUT_DIRECTIVES]
})
export class InputDemo {
dividerColor: boolean;