mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(input): make input spacing match spec (#4788)
* make input match mocks better, WIP still WIP placeholder working, still WIP fixed main styles, now just themes... themes working again icon button support * add select to baseline demo * fix IE bug * address comments * address comments * remove forced font-size * integrate typography system * switch font-size to inherit * fix non-floating placeholders
This commit is contained in:
@@ -14,6 +14,10 @@
|
||||
<input mdInput placeholder="Input" value="Text Input">
|
||||
</md-input-container>
|
||||
| Text 5 |
|
||||
<md-select placeholder="Select">
|
||||
<md-option value="option">Option</md-option>
|
||||
</md-select>
|
||||
| Text 6 |
|
||||
<md-input-container>
|
||||
<textarea mdInput placeholder="Input" mdTextareaAutosize>Textarea Line 2</textarea>
|
||||
</md-input-container>
|
||||
@@ -38,6 +42,10 @@
|
||||
<input mdInput placeholder="Input" value="Text Input">
|
||||
</md-input-container>
|
||||
| Text 5 |
|
||||
<md-select placeholder="Select">
|
||||
<md-option value="option">Option</md-option>
|
||||
</md-select>
|
||||
| Text 6 |
|
||||
<md-input-container>
|
||||
<textarea mdInput placeholder="Input" mdTextareaAutosize>Textarea Line 2</textarea>
|
||||
</md-input-container>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<table style="width: 100%" cellspacing="0"><tr>
|
||||
<td>
|
||||
<md-input-container style="width: 100%">
|
||||
<md-input-container style="width: 100%" floatPlaceholder="never">
|
||||
<input mdInput placeholder="First name">
|
||||
</md-input-container>
|
||||
</td>
|
||||
@@ -113,6 +113,13 @@
|
||||
<md-icon mdPrefix>attach_money</md-icon>
|
||||
<md-icon mdSuffix>mode_edit</md-icon>
|
||||
</md-input-container>
|
||||
|
||||
<h4>Icon buttons</h4>
|
||||
<md-input-container>
|
||||
<input mdInput placeholder="amount">
|
||||
<button md-icon-button mdPrefix><md-icon>attach_money</md-icon></button>
|
||||
<button md-icon-button mdSuffix><md-icon>mode_edit</md-icon></button>
|
||||
</md-input-container>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
$body-2: mat-typography-level(14px, 24px, 500),
|
||||
$body-1: mat-typography-level(14px, 20px, 400),
|
||||
$caption: mat-typography-level(12px, 12px, 400),
|
||||
$button: mat-typography-level(14px, 14px, 500)
|
||||
$button: mat-typography-level(14px, 14px, 500),
|
||||
// Line-height must be unit-less fraction of the font-size.
|
||||
$input: mat-typography-level(inherit, 1.125, 400)
|
||||
) {
|
||||
@return (
|
||||
font-family: $font-family,
|
||||
@@ -37,7 +39,8 @@
|
||||
body-2: $body-2,
|
||||
body-1: $body-1,
|
||||
caption: $caption,
|
||||
button: $button
|
||||
button: $button,
|
||||
input: $input,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,7 +64,7 @@
|
||||
}
|
||||
|
||||
.mat-h2, #{$selector} h2 {
|
||||
@include mat-typography-level-to-styles($config, display-2)
|
||||
@include mat-typography-level-to-styles($config, display-2);
|
||||
|
||||
// Note: The spec doesn't mention letter spacing. The value comes from
|
||||
// eyeballing it until it looked exactly like the spec examples.;
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
.mat-input-underline {
|
||||
border-color: $input-underline-color;
|
||||
background-color: $input-underline-color;
|
||||
}
|
||||
|
||||
.mat-input-ripple {
|
||||
@@ -91,20 +91,121 @@
|
||||
}
|
||||
|
||||
@mixin mat-input-typography($config) {
|
||||
.mat-input-container {
|
||||
font-family: mat-font-family($config);
|
||||
line-height: normal;
|
||||
// The unit-less line-height from the font config.
|
||||
$mat-input-line-height: mat-line-height($config, input);
|
||||
|
||||
.mat-icon {
|
||||
font-size: 100%;
|
||||
// The amount to scale the font for the floating label and subscript.
|
||||
$mat-input-subscript-font-scale: 0.75;
|
||||
// The amount to scale the font for the prefix and suffix icons.
|
||||
$mat-input-prefix-suffix-icon-font-scale: 1.5;
|
||||
|
||||
// The amount of space between the top of the line and the top of the actual text
|
||||
// (as a fraction of the font-size).
|
||||
$mat-input-line-spacing: ($mat-input-line-height - 1) / 2;
|
||||
// The padding on the infix. Mocks show half of the text size, but seem to measure from the edge
|
||||
// of the text itself, not the edge of the line; therefore we subtract off the line spacing.
|
||||
$mat-input-infix-padding: 0.5em - $mat-input-line-spacing;
|
||||
// The margin applied to the input-infix to reserve space for the floating label.
|
||||
$mat-input-infix-margin-top: 1em * $mat-input-line-height * $mat-input-subscript-font-scale;
|
||||
// Font size to use for the label and subscript text.
|
||||
$mat-input-subscript-font-size: $mat-input-subscript-font-scale * 100%;
|
||||
// Font size to use for the for the prefix and suffix icons.
|
||||
$mat-input-prefix-suffix-icon-font-size: $mat-input-prefix-suffix-icon-font-scale * 100%;
|
||||
// The space between the bottom of the input table and the subscript container. Mocks show half of
|
||||
// the text size, but this margin is applied to an element with the subscript text font size, so
|
||||
// we need to divide by the scale factor to make it half of the original text size. We again need
|
||||
// to subtract off the line spacing since the mocks measure to the edge of the text, not the edge
|
||||
// of the line.
|
||||
$mat-input-subscript-margin-top:
|
||||
0.5em / $mat-input-subscript-font-scale - $mat-input-line-spacing;
|
||||
// The padding applied to the input-wrapper to reserve space for the subscript, since it's
|
||||
// absolutely positioned. This is a combination of the subscript's margin and line-height, but we
|
||||
// need to multiply by the subscript font scale factor since the wrapper has a larger font size.
|
||||
$mat-input-wrapper-padding-bottom:
|
||||
($mat-input-subscript-margin-top + $mat-input-line-height) * $mat-input-subscript-font-scale;
|
||||
|
||||
// Applies a floating placeholder above the input itself.
|
||||
@mixin mat-input-placeholder-floating {
|
||||
transform: translateY(-$mat-input-infix-margin-top - $mat-input-infix-padding)
|
||||
scale($mat-input-subscript-font-scale)
|
||||
// We use perspecitve to fix the text blurriness as described here:
|
||||
// http://www.useragentman.com/blog/2014/05/04/fixing-typography-inside-of-2-d-css-transforms/
|
||||
// This results in a small jitter after the label floats on Firefox, which the
|
||||
// translateZ fixes.
|
||||
perspective(100px) translateZ(0.001px);
|
||||
// The tricks above used to smooth out the animation on chrome and firefox actually make things
|
||||
// worse on IE, so we don't include them in the IE version.
|
||||
-ms-transform: translateY(-$mat-input-infix-margin-top - $mat-input-infix-padding)
|
||||
scale($mat-input-subscript-font-scale);
|
||||
|
||||
width: 100% / $mat-input-subscript-font-scale;
|
||||
}
|
||||
|
||||
.mat-input-container {
|
||||
@include mat-typography-level-to-styles($config, input);
|
||||
}
|
||||
|
||||
.mat-input-wrapper {
|
||||
padding-bottom: $mat-input-wrapper-padding-bottom;
|
||||
}
|
||||
|
||||
.mat-input-prefix,
|
||||
.mat-input-suffix {
|
||||
// Allow icons in a prefix or suffix to adapt to the correct size.
|
||||
.mat-icon,
|
||||
.mat-datepicker-toggle {
|
||||
font-size: $mat-input-prefix-suffix-icon-font-size;
|
||||
}
|
||||
|
||||
// Allow icon buttons in a prefix or suffix to adapt to the correct size.
|
||||
.mat-icon-button {
|
||||
height: $mat-input-prefix-suffix-icon-font-scale * 1em;
|
||||
width: $mat-input-prefix-suffix-icon-font-scale * 1em;
|
||||
|
||||
.mat-icon {
|
||||
line-height: $mat-input-prefix-suffix-icon-font-scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-input-infix {
|
||||
padding: $mat-input-infix-padding 0;
|
||||
// Throws off the baseline if we do it as a real margin, so we do it as a border instead.
|
||||
border-top: $mat-input-infix-margin-top solid transparent;
|
||||
}
|
||||
|
||||
.mat-input-element {
|
||||
&:-webkit-autofill + .mat-input-placeholder-wrapper .mat-float {
|
||||
@include mat-input-placeholder-floating;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-input-placeholder-wrapper {
|
||||
top: -$mat-input-infix-margin-top;
|
||||
padding-top: $mat-input-infix-margin-top;
|
||||
}
|
||||
|
||||
.mat-input-placeholder {
|
||||
font-size: 100%;
|
||||
top: $mat-input-infix-margin-top + $mat-input-infix-padding;
|
||||
|
||||
// Show the placeholder above the input when it's not empty, or focused.
|
||||
&.mat-float:not(.mat-empty), .mat-focused &.mat-float {
|
||||
@include mat-input-placeholder-floating;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-input-underline {
|
||||
// We want the underline to start at the end of the content box, not the padding box,
|
||||
// so we move it up by the padding amount;
|
||||
bottom: $mat-input-wrapper-padding-bottom;
|
||||
}
|
||||
|
||||
.mat-input-subscript-wrapper {
|
||||
font-size: 75%;
|
||||
font-size: $mat-input-subscript-font-size;
|
||||
margin-top: $mat-input-subscript-margin-top;
|
||||
|
||||
// We want the subscript to start at the end of the content box, not the padding box,
|
||||
// so we move it up by the padding amount (adjusted for the smaller font size);
|
||||
top: calc(100% - #{$mat-input-wrapper-padding-bottom / $mat-input-subscript-font-scale});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<div class="mat-input-wrapper">
|
||||
<div class="mat-input-table">
|
||||
<div class="mat-input-flex">
|
||||
<div class="mat-input-prefix" *ngIf="_prefixChildren.length">
|
||||
<!-- TODO(andrewseguin): remove [md-prefix] -->
|
||||
<ng-content select="[mdPrefix], [matPrefix], [md-prefix]"></ng-content>
|
||||
<ng-content select="[mdPrefix], [matPrefix]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="mat-input-infix" [class.mat-end]="align == 'end'">
|
||||
@@ -24,8 +23,7 @@
|
||||
</div>
|
||||
|
||||
<div class="mat-input-suffix" *ngIf="_suffixChildren.length">
|
||||
<!-- TODO(andrewseguin): remove [md-suffix] -->
|
||||
<ng-content select="[mdSuffix], [matSuffix], [md-suffix]"></ng-content>
|
||||
<ng-content select="[mdSuffix], [matSuffix]"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3,20 +3,11 @@
|
||||
@import '../core/style/form-common';
|
||||
|
||||
|
||||
$mat-input-floating-placeholder-scale-factor: 0.75 !default;
|
||||
$mat-input-wrapper-spacing: 1em !default;
|
||||
$mat-input-hint-min-space: 10px !default;
|
||||
// Min amount of space between start and end hint.
|
||||
$mat-input-hint-min-space: 1em !default;
|
||||
// The height of the underline.
|
||||
$mat-input-underline-height: 1px !default;
|
||||
|
||||
// Gradient for showing the dashed line when the input is disabled.
|
||||
$mat-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.
|
||||
@mixin mat-input-placeholder-floating {
|
||||
display: block;
|
||||
transform: translate3d(0, -1.35em, 0) scale($mat-input-floating-placeholder-scale-factor);
|
||||
width: 100% / $mat-input-floating-placeholder-scale-factor;
|
||||
}
|
||||
|
||||
.mat-input-container {
|
||||
display: inline-block;
|
||||
@@ -28,42 +19,53 @@ $mat-input-underline-disabled-background-image:
|
||||
[dir='rtl'] & {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
// Allow icons in a prefix/suffix/hint/etc to adapt to the correct size.
|
||||
& .mat-icon,
|
||||
& .mat-datepicker-toggle {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
// Global wrapper. We need to apply margin to the element for spacing, but
|
||||
// cannot apply it to the host element directly.
|
||||
.mat-input-wrapper {
|
||||
margin: $mat-input-wrapper-spacing 0;
|
||||
// Account for the underline which has 4px of margin + 2px of border.
|
||||
padding-bottom: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// We use a table layout to baseline align the prefix and suffix classes.
|
||||
// The underline is outside of it so it can cover all of the elements under
|
||||
// this table.
|
||||
// Flex does not respect the baseline. What we really want is akin to a table
|
||||
// as want an inline-block where elements don't wrap.
|
||||
.mat-input-table {
|
||||
display: inline-table;
|
||||
flex-flow: column;
|
||||
vertical-align: bottom;
|
||||
// We use a flex layout to baseline align the prefix and suffix elements.
|
||||
// The underline is outside of it so it can cover all of the elements under this flex container.
|
||||
.mat-input-flex {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
& > * {
|
||||
display: table-cell;
|
||||
.mat-input-prefix,
|
||||
.mat-input-suffix {
|
||||
white-space: nowrap;
|
||||
flex: none;
|
||||
|
||||
// Allow icons in a prefix or suffix to adapt to the correct size.
|
||||
.mat-icon,
|
||||
.mat-datepicker-toggle {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
// Allow icon buttons in a prefix or suffix to adapt to the correct size.
|
||||
.mat-icon-button {
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
|
||||
.mat-icon {
|
||||
font-size: inherit;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-input-infix {
|
||||
display: block;
|
||||
position: relative;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
// The Input element proper.
|
||||
@@ -106,9 +108,17 @@ $mat-input-underline-disabled-background-image:
|
||||
// Once the autofill is committed, a change event happen and the regular md-input-container
|
||||
// classes take over to fulfill this behaviour.
|
||||
// Assumes the autofill is non-empty.
|
||||
&:-webkit-autofill + .mat-input-placeholder-wrapper .mat-float {
|
||||
@include mat-input-placeholder-floating;
|
||||
transition: none;
|
||||
&:-webkit-autofill + .mat-input-placeholder-wrapper {
|
||||
// The input is still technically empty at this point, so we need to hide non-floating
|
||||
// placeholders to prevent overlapping with the autofilled value.
|
||||
.mat-input-placeholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mat-float {
|
||||
display: block;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we can't use something like visibility: hidden or
|
||||
@@ -121,6 +131,18 @@ $mat-input-underline-disabled-background-image:
|
||||
}
|
||||
}
|
||||
|
||||
// Used to hide the placeholder overflow on IE, since IE doesn't take transform into account when
|
||||
// determining overflow.
|
||||
.mat-input-placeholder-wrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
pointer-events: none; // We shouldn't catch mouse events (let them through).
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -129,37 +151,36 @@ $mat-input-underline-disabled-background-image:
|
||||
// infix <div>.
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
font: inherit;
|
||||
pointer-events: none; // We shouldn't catch mouse events (let them through).
|
||||
z-index: 1;
|
||||
padding-top: 1em;
|
||||
|
||||
// Put ellipsis text overflow.
|
||||
width: 100%;
|
||||
display: none;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
transform: translate3d(0, 0, 0);
|
||||
transform-origin: bottom left;
|
||||
// The perspective helps smooth out animations on Chrome and Firefox but isn't needed on IE.
|
||||
transform: perspective(100px);
|
||||
-ms-transform: none;
|
||||
|
||||
transform-origin: 0 0;
|
||||
transition: transform $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
color $swift-ease-out-duration $swift-ease-out-timing-function,
|
||||
width $swift-ease-out-duration $swift-ease-out-timing-function;
|
||||
|
||||
&.mat-empty {
|
||||
display: block;
|
||||
cursor: text;
|
||||
}
|
||||
// Hide the placeholder initially, and only show it when it's floating or the input is empty.
|
||||
display: none;
|
||||
|
||||
// Show the placeholder above the input when it's not empty, or focused.
|
||||
&.mat-float:not(.mat-empty), .mat-focused &.mat-float {
|
||||
@include mat-input-placeholder-floating;
|
||||
&.mat-empty,
|
||||
&.mat-float:not(.mat-empty),
|
||||
.mat-focused &.mat-float {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[dir='rtl'] & {
|
||||
transform-origin: bottom right;
|
||||
transform-origin: 100% 0;
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
@@ -171,47 +192,23 @@ $mat-input-underline-disabled-background-image:
|
||||
transition: none;
|
||||
}
|
||||
|
||||
// Used to hide the placeholder overflow on IE, since IE doesn't take transform into account when
|
||||
// determining overflow.
|
||||
.mat-input-placeholder-wrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -1em;
|
||||
width: 100%;
|
||||
padding-top: 1em;
|
||||
overflow: hidden;
|
||||
pointer-events: none; // We shouldn't catch mouse events (let them through).
|
||||
transform: translate3d(0, 0, 0); // Prevents the label from shifting after the animation is done.
|
||||
|
||||
// Keeps the element height since the placeholder text is `position: absolute`.
|
||||
&::after {
|
||||
content: '';
|
||||
display: inline-table;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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.
|
||||
.mat-input-underline {
|
||||
position: absolute;
|
||||
height: 1px;
|
||||
height: $mat-input-underline-height;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
|
||||
&.mat-disabled {
|
||||
@include mat-control-disabled-underline();
|
||||
border-top: 0;
|
||||
background-position: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.mat-input-ripple {
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
z-index: 1;
|
||||
top: -1px;
|
||||
height: $mat-input-underline-height * 2;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
transform-origin: 50%;
|
||||
transform: scaleX(0.5);
|
||||
@@ -223,7 +220,7 @@ $mat-input-underline-disabled-background-image:
|
||||
visibility: visible;
|
||||
transform: scaleX(1);
|
||||
transition: transform 150ms linear,
|
||||
background-color $swift-ease-in-duration $swift-ease-in-timing-function;
|
||||
background-color $swift-ease-in-duration $swift-ease-in-timing-function;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,21 +228,29 @@ $mat-input-underline-disabled-background-image:
|
||||
// Wrapper for the hints and error messages. Provides positioning and text size.
|
||||
// Note that we're using `top` in order to allow for stacked children to flow downwards.
|
||||
.mat-input-subscript-wrapper {
|
||||
$line-height: 1.2em;
|
||||
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
width: 100%;
|
||||
margin-top: -$line-height;
|
||||
line-height: $line-height;
|
||||
overflow: hidden; // prevents multi-line errors from overlapping the input
|
||||
}
|
||||
|
||||
// Scale down icons in the placeholder and hint to be the same size as the text.
|
||||
.mat-input-subscript-wrapper,
|
||||
.mat-input-placeholder-wrapper {
|
||||
.mat-icon,
|
||||
.mat-datepicker-toggle {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
font-size: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
// Clears the floats on the hints. This is necessary for the hint animation to work.
|
||||
.mat-input-hint-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
// Spacer used to make sure start and end hints have enough space between them.
|
||||
.mat-input-hint-spacer {
|
||||
flex: 1 0 $mat-input-hint-min-space;
|
||||
}
|
||||
@@ -254,9 +259,3 @@ $mat-input-underline-disabled-background-image:
|
||||
.mat-input-error {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mat-input-prefix, .mat-input-suffix {
|
||||
// Prevents the prefix and suffix from stretching together with the container.
|
||||
width: 0.1px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user