Skip to content

Commit db17910

Browse files
authored
Revert "refactor(material/form-field): tokenize density overrides (#28249)" (#28269)
This reverts commit 087cf15.
1 parent cb9c222 commit db17910

File tree

10 files changed

+174
-135
lines changed

10 files changed

+174
-135
lines changed

src/material/core/tokens/m2/mat/_form-field.scss

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
@use 'sass:math';
21
@use 'sass:map';
3-
@use '@material/textfield' as mdc-textfield;
4-
@use '@material/density' as mdc-density;
52
@use '../../token-utils';
63
@use '../../../style/sass-utils';
7-
@use '../../../theming/theming';
84
@use '../../../theming/inspection';
95
@use '../../../theming/palette';
106

@@ -90,52 +86,7 @@ $prefix: (mat, form-field);
9086

9187
// Tokens that can be configured through Angular Material's density theming API.
9288
@function get-density-tokens($theme) {
93-
$density-scale: theming.clamp-density(inspection.get-theme-density($theme), -4);
94-
$height: mdc-density.prop-value(
95-
$density-config: mdc-textfield.$density-config,
96-
$density-scale: inspection.get-theme-density($theme),
97-
$property-name: height,
98-
);
99-
$hide-label: $height < mdc-textfield.$minimum-height-for-filled-label;
100-
101-
// We computed the desired height of the form-field using the density configuration. The
102-
// spec only describes vertical spacing/alignment in non-dense mode. This means that we
103-
// cannot update the spacing to explicit numbers based on the density scale. Instead, we
104-
// determine the height reduction and equally subtract it from the default `top` and `bottom`
105-
// padding that is provided by the Material Design specification.
106-
$vertical-deduction: math.div(mdc-textfield.$height - $height, 2);
107-
108-
// Note: these calculations are trivial enough that we could do them at runtime with `calc`
109-
// and the value of the `height` token. The problem is that because we need to hide the label
110-
// if the container becomes too short, we have to change the padding calculation. This is
111-
// complicated further by the fact that filled form fields without labels have the same
112-
// vertical padding as outlined ones. Alternatives:
113-
// 1. Using container queries to hide the label and change the padding - this doesn't work
114-
// because size container queries require setting the `container-type` property which breaks
115-
// the form field layout. We could use style queries, but they're only supported in Chrome.
116-
// 2. Monitoring the size of the label - we already have a `ResizeObserver` on the label so we
117-
// could reuse it to also check when it becomes `display: none`. This would allows us to remove
118-
// the three padding tokens. We don't do it, because it would require us to always set up
119-
// the resize observer, as opposed to currently where it's only set up for outlined form fields.
120-
// This may lead to performance regressions.
121-
// 3. Conditionally adding `::before` and `::after` to the infix with positive and negative
122-
// margin respectively - this works, but is likely to break a lot of overrides that are targeting
123-
// a specific padding. It also runs the risk of overflowing the container.
124-
// TODO: switch the padding tokens to style-based container queries
125-
// when they become available in all the browsers we support.
126-
$filled-with-label-padding-top: 24px - $vertical-deduction;
127-
$filled-with-label-padding-bottom: 8px - $vertical-deduction;
128-
$vertical-padding: 16px - $vertical-deduction;
129-
130-
@return (
131-
container-height: $height,
132-
filled-label-display: if($hide-label, none, block),
133-
container-vertical-padding: $vertical-padding,
134-
filled-with-label-container-padding-top:
135-
if($hide-label, $vertical-padding, $filled-with-label-padding-top),
136-
filled-with-label-container-padding-bottom:
137-
if($hide-label, $vertical-padding, $filled-with-label-padding-bottom),
138-
);
89+
@return ();
13990
}
14091

14192
// Combines the tokens generated by the above functions into a single map with placeholder values.

src/material/form-field/BUILD.bazel

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ sass_binary(
5252
sass_library(
5353
name = "form_field_partials",
5454
srcs = [
55+
"_form-field-density.scss",
5556
"_form-field-focus-overlay.scss",
5657
"_form-field-high-contrast.scss",
5758
"_form-field-native-select.scss",
59+
"_form-field-sizing.scss",
5860
"_form-field-subscript.scss",
59-
"_mdc-text-field-density-overrides.scss",
6061
"_mdc-text-field-structure-overrides.scss",
6162
"_mdc-text-field-textarea-overrides.scss",
6263
"_user-agent-overrides.scss",
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
@use 'sass:map';
2+
@use 'sass:math';
3+
@use '@material/density' as mdc-density;
4+
@use '@material/textfield' as mdc-textfield;
5+
@use '../core/theming/inspection';
6+
7+
@use './form-field-sizing';
8+
9+
// Mixin that sets the vertical spacing for the infix container of filled form fields.
10+
// We need to apply spacing to the infix container because we removed the input padding
11+
// provided by MDC in order to support arbitrary form-field controls.
12+
@mixin _infix-vertical-spacing-filled($with-label-padding, $no-label-padding) {
13+
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-form-field-infix {
14+
padding-top: map.get($with-label-padding, top);
15+
padding-bottom: map.get($with-label-padding, bottom);
16+
}
17+
18+
.mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea)
19+
.mat-mdc-form-field-infix {
20+
padding-top: map.get($no-label-padding, top);
21+
padding-bottom: map.get($no-label-padding, bottom);
22+
}
23+
}
24+
25+
// Mixin that sets the vertical spacing for the infix container of outlined form fields.
26+
// We need to apply spacing to the infix container because we removed the input padding
27+
// provided by MDC in order to support arbitrary form-field controls.
28+
@mixin _infix-vertical-spacing-outlined($padding) {
29+
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix {
30+
padding-top: map.get($padding, top);
31+
padding-bottom: map.get($padding, bottom);
32+
}
33+
}
34+
35+
// Mixin that includes the density styles for form fields. MDC provides their own density
36+
// styles for MDC text-field which we cannot use. MDC relies on input elements to stretch
37+
// vertically when the height is reduced as per density scale. This doesn't work for our
38+
// form field since we support custom form field controls without a fixed height. Instead, we
39+
// provide spacing that makes arbitrary controls align as specified in the Material Design
40+
// specification. In order to support density, we need to adjust the vertical spacing to be
41+
// based on the density scale.
42+
@mixin private-form-field-density($theme) {
43+
// Height of the form field that is based on the current density scale.
44+
$height: mdc-density.prop-value(
45+
$density-config: mdc-textfield.$density-config,
46+
$density-scale: inspection.get-theme-density($theme),
47+
$property-name: height,
48+
);
49+
50+
// Whether floating labels for filled form fields should be hidden. MDC hides the label in
51+
// their density styles when the height decreases too much. We match their density styles.
52+
$hide-filled-floating-label: $height < mdc-textfield.$minimum-height-for-filled-label;
53+
// We computed the desired height of the form-field using the density configuration. The
54+
// spec only describes vertical spacing/alignment in non-dense mode. This means that we
55+
// cannot update the spacing to explicit numbers based on the density scale. Instead, we
56+
// determine the height reduction and equally subtract it from the default `top` and `bottom`
57+
// padding that is provided by the Material Design specification.
58+
$vertical-deduction: math.div(mdc-textfield.$height - $height, 2);
59+
// Map that describes the padding for form-fields with label.
60+
$with-label-padding: (
61+
top: form-field-sizing.$mat-form-field-with-label-input-padding-top - $vertical-deduction,
62+
bottom: form-field-sizing.$mat-form-field-with-label-input-padding-bottom - $vertical-deduction,
63+
);
64+
// Map that describes the padding for form-fields without label.
65+
$no-label-padding: (
66+
top: form-field-sizing.$mat-form-field-no-label-padding-top - $vertical-deduction,
67+
bottom: form-field-sizing.$mat-form-field-no-label-padding-bottom - $vertical-deduction,
68+
);
69+
70+
// We add a minimum height to the infix container in order to ensure that custom controls have
71+
// the same default vertical space as text-field inputs (with respect to the vertical padding).
72+
.mat-mdc-form-field-infix {
73+
min-height: $height;
74+
}
75+
76+
// By default, MDC aligns the label using percentage. This will be overwritten based
77+
// on whether a textarea is used. This is not possible in our implementation of the
78+
// form-field because we do not know what type of form-field control is set up. Hence
79+
// we always use a fixed position for the label. This does not have any implications.
80+
.mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label {
81+
top: math.div($height, 2);
82+
}
83+
84+
// For the outline appearance, we re-create the active floating label transform. This is
85+
// necessary because the transform for docked floating labels can be updated to account for
86+
// the width of prefix container.
87+
.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded
88+
.mdc-floating-label--float-above {
89+
--mat-mdc-form-field-label-transform: translateY(
90+
-#{mdc-textfield.get-outlined-label-position-y($height)})
91+
scale(var(--mat-mdc-form-field-floating-label-scale, 0.75));
92+
transform: var(--mat-mdc-form-field-label-transform);
93+
}
94+
95+
// Add vertical spacing to the infix to ensure that outlined form fields have their controls
96+
// aligned as if there is no label. This is done similarly in MDC and is specified in the
97+
// Material Design specification. Outline form fields position the control as if there is no
98+
// label. This is because the label overflows the form-field and doesn't need space at the top.
99+
@include _infix-vertical-spacing-outlined($no-label-padding);
100+
101+
// MDC hides labels for filled form fields when the form field height decreases. We match
102+
// this behavior in our custom density styles.
103+
@if $hide-filled-floating-label {
104+
// Update the spacing for filled form fields to account for the hidden floating label.
105+
@include _infix-vertical-spacing-filled(
106+
$no-label-padding, $no-label-padding);
107+
.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-floating-label {
108+
display: none;
109+
}
110+
}
111+
@else {
112+
// By default, filled form fields align their controls differently based on whether there
113+
// is a label or not. MDC does this too, but we cannot rely on their styles as we support
114+
// arbitrary form field controls and MDC only applies their spacing to the `<input>` elements.
115+
@include _infix-vertical-spacing-filled(
116+
$with-label-padding, $no-label-padding);
117+
}
118+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Top spacing of the form-field outline. MDC does not have a variable for this
2+
// and just hard-codes it into their styles.
3+
$mat-form-field-outline-top-spacing: 12px;
4+
5+
// Infix stretches to fit the container, but naturally wants to be this wide. We set
6+
// this in order to have a consistent natural size for the various types of controls
7+
// that can go in a form field.
8+
$mat-form-field-default-infix-width: 180px !default;
9+
10+
// Minimum amount of space between start and end hints in the subscript. MDC does not
11+
// have built-in support for hints.
12+
$mat-form-field-hint-min-space: 1em !default;
13+
14+
// Vertical spacing of the text-field if there is no label. MDC hard-codes the spacing
15+
// into their styles, but their spacing variables would not work for our form-field
16+
// structure anyway. This is because MDC's input elements are larger than the text, and
17+
// their padding variables are calculated with respect to the vertical empty space of the
18+
// inputs. We take the explicit numbers provided by the Material Design specification.
19+
// https://material.io/components/text-fields/#specs
20+
21+
// Vertical spacing of the text-field if there is a label. MDC hard-codes the spacing into
22+
// their styles, but their spacing variables would not work for our form-field structure anyway.
23+
// This is because MDC's alignment depends on the input element to expand to full infix height.
24+
// We allow for arbitrary form controls and support dynamic height, so we manage the control
25+
// infix alignment through padding on the infix that works for any control. We manually measure
26+
// spacing as provided by the Material Design specification. The outlined dimensions in the
27+
// spec section do not match with the text fields shown in the overview or the ones implemented
28+
// by MDC. Note that we need to account for the input box offset. See above for more context.
29+
$mat-form-field-with-label-input-padding-top: 24px;
30+
$mat-form-field-with-label-input-padding-bottom: 8px;
31+
32+
// Vertical spacing of the text-field if there is no label. We manually measure the
33+
// spacing in the specs. See comment above for padding for text fields with label. The
34+
// same reasoning applies to the padding for text fields without label.
35+
$mat-form-field-no-label-padding-bottom: 16px;
36+
$mat-form-field-no-label-padding-top: 16px;
37+
38+
// The amount of padding between the icon prefix/suffix and the infix.
39+
// This assumes that the icon will be a 24px square with 12px padding.
40+
$mat-form-field-icon-prefix-infix-padding: 4px;

src/material/form-field/_form-field-subscript.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
@use '../core/tokens/m2/mat/form-field' as tokens-mat-form-field;
55
@use '../core/tokens/token-utils';
6+
@use './form-field-sizing';
67

78
@mixin private-form-field-subscript() {
89
// Wrapper for the hints and error messages.
@@ -49,7 +50,7 @@
4950

5051
// Spacer used to make sure start and end hints have enough space between them.
5152
.mat-mdc-form-field-hint-spacer {
52-
flex: 1 0 1em;
53+
flex: 1 0 form-field-sizing.$mat-form-field-hint-min-space;
5354
}
5455

5556
// Single error message displayed beneath the form field underline.

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
@use '../core/typography/typography';
1010
@use '../core/style/sass-utils';
1111
@use '../core/tokens/token-utils';
12+
@use './form-field-density';
1213

1314
@mixin base($theme) {
1415
@if inspection.get-theme-version($theme) == 1 {
@@ -84,10 +85,7 @@
8485
@include _theme-from-tokens(inspection.get-theme-tokens($theme, density));
8586
}
8687
@else {
87-
@include sass-utils.current-selector-or-root() {
88-
@include token-utils.create-token-values(tokens-mat-form-field.$prefix,
89-
tokens-mat-form-field.get-density-tokens($theme));
90-
}
88+
@include form-field-density.private-form-field-density($theme);
9189
}
9290
}
9391

src/material/form-field/_mdc-text-field-density-overrides.scss

Lines changed: 0 additions & 60 deletions
This file was deleted.

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

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
@use '../core/tokens/m2/mat/form-field' as tokens-mat-form-field;
1616
@use '../core/tokens/m2/mdc/filled-text-field' as tokens-mdc-filled-text-field;
1717
@use '../core/tokens/m2/mdc/outlined-text-field' as tokens-mdc-outlined-text-field;
18+
@use './form-field-sizing';
1819
@use './form-field-subscript';
1920
@use './form-field-focus-overlay';
2021
@use './form-field-high-contrast';
2122
@use './form-field-native-select';
2223
@use './user-agent-overrides';
2324
@use './mdc-text-field-textarea-overrides';
2425
@use './mdc-text-field-structure-overrides';
25-
@use './mdc-text-field-density-overrides';
2626

2727
// Includes the structural styles of the components that the form field is composed of.
2828
@mixin _static-styles($query) {
@@ -57,7 +57,6 @@
5757
// MDC text-field overwrites.
5858
@include mdc-text-field-textarea-overrides.private-text-field-textarea-overrides();
5959
@include mdc-text-field-structure-overrides.private-text-field-structure-overrides();
60-
@include mdc-text-field-density-overrides.private-text-field-density-overrides();
6160

6261
// Include the subscript, focus-overlay, native select and high-contrast styles.
6362
@include form-field-subscript.private-form-field-subscript();
@@ -66,10 +65,6 @@
6665
@include form-field-high-contrast.private-form-field-high-contrast();
6766
@include user-agent-overrides.private-form-field-user-agent-overrides();
6867

69-
// The amount of padding between the icon prefix/suffix and the infix.
70-
// This assumes that the icon will be a 24px square with 12px padding.
71-
$_icon-prefix-infix-padding: 4px;
72-
7368
// Host element of the form-field. It contains the mdc-text-field wrapper
7469
// and the subscript wrapper.
7570
.mat-mdc-form-field {
@@ -149,11 +144,11 @@ $_icon-prefix-infix-padding: 4px;
149144
// icons, and therefore can't rely on MDC for these styles.
150145
.mat-mdc-form-field-icon-prefix,
151146
[dir='rtl'] .mat-mdc-form-field-icon-suffix {
152-
padding: 0 $_icon-prefix-infix-padding 0 0;
147+
padding: 0 form-field-sizing.$mat-form-field-icon-prefix-infix-padding 0 0;
153148
}
154149
.mat-mdc-form-field-icon-suffix,
155150
[dir='rtl'] .mat-mdc-form-field-icon-prefix {
156-
padding: 0 0 0 $_icon-prefix-infix-padding;
151+
padding: 0 0 0 form-field-sizing.$mat-form-field-icon-prefix-infix-padding;
157152
}
158153

159154
.mat-mdc-form-field-icon-prefix,
@@ -183,12 +178,7 @@ $_icon-prefix-infix-padding: 4px;
183178
.mat-mdc-form-field-infix {
184179
flex: auto;
185180
min-width: 0;
186-
187-
// Infix stretches to fit the container, but naturally wants to be this wide. We set
188-
// this in order to have a consistent natural size for the various types of controls
189-
// that can go in a form field.
190-
width: 180px;
191-
181+
width: form-field-sizing.$mat-form-field-default-infix-width;
192182
// Needed so that the floating label does not overlap with prefixes or suffixes.
193183
position: relative;
194184
box-sizing: border-box;

0 commit comments

Comments
 (0)