blob: a51999568a1c0e09868cf1f114b238fc7ba927c2 [file] [log] [blame]
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--><html><head><link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="../paper-styles/default-theme.html">
<link rel="import" href="../paper-styles/typography.html">
<!--
`<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or
`<textarea>` and optional add-on elements such as an error message or character
counter, used to implement Material Design text fields.
For example:
<paper-input-container>
<label>Your name</label>
<input is="iron-input">
</paper-input-container>
Do not wrap `<paper-input-container>` around elements that already include it, such as `<paper-input>`.
Doing so may cause events to bounce infintely between the container and its contained element.
### Listening for input changes
By default, it listens for changes on the `bind-value` attribute on its children nodes and perform
tasks such as auto-validating and label styling when the `bind-value` changes. You can configure
the attribute it listens to with the `attr-for-value` attribute.
### Using a custom input element
You can use a custom input element in a `<paper-input-container>`, for example to implement a
compound input field like a social security number input. The custom input element should have the
`paper-input-input` class, have a `notify:true` value property and optionally implements
`Polymer.IronValidatableBehavior` if it is validatable.
<paper-input-container attr-for-value="ssn-value">
<label>Social security number</label>
<ssn-input class="paper-input-input"></ssn-input>
</paper-input-container>
If you're using a `<paper-input-container>` imperatively, it's important to make sure
that you attach its children (the `iron-input` and the optional `label`) before you
attach the `<paper-input-container>` itself, so that it can be set up correctly.
### Validation
If the `auto-validate` attribute is set, the input container will validate the input and update
the container styling when the input value changes.
### Add-ons
Add-ons are child elements of a `<paper-input-container>` with the `add-on` attribute and
implements the `Polymer.PaperInputAddonBehavior` behavior. They are notified when the input value
or validity changes, and may implement functionality such as error messages or character counters.
They appear at the bottom of the input.
### Prefixes and suffixes
These are child elements of a `<paper-input-container>` with the `prefix`
or `suffix` attribute, and are displayed inline with the input, before or after.
<paper-input-container>
<div prefix>$</div>
<label>Total</label>
<input is="iron-input">
<paper-icon-button suffix icon="clear"></paper-icon-button>
</paper-input-container>
### Styling
The following custom properties and mixins are available for styling:
Custom property | Description | Default
----------------|-------------|----------
`--paper-input-container-color` | Label and underline color when the input is not focused | `--secondary-text-color`
`--paper-input-container-focus-color` | Label and underline color when the input is focused | `--primary-color`
`--paper-input-container-invalid-color` | Label and underline color when the input is is invalid | `--error-color`
`--paper-input-container-input-color` | Input foreground color | `--primary-text-color`
`--paper-input-container` | Mixin applied to the container | `{}`
`--paper-input-container-disabled` | Mixin applied to the container when it's disabled | `{}`
`--paper-input-container-label` | Mixin applied to the label | `{}`
`--paper-input-container-label-focus` | Mixin applied to the label when the input is focused | `{}`
`--paper-input-container-label-floating` | Mixin applied to the label when floating | `{}`
`--paper-input-container-input` | Mixin applied to the input | `{}`
`--paper-input-container-input-webkit-spinner` | Mixin applied to the webkit spinner | `{}`
`--paper-input-container-underline` | Mixin applied to the underline | `{}`
`--paper-input-container-underline-focus` | Mixin applied to the underline when the input is focused | `{}`
`--paper-input-container-underline-disabled` | Mixin applied to the underline when the input is disabled | `{}`
`--paper-input-prefix` | Mixin applied to the input prefix | `{}`
`--paper-input-suffix` | Mixin applied to the input suffix | `{}`
This element is `display:block` by default, but you can set the `inline` attribute to make it
`display:inline-block`.
-->
</head><body><dom-module id="paper-input-container">
<template>
<style>
:host {
display: block;
padding: 8px 0;
@apply(--paper-input-container);
}
:host([inline]) {
display: inline-block;
}
:host([disabled]) {
pointer-events: none;
opacity: 0.33;
@apply(--paper-input-container-disabled);
}
:host([hidden]) {
display: none !important;
}
.floated-label-placeholder {
@apply(--paper-font-caption);
}
.underline {
height: 2px;
position: relative;
}
.focused-line {
@apply(--layout-fit);
border-bottom: 2px solid var(--paper-input-container-focus-color, --primary-color);
-webkit-transform-origin: center center;
transform-origin: center center;
-webkit-transform: scale3d(0,1,1);
transform: scale3d(0,1,1);
@apply(--paper-input-container-underline-focus);
}
.underline.is-highlighted .focused-line {
-webkit-transform: none;
transform: none;
-webkit-transition: -webkit-transform 0.25s;
transition: transform 0.25s;
@apply(--paper-transition-easing);
}
.underline.is-invalid .focused-line {
border-color: var(--paper-input-container-invalid-color, --error-color);
-webkit-transform: none;
transform: none;
-webkit-transition: -webkit-transform 0.25s;
transition: transform 0.25s;
@apply(--paper-transition-easing);
}
.unfocused-line {
@apply(--layout-fit);
border-bottom: 1px solid var(--paper-input-container-color, --secondary-text-color);
@apply(--paper-input-container-underline);
}
:host([disabled]) .unfocused-line {
border-bottom: 1px dashed;
border-color: var(--paper-input-container-color, --secondary-text-color);
@apply(--paper-input-container-underline-disabled);
}
.label-and-input-container {
@apply(--layout-flex-auto);
@apply(--layout-relative);
width: 100%;
max-width: 100%;
}
.input-content {
@apply(--layout-horizontal);
@apply(--layout-center);
position: relative;
}
.input-content ::content label,
.input-content ::content .paper-input-label {
position: absolute;
top: 0;
right: 0;
left: 0;
width: 100%;
font: inherit;
color: var(--paper-input-container-color, --secondary-text-color);
-webkit-transition: -webkit-transform 0.25s, width 0.25s;
transition: transform 0.25s, width 0.25s;
-webkit-transform-origin: left top;
transform-origin: left top;
@apply(--paper-font-common-nowrap);
@apply(--paper-font-subhead);
@apply(--paper-input-container-label);
@apply(--paper-transition-easing);
}
.input-content.label-is-floating ::content label,
.input-content.label-is-floating ::content .paper-input-label {
-webkit-transform: translateY(-75%) scale(0.75);
transform: translateY(-75%) scale(0.75);
/* Since we scale to 75/100 of the size, we actually have 100/75 of the
original space now available */
width: 133%;
@apply(--paper-input-container-label-floating);
}
:host-context([dir="rtl"]) .input-content.label-is-floating ::content label,
:host-context([dir="rtl"]) .input-content.label-is-floating ::content .paper-input-label {
/* TODO(noms): Figure out why leaving the width at 133% before the animation
* actually makes
* it wider on the right side, not left side, as you would expect in RTL */
width: 100%;
-webkit-transform-origin: right top;
transform-origin: right top;
}
.input-content.label-is-highlighted ::content label,
.input-content.label-is-highlighted ::content .paper-input-label {
color: var(--paper-input-container-focus-color, --primary-color);
@apply(--paper-input-container-label-focus);
}
.input-content.is-invalid ::content label,
.input-content.is-invalid ::content .paper-input-label {
color: var(--paper-input-container-invalid-color, --error-color);
}
.input-content.label-is-hidden ::content label,
.input-content.label-is-hidden ::content .paper-input-label {
visibility: hidden;
}
.input-content ::content input,
.input-content ::content textarea,
.input-content ::content iron-autogrow-textarea,
.input-content ::content .paper-input-input {
position: relative; /* to make a stacking context */
outline: none;
box-shadow: none;
padding: 0;
width: 100%;
max-width: 100%;
background: transparent;
border: none;
color: var(--paper-input-container-input-color, --primary-text-color);
-webkit-appearance: none;
text-align: inherit;
vertical-align: bottom;
@apply(--paper-font-subhead);
@apply(--paper-input-container-input);
}
.input-content ::content input::-webkit-outer-spin-button,
.input-content ::content input::-webkit-inner-spin-button {
@apply(--paper-input-container-input-webkit-spinner);
}
::content [prefix] {
@apply(--paper-font-subhead);
@apply(--paper-input-prefix);
@apply(--layout-flex-none);
}
::content [suffix] {
@apply(--paper-font-subhead);
@apply(--paper-input-suffix);
@apply(--layout-flex-none);
}
/* Firefox sets a min-width on the input, which can cause layout issues */
.input-content ::content input {
min-width: 0;
}
.input-content ::content textarea {
resize: none;
}
.add-on-content {
position: relative;
}
.add-on-content.is-invalid ::content * {
color: var(--paper-input-container-invalid-color, --error-color);
}
.add-on-content.is-highlighted ::content * {
color: var(--paper-input-container-focus-color, --primary-color);
}
</style>
<template is="dom-if" if="[[!noLabelFloat]]">
<div class="floated-label-placeholder" aria-hidden="true">&nbsp;</div>
</template>
<div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focused,invalid,_inputHasContent)]]">
<content select="[prefix]" id="prefix"></content>
<div class="label-and-input-container" id="labelAndInputContainer">
<content select=":not([add-on]):not([prefix]):not([suffix])"></content>
</div>
<content select="[suffix]"></content>
</div>
<div class$="[[_computeUnderlineClass(focused,invalid)]]">
<div class="unfocused-line"></div>
<div class="focused-line"></div>
</div>
<div class$="[[_computeAddOnContentClass(focused,invalid)]]">
<content id="addOnContent" select="[add-on]"></content>
</div>
</template>
</dom-module>
<script src="paper-input-container-extracted.js"></script></body></html>