|
| 1 | +@use 'sass:math'; |
1 | 2 | @use 'sass:map';
|
| 3 | +@use '@material/textfield' as mdc-textfield; |
2 | 4 | @use '../../token-utils';
|
3 | 5 | @use '../../../style/sass-utils';
|
| 6 | +@use '../../../theming/theming'; |
4 | 7 | @use '../../../theming/inspection';
|
5 | 8 | @use '../../../theming/palette';
|
6 | 9 |
|
@@ -86,7 +89,53 @@ $prefix: (mat, form-field);
|
86 | 89 |
|
87 | 90 | // Tokens that can be configured through Angular Material's density theming API.
|
88 | 91 | @function get-density-tokens($theme) {
|
89 |
| - @return (); |
| 92 | + $density-scale: theming.clamp-density(inspection.get-theme-density($theme), -4); |
| 93 | + $size-scale: ( |
| 94 | + 0: 56px, |
| 95 | + -1: 52px, |
| 96 | + -2: 48px, |
| 97 | + -3: 44px, |
| 98 | + -4: 36px, |
| 99 | + ); |
| 100 | + $height: map.get($size-scale, $density-scale); |
| 101 | + $hide-label: $height < mdc-textfield.$minimum-height-for-filled-label; |
| 102 | + |
| 103 | + // We computed the desired height of the form-field using the density configuration. The |
| 104 | + // spec only describes vertical spacing/alignment in non-dense mode. This means that we |
| 105 | + // cannot update the spacing to explicit numbers based on the density scale. Instead, we |
| 106 | + // determine the height reduction and equally subtract it from the default `top` and `bottom` |
| 107 | + // padding that is provided by the Material Design specification. |
| 108 | + $vertical-deduction: math.div(mdc-textfield.$height - $height, 2); |
| 109 | + |
| 110 | + // Note: these calculations are trivial enough that we could do them at runtime with `calc` |
| 111 | + // and the value of the `height` token. The problem is that because we need to hide the label |
| 112 | + // if the container becomes too short, we have to change the padding calculation. This is |
| 113 | + // complicated further by the fact that filled form fields without labels have the same |
| 114 | + // vertical padding as outlined ones. Alternatives: |
| 115 | + // 1. Using container queries to hide the label and change the padding - this doesn't work |
| 116 | + // because size container queries require setting the `container-type` property which breaks |
| 117 | + // the form field layout. We could use style queries, but they're only supported in Chrome. |
| 118 | + // 2. Monitoring the size of the label - we already have a `ResizeObserver` on the label so we |
| 119 | + // could reuse it to also check when it becomes `display: none`. This would allows us to remove |
| 120 | + // the three padding tokens. We don't do it, because it would require us to always set up |
| 121 | + // the resize observer, as opposed to currently where it's only set up for outlined form fields. |
| 122 | + // This may lead to performance regressions. |
| 123 | + // 3. Conditionally adding `::before` and `::after` to the infix with positive and negative |
| 124 | + // margin respectively - this works, but is likely to break a lot of overrides that are targeting |
| 125 | + // a specific padding. It also runs the risk of overflowing the container. |
| 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 | + ); |
90 | 139 | }
|
91 | 140 |
|
92 | 141 | // Combines the tokens generated by the above functions into a single map with placeholder values.
|
|
0 commit comments