Skip to content

Commit 3bcdc5e

Browse files
devversionandrewseguin
authored andcommitted
feat(material-experimental/mdc-form-field): support density scaling
1 parent 8e3698b commit 3bcdc5e

File tree

6 files changed

+122
-49
lines changed

6 files changed

+122
-49
lines changed

src/material-experimental/mdc-form-field/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ sass_library(
8181
sass_library(
8282
name = "form_field_partials",
8383
srcs = [
84+
"_form-field-density.scss",
8485
"_form-field-focus-overlay.scss",
8586
"_form-field-native-select.scss",
8687
"_form-field-sizing.scss",
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
@import '@material/density/functions.import';
2+
@import '@material/textfield/variables.import';
3+
@import 'form-field-sizing';
4+
5+
// Mixin that sets the vertical spacing for the infix container of filled form fields.
6+
// We need to apply spacing to the infix container because we removed the input padding
7+
// provided by MDC in order to support arbitrary form-field controls.
8+
@mixin _mat-form-field-infix-vertical-spacing-filled($with-label-padding, $no-label-padding) {
9+
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-form-field-infix {
10+
padding-top: map_get($with-label-padding, top);
11+
padding-bottom: map_get($with-label-padding, bottom);
12+
}
13+
14+
.mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea)
15+
.mat-mdc-form-field-infix {
16+
padding-top: map_get($no-label-padding, top);
17+
padding-bottom: map_get($no-label-padding, bottom);
18+
}
19+
}
20+
21+
// Mixin that sets the vertical spacing for the infix container of outlined form fields.
22+
// We need to apply spacing to the infix container because we removed the input padding
23+
// provided by MDC in order to support arbitrary form-field controls.
24+
@mixin _mat-form-field-infix-vertical-spacing-outlined($padding) {
25+
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix {
26+
padding-top: map_get($padding, top);
27+
padding-bottom: map_get($padding, bottom);
28+
}
29+
}
30+
31+
// Mixin that includes the density styles for form fields. MDC provides their own density
32+
// styles for MDC text-field which we cannot use. MDC relies on input elements to stretch
33+
// vertically when the height is reduced as per density scale. This doesn't work for for our
34+
// form field since we support custom form field controls without a fixed height. Instead, we
35+
// provide spacing that makes arbitrary controls align as specified in the Material Design
36+
// specification. In order to support density, we need to adjust the vertical spacing to be
37+
// based on the density scale.
38+
@mixin _mat-form-field-density($density-scale) {
39+
// Height of the form field that is based on the current density scale.
40+
$height: mdc-density-prop-value(
41+
$density-config: $mdc-text-field-density-config,
42+
$density-scale: $density-scale,
43+
$property-name: height,
44+
);
45+
46+
// Whether floating labels for filled form fields should be hidden. MDC hides the label in
47+
// their density styles when the height decreases too much. We match their density styles.
48+
$hide-filled-floating-label: $height < $mdc-text-field-minimum-height-for-filled-label;
49+
// We computed the desired height of the form-field using the density configuration. The
50+
// spec only describes vertical spacing/alignment in non-dense mode. This means that we
51+
// cannot update the spacing to explicit numbers based on the density scale. Instead, we
52+
// determine the height reduction and equally subtract it from the default `top` and `bottom`
53+
// padding that is provided by the Material Design specification.
54+
$vertical-deduction: ($mdc-text-field-height - $height) / 2;
55+
// Map that describes the padding for form-fields with label.
56+
$with-label-padding: (
57+
top: $mat-form-field-with-label-input-padding-top - $vertical-deduction,
58+
bottom: $mat-form-field-with-label-input-padding-bottom - $vertical-deduction,
59+
);
60+
// Map that describes the padding for form-fields without label.
61+
$no-label-padding: (
62+
top: $mat-form-field-no-label-padding-top - $vertical-deduction,
63+
bottom: $mat-form-field-no-label-padding-bottom - $vertical-deduction,
64+
);
65+
66+
// We add a minimum height to the infix container in order to ensure that custom controls have
67+
// the same default vertical space as text-field inputs (with respect to the vertical padding).
68+
.mat-mdc-form-field-infix {
69+
min-height: $height;
70+
}
71+
72+
// By default, MDC aligns the label using percentage. This will be overwritten based
73+
// on whether a textarea is used. This is not possible in our implementation of the
74+
// form-field because we do not know what type of form-field control is set up. Hence
75+
// we always use a fixed position for the label. This does not have any implications.
76+
.mat-mdc-form-field .mat-mdc-text-field-wrapper .mdc-floating-label {
77+
top: $height / 2;
78+
}
79+
80+
// For the outline appearance, we re-create the active floating label transform. This is
81+
// necessary because the transform for docked floating labels can be updated to account for
82+
// the width of prefix container. We need to re-create these styles with `!important` because
83+
// the horizontal adjustment for the label is applied through inline styles, and we want to
84+
// make sure that the label can still float as expected. It should be okay using `!important`
85+
// because it's unlikely that developers commonly overwrite the floating label transform.
86+
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded
87+
.mdc-floating-label--float-above {
88+
$outlined-label-floating-position-y: mdc-text-field-get-outlined-label-position-y($height);
89+
// This transform has been extracted from the MDC text-field styles. We can't access it
90+
// through a variable because MDC generates this label transform through a mixin.
91+
transform: translateY(-$outlined-label-floating-position-y) scale(0.75) !important;
92+
}
93+
94+
// Add vertical spacing to the infix to ensure that outlined form fields have their controls
95+
// aligned as if there is no label. This is done similarly in MDC and is specified in the
96+
// Material Design specification. Outline form fields position the control as if there is no
97+
// label. This is because the label overflows the form-field and doesn't need space at the top.
98+
@include _mat-form-field-infix-vertical-spacing-outlined($no-label-padding);
99+
100+
// MDC hides labels for filled form fields when the form field height decreases. We match
101+
// this behavior in our custom density styles.
102+
@if $hide-filled-floating-label {
103+
// Update the spacing for filled form fields to account for the hidden floating label.
104+
@include _mat-form-field-infix-vertical-spacing-filled($no-label-padding, $no-label-padding);
105+
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mdc-floating-label {
106+
display: none;
107+
}
108+
}
109+
@else {
110+
// By default, filled form fields align their controls differently based on whether there
111+
// is a label or not. MDC does this too, but we cannot rely on their styles as we support
112+
// arbitrary form field controls and MDC only applies their spacing to the `<input>` elements.
113+
@include _mat-form-field-infix-vertical-spacing-filled($with-label-padding, $no-label-padding);
114+
}
115+
}

src/material-experimental/mdc-form-field/_form-field-sizing.scss

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
// and just hard-codes it into their styles.
55
$mat-form-field-outline-top-spacing: 12px;
66

7-
// Baseline based on the default height of the MDC text-field.
8-
$mat-form-field-baseline: $mdc-text-field-height / 2;
9-
107
// Infix stretches to fit the container, but naturally wants to be this wide. We set
118
// this in order to have a a consistent natural size for the various types of controls
129
// that can go in a form field.

src/material-experimental/mdc-form-field/_form-field-theme.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
@use '@material/ripple/mixins' as mdc-ripple;
22

3+
@import '@material/density/functions.import';
34
@import '@material/theme/variables.import';
45
@import '@material/textfield/mixins.import';
6+
@import '@material/textfield/variables.import';
57
@import '../mdc-helpers/mdc-helpers';
8+
@import 'form-field-density';
69
@import 'form-field-subscript';
710
@import 'form-field-focus-overlay';
811
@import 'form-field-native-select';
@@ -68,7 +71,9 @@
6871
}
6972
}
7073

