Skip to content

Commit

Permalink
feat(MdInput): README.md improvements and autofill support.
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
hansl committed Apr 3, 2016
1 parent 5a6657a commit b711c2b
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 42 deletions.
87 changes: 83 additions & 4 deletions src/components/input/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>`.



Expand All @@ -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
Expand All @@ -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">
62 changes: 33 additions & 29 deletions src/components/input/input.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down
58 changes: 51 additions & 7 deletions src/components/input/input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,37 @@ $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);

// Gradient for showing the dashed line when the input is disabled.
$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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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++}`;
Expand Down
60 changes: 60 additions & 0 deletions src/demo-app/input/input-demo.html
Original file line number Diff line number Diff line change
@@ -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>,
Expand Down
Loading

0 comments on commit b711c2b

Please sign in to comment.