Skip to content

Commit 1706343

Browse files
committed
add spacing and alignment rules for outline variant
1 parent 5a30888 commit 1706343

10 files changed

+219
-15
lines changed

src/demo-app/input/input-demo.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,13 @@ <h3>&lt;textarea&gt; with ngModel</h3>
588588
<mat-hint>Please type something here</mat-hint>
589589
</mat-form-field>
590590

591+
<mat-form-field appearance="outline">
592+
<mat-label>Outline appearance</mat-label>
593+
<input matInput [(ngModel)]="outlineAppearance" required>
594+
<mat-error>This field is required</mat-error>
595+
<mat-hint>Please type something here</mat-hint>
596+
</mat-form-field>
597+
591598
<table style="width: 100%" cellspacing="0"><tr>
592599
<td>
593600
<mat-form-field appearance="legacy" style="width: 100%">
@@ -613,6 +620,14 @@ <h3>&lt;textarea&gt; with ngModel</h3>
613620
<mat-hint>Please type something here</mat-hint>
614621
</mat-form-field>
615622
</td>
623+
<td>
624+
<mat-form-field appearance="outline" style="width: 100%">
625+
<mat-label>Outline appearance</mat-label>
626+
<input matInput [(ngModel)]="outlineAppearance" required>
627+
<mat-error>This field is required</mat-error>
628+
<mat-hint>Please type something here</mat-hint>
629+
</mat-form-field>
630+
</td>
616631
</tr></table>
617632
</mat-card-content>
618633
</mat-card>