71-
@mixin mat-mdc-form-field-density($density-scale) {}
74+
@mixin mat-mdc-form-field-density($density-scale) {
75+
@include _mat-form-field-density($density-scale);
76+
}
7277

7378
@mixin mat-mdc-form-field-theme($theme) {
7479
$color: mat-get-color-config($theme);

src/material-experimental/mdc-form-field/_mdc-text-field-structure-overrides.scss

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,6 @@
3838
height: auto;
3939
}
4040

41-
// MDC adds vertical spacing to inputs. We removed this spacing and intend to add it
42-
// to the infix container. This is necessary to ensure that custom form-field controls
43-
// also have the proper Material Design spacing to the label and bottom-line.
44-
.mat-mdc-text-field-wrapper .mat-mdc-form-field-infix {
45-
// Apply the default text-field input padding to the infix container. We removed the
46-
// padding from the input elements in order to support arbitrary form-field controls.
47-
padding-top: $mat-form-field-with-label-input-padding-top;
48-
padding-bottom: $mat-form-field-with-label-input-padding-bottom;
49-
}
50-
51-
// MDC changes the vertical spacing of the input if there is no label, or in the outline
52-
// appearance. This is because the input should vertically align with other inputs which use
53-
// a floating label. To achieve this, we add custom vertical spacing to the infix container
54-
// that differs from the vertical spacing for text-field's with a floating label.
55-
.mdc-text-field--no-label:not(.mdc-text-field--textarea) .mat-mdc-form-field-infix,
56-
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix {
57-
padding-top: $mat-form-field-no-label-padding-top;
58-
padding-bottom: $mat-form-field-no-label-padding-bottom;
59-
}
60-
6141
// Root element of the mdc-text-field. As explained in the height overwrites above, MDC
6242
// sets a default height on the text-field root element. This is not desired since we
6343
// want the element to be able to expand as needed.
@@ -90,34 +70,13 @@
9070
right: 0;
9171
}
9272