src/demo-app/input/input-demo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export class InputDemo {
5555
legacyAppearance: string;
5656
standardAppearance: string;
5757
fillAppearance: string;
58+
outlineAppearance: string;
5859

5960
constructor() {
6061
setTimeout(() => this.delayedFormControl.setValue('hello'), 100);

src/lib/form-field/BUILD.bazel

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ng_module(
1111
":form_field_css",
1212
":form_field_fill_css",
1313
":form_field_legacy_css",
14+
":form_field_outline_css",
1415
":form_field_standard_css",
1516
"//src/lib/input:input_css"
1617
],
@@ -40,6 +41,12 @@ sass_binary(
4041
deps = ["//src/lib/core:core_scss_lib"],
4142
)
4243

44+
sass_binary(
45+
name = "form_field_outline_scss",
46+
src = "form-field-outline.scss",
47+
deps = ["//src/lib/core:core_scss_lib"],
48+
)
49+
4350
sass_binary(
4451
name = "form_field_standard_scss",
4552
src = "form-field-standard.scss",
@@ -69,6 +76,13 @@ genrule(
6976
cmd = "cat $(locations :form_field_legacy_scss) > $@",
7077
)
7178

79+
genrule(
80+
name = "form_field_outline_css",
81+
srcs = [":form_field_outline_scss"],
82+
outs = ["form-field-outline.css"],
83+
cmd = "cat $(locations :form_field_outline_scss) > $@",
84+
)
85+
7286
genrule(
7387
name = "form_field_standard_css",
7488
srcs = [":form_field_standard_scss"],

src/lib/form-field/_form-field-fill-theme.scss

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,38 +60,36 @@ $mat-form-field-fill-dedupe: 0;
6060
$line-height: mat-line-height($config, input);
6161
// The amount to scale the font for the floating label and subscript.
6262
$subscript-font-scale: 0.75;
63-
// The padding on the infix. Mocks show half of the text size.
63+
// The padding on top of the infix.
6464
$infix-padding-top: 0.25em;
65+
// The padding below the infix.
6566
$infix-padding-bottom: 0.75em;
6667
// The margin applied to the form-field-infix to reserve space for the floating label.
6768
$infix-margin-top: 1em * $line-height * $subscript-font-scale;
68-
// The amount we offset the label in the fill appearance.
69-
$fill-appearance-label-offset: -0.5em * $line-height;
69+
// The amount we offset the label from the input text in the fill appearance.
70+
$fill-appearance-label-offset: -0.5em;
7071

7172
.mat-form-field-appearance-fill {
7273
.mat-form-field-infix {
7374
padding: $infix-padding-top 0 $infix-padding-bottom 0;
7475
}
7576

76-
.mat-form-field-label {
77-
margin-top: $fill-appearance-label-offset;
78-
}
79-
8077
.mat-form-field-label {
8178
top: $infix-margin-top + $infix-padding-top;
79+
margin-top: $fill-appearance-label-offset;
8280
}
8381

8482
&.mat-form-field-can-float {
8583
&.mat-form-field-should-float .mat-form-field-label,
8684
.mat-input-server:focus + .mat-form-field-label-wrapper .mat-form-field-label {
87-
@include _mat-form-field-label-floating(
85+
@include _mat-form-field-fill-label-floating(
8886
$subscript-font-scale, $infix-padding-top + $fill-appearance-label-offset,
8987
$infix-margin-top);
9088
}
9189

9290
.mat-form-field-autofill-control:-webkit-autofill + .mat-form-field-label-wrapper
9391
.mat-form-field-label {
94-
@include _mat-form-field-label-floating(
92+
@include _mat-form-field-fill-label-floating(
9593
$subscript-font-scale, $infix-padding-top + $fill-appearance-label-offset,
9694
$infix-margin-top);
9795
}
@@ -100,7 +98,7 @@ $mat-form-field-fill-dedupe: 0;
10098
// (used as a pure CSS stand-in for mat-form-field-should-float).
10199
.mat-input-server[label]:not(:label-shown) + .mat-form-field-label-wrapper
102100
.mat-form-field-label {
103-
@include _mat-form-field-label-floating(
101+
@include _mat-form-field-fill-label-floating(
104102
$subscript-font-scale, $infix-padding-top + $fill-appearance-label-offset,
105103
$infix-margin-top);
106104
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
@import '../core/theming/palette';
2+
@import '../core/theming/theming';
3+
@import '../core/style/form-common';
4+
@import '../core/typography/typography-utils';
5+
6+
7+
// Theme styles that only apply to the outline appearance of the form-field.
8+
9+
@mixin mat-form-field-outline-theme($theme) {
10+
$foreground: map-get($theme, foreground);
11+
$label-disabled-color: mat-color($foreground, disabled-text);
12+
13+
.mat-form-field-appearance-outline {
14+
&.mat-form-field-disabled {
15+
.mat-form-field-label {
16+
color: $label-disabled-color;
17+
}
18+
}
19+
}
20+
}
21+
22+
// Used to make instances of the _mat-form-field-label-floating mixin negligibly different,
23+
// and prevent Google's CSS Optimizer from collapsing the declarations. This is needed because some
24+
// of the selectors contain pseudo-classes not recognized in all browsers. If a browser encounters
25+
// an unknown pseudo-class it will discard the entire rule set.
26+
$mat-form-field-outline-dedupe: 0;
27+
28+
// Applies a floating label above the form field control itself.
29+
@mixin _mat-form-field-outline-label-floating($font-scale, $infix-padding, $infix-margin-top) {
30+
transform: translateY(-$infix-margin-top - $infix-padding + $mat-form-field-outline-dedupe)
31+
scale($font-scale);
32+
width: 100% / $font-scale + $mat-form-field-outline-dedupe;
33+
34+
$mat-form-field-fill-dedupe: $mat-form-field-outline-dedupe + 0.00001 !global;
35+
}
36+
37+
@mixin mat-form-field-outline-typography($config) {
38+
// The unit-less line-height from the font config.
39+
$line-height: mat-line-height($config, input);
40+
// The amount to scale the font for the floating label and subscript.
41+
$subscript-font-scale: 0.75;
42+
// The padding above and below the infix.
43+
$infix-padding: 1em;
44+
// The margin applied to the form-field-infix to reserve space for the floating label.
45+
$infix-margin-top: 1em * $line-height * $subscript-font-scale;
46+
// The space between the bottom of the .mat-form-field-flex area and the subscript wrapper.
47+
// Mocks show half of the text size, but this margin is applied to an element with the subscript
48+
// text font size, so we need to divide by the scale factor to make it half of the original text
49+
// size.
50+
$subscript-margin-top: 0.5em / $subscript-font-scale;
51+
// The padding applied to the form-field-wrapper to reserve space for the subscript, since it's
52+
// absolutely positioned. This is a combination of the subscript's margin and line-height, but we
53+
// need to multiply by the subscript font scale factor since the wrapper has a larger font size.
54+
$wrapper-padding-bottom: ($subscript-margin-top + $line-height) * $subscript-font-scale;
55+
// The amount we offset the label from the input text in the outline appearance.
56+
$outline-appearance-label-offset: -0.25em;
57+
58+
.mat-form-field-appearance-outline {
59+
.mat-form-field-infix {
60+
padding: $infix-padding 0 $infix-padding 0;
61+
}
62+
63+
.mat-form-field-outline {
64+
// We want the bottom of the outline to start at the end of the content box, not the padding
65+
// box, so we move it up by the padding amount.
66+
bottom: $wrapper-padding-bottom;
67+
}
68+
69+
.mat-form-field-label {
70+
top: $infix-margin-top + $infix-padding;
71+
margin-top: $outline-appearance-label-offset;
72+
}
73+
74+
&.mat-form-field-can-float {
75+
&.mat-form-field-should-float .mat-form-field-label,
76+
.mat-input-server:focus + .mat-form-field-label-wrapper .mat-form-field-label {
77+
@include _mat-form-field-outline-label-floating(
78+
$subscript-font-scale, $infix-padding + $outline-appearance-label-offset,
79+
$infix-margin-top);
80+
}
81+
82+
.mat-form-field-autofill-control:-webkit-autofill + .mat-form-field-label-wrapper
83+
.mat-form-field-label {
84+
@include _mat-form-field-outline-label-floating(
85+
$subscript-font-scale, $infix-padding + $outline-appearance-label-offset,
86+
$infix-margin-top);
87+
}
88+
89+
// Server-side rendered matInput with a label attribute but label not shown
90+
// (used as a pure CSS stand-in for mat-form-field-should-float).
91+
.mat-input-server[label]:not(:label-shown) + .mat-form-field-label-wrapper
92+
.mat-form-field-label {
93+
@include _mat-form-field-outline-label-floating(
94+
$subscript-font-scale, $infix-padding + $outline-appearance-label-offset,
95+
$infix-margin-top);
96+
}
97+
}
98+
}
99+
}

src/lib/form-field/_form-field-theme.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
@import '../core/typography/typography-utils';
55
@import 'form-field-fill-theme.scss';
66
@import 'form-field-legacy-theme.scss';
7+
@import 'form-field-outline-theme.scss';
78
@import 'form-field-standard-theme.scss';
89

910

@@ -95,6 +96,7 @@
9596
@include mat-form-field-legacy-theme($theme);
9697
@include mat-form-field-standard-theme($theme);
9798
@include mat-form-field-fill-theme($theme);
99+
@include mat-form-field-outline-theme($theme);
98100
}
99101

100102
// Used to make instances of the _mat-form-field-label-floating mixin negligibly different,
@@ -222,4 +224,5 @@ $mat-form-field-dedupe: 0;
222224
@include mat-form-field-legacy-typography($config);
223225
@include mat-form-field-standard-typography($config);
224226
@include mat-form-field-fill-typography($config);
227+
@include mat-form-field-outline-typography($config);
225228
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
@import '../core/style/variables';
2+
@import '../core/style/vendor-prefixes';
3+
4+
// Styles that only apply to the outline appearance of the form-field.
5+
6+
// The horizontal padding between the edge of the form field fill box and the start of the text.
7+
$mat-form-field-outline-side-padding: 0.75em !default;
8+
// The scale of the subscript and floating label text w.r.t the value text.
9+
$mat-form-field-outline-subscript-font-scale: 0.75 !default;
10+
// The amount of overlap between the label and the outline.
11+
$mat-form-field-outline-label-overlap: 0.25em;
12+
// The horizontal padding between the edge of the subscript box and the start of the subscript text.
13+
$mat-form-field-outline-subscript-padding:
14+
$mat-form-field-outline-side-padding / $mat-form-field-outline-subscript-font-scale;
15+
16+
17+
.mat-form-field-appearance-outline {
18+
// We need to add margin to the top to reserve space in the layout for the label which sticks out
19+
// of the top. In order to ensure that the outline appearance aligns nicely with other form-field
20+
// appearances when center-aligned, we also need to add the same amount of margin to the bottom.
21+
.mat-form-field-wrapper {
22+
margin: $mat-form-field-outline-label-overlap 0;
23+
}
24+
25+
.mat-form-field-flex {
26+
padding: 0 $mat-form-field-outline-side-padding 0 $mat-form-field-outline-side-padding;
27+
margin-top: -$mat-form-field-outline-label-overlap;
28+
}
29+
30+
.mat-form-field-outline {
31+
display: flex;
32+
position: absolute;
33+
top: 0;
34+
left: 0;
35+
right: 0;
36+
pointer-events: none;
37+
}
38+
39+
.mat-form-field-outline::before,
40+
.mat-form-field-outline::after {
41+
content: '';
42+
width: 12px; // use var for this
43+
border: 1px solid rgba(0, 0, 0, .5); //use vars for this
44+
flex: 1;
45+
}
46+
47+
.mat-form-field-outline::before {
48+
border-radius: 4px 0 0 4px; // use vars for this
49+
border-right: none;
50+
}
51+
52+
.mat-form-field-outline::after {
53+
border-radius: 0 4px 4px 0; // use vars for this
54+
border-left: none;
55+
}
56+
57+
.mat-form-field-subscript-wrapper {
58+
padding: 0 $mat-form-field-outline-subscript-padding;
59+
}
60+
}

src/lib/form-field/form-field-standard.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
// The height of the underline.
88
$mat-form-field-standard-underline-height: 1px !default;
99
// The padding between the top of the form field and the label text (used to align the standard
10-
// form field with the fill appearance).
11-
$mat-form-field-standard-padding-top: 0.5em !default;
10+
// form field with the fill and outline appearances).
11+
$mat-form-field-standard-padding-top: 0.75em !default;
1212

1313

1414
.mat-form-field-appearance-standard {

src/lib/form-field/form-field.html

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,24 @@
5353
</div>
5454
</div>
5555

56-
<div class="mat-input-underline mat-form-field-underline" #underline>
56+
<!-- Underline used for legacy, standard, and box appearances. -->
57+
<div class="mat-input-underline mat-form-field-underline" #underline
58+
*ngIf="appearance != 'outline'">
5759
<span class="mat-input-ripple mat-form-field-ripple"
5860
[class.mat-accent]="color == 'accent'"
5961
[class.mat-warn]="color == 'warn'"></span>
6062
</div>
6163

64+
<!-- Outline used for outline appearance. -->
65+
<ng-container *ngIf="appearance == 'outline'">
66+
<div class="mat-form-field-outline">
67+
<div class="mat-form-field-outline-gap"></div>
68+
</div>
69+
<div class="mat-form-field-outline mat-form-field-outline-thick">
70+
<div class="mat-form-field-outline-gap"></div>
71+
</div>
72+
</ng-container>
73+
6274
<div class="mat-input-subscript-wrapper mat-form-field-subscript-wrapper"
6375
[ngSwitch]="_getDisplayedMessages()">
6476
<div *ngSwitchCase="'error'" [@transitionMessages]="_subscriptAnimationState">

src/lib/form-field/form-field.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const _MatFormFieldMixinBase = mixinColor(MatFormFieldBase, 'primary');
6262
let nextUniqueId = 0;
6363

6464

65-
export type MatFormFieldAppearance = 'legacy' | 'standard' | 'fill';
65+
export type MatFormFieldAppearance = 'legacy' | 'standard' | 'fill' | 'outline';
6666

6767

6868
/** Container for form controls that applies Material Design styling and behavior. */
@@ -79,6 +79,7 @@ export type MatFormFieldAppearance = 'legacy' | 'standard' | 'fill';
7979
'form-field.css',
8080
'form-field-fill.css',
8181
'form-field-legacy.css',
82+
'form-field-outline.css',
8283
'form-field-standard.css',
8384
'../input/input.css',
8485
],
@@ -87,6 +88,7 @@ export type MatFormFieldAppearance = 'legacy' | 'standard' | 'fill';
8788
'class': 'mat-input-container mat-form-field',
8889
'[class.mat-form-field-appearance-standard]': 'appearance == "standard"',
8990
'[class.mat-form-field-appearance-fill]': 'appearance == "fill"',
91+
'[class.mat-form-field-appearance-outline]': 'appearance == "outline"',
9092
'[class.mat-form-field-appearance-legacy]': 'appearance == "legacy"',
9193
'[class.mat-input-invalid]': '_control.errorState',
9294
'[class.mat-form-field-invalid]': '_control.errorState',
@@ -114,7 +116,7 @@ export class MatFormField extends _MatFormFieldMixinBase
114116
private _labelOptions: LabelOptions;
115117

116118
/** The form-field appearance style. */
117-
@Input() appearance: MatFormFieldAppearance = 'legacy';
119+
@Input() appearance: MatFormFieldAppearance = 'outline';
118120

119121
/**
120122
* @deprecated Use `color` instead.

0 commit comments

Comments
 (0)