93-
// For the outline appearance, we re-create the active floating label transform. This is
94-
// necessary because the transform for docked floating labels can be updated to account for
95-
// the width of prefix container. We need to re-create these styles with `!important` because
96-
// the horizontal adjustment for the label is applied through inline styles, and we want to
97-
// make sure that the label can still float as expected. It should be okay using `!important`
98-
// because it's unlikely that developers commonly overwrite the floating label transform.
99-
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded
100-
.mdc-floating-label--float-above {
101-
// This transform has been extracted from the MDC text-field styles. We can't access it
102-
// through a variable because MDC generates this label transform through a mixin.
103-
transform: translateY(-$mdc-text-field-outlined-label-position-y) scale(0.75) !important;
104-
}
105-
10673
// MDC sets the input elements in outline appearance to "display: flex". There seems to
10774
// be no particular reason why this is needed. We set it to "inline-block", as it otherwise
10875
// could shift the baseline.
10976
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-text-field__input {
11077
display: inline-block;
11178
}
11279

113-
// By default, MDC aligns the label using percentage. This will be overwritten based
114-
// on whether a textarea is used. This is not possible in our implementation of the
115-
// form-field because we do not know what type of form-field control is set up. Hence
116-
// we always use a fixed position for the label. This does not have any implications.
117-
.mat-mdc-text-field-wrapper .mdc-floating-label {
118-
top: $mat-form-field-baseline;
119-
}
120-
12180
// As mentioned in the override before, MDC aligns the label using percentage. This means that
12281
// MDC tries to offset the label when the parent element changes in the notched-outline. For
12382
// example, the outline stroke width changes on focus. Since we updated the label to use a fixed

src/material-experimental/mdc-form-field/form-field.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@
5555
width: $mat-form-field-default-infix-width;
5656
// Needed so that the floating label does not overlap with prefixes or suffixes.
5757
position: relative;
58-
59-
// We add a minimum height in order to ensure that custom controls have the same
60-
// default vertical space as text-field inputs (with respect to the vertical padding).
61-
min-height: $mdc-text-field-height;
6258
box-sizing: border-box;
6359
}
6460

0 commit comments

Comments
 (0)