_mdc-text-field-structure-overrides.scss 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. @use '../core/tokens/m2/mat/form-field' as tokens-mat-form-field;
  2. @use '../core/tokens/token-utils';
  3. @use '../core/style/vendor-prefixes';
  4. // TODO(b/263527625): should be removed when this is addressed on the MDC side.
  5. // MDC sets a will-change on this element, because of the animation. This can cause
  6. // scrolling performance degradation on pages with a lot of form fields so we reset it.
  7. // The animation is on a `transform` which is hardware-accelerated already.
  8. // This flag is used to re-add the `will-change` internally since removing it causes a
  9. // lot of screenshot diffs.
  10. $_enable-form-field-will-change-reset: true;
  11. // Mixin that can be included to override the default MDC text-field
  12. // styles to fit our needs. See individual comments for context on why
  13. // certain MDC styles need to be modified.
  14. @mixin private-text-field-structure-overrides() {
  15. // Unset the border set by MDC. We move the border (which serves as the Material Design
  16. // text-field bottom line) into its own element. This is necessary because we want the
  17. // bottom-line to span across the whole form-field (including prefixes and suffixes). Also
  18. // we ensure that font styles are inherited for input elements. We do this because inputs by
  19. // default have explicit font styles from the user agent, and we set the desired font styles
  20. // in the parent `mat-form-field` element (for better custom form-field control support).
  21. // Note: We increase specificity here because the MDC textfield seems to override this,
  22. // depending on the CSS order, with an affix selector joint with the input.
  23. .mat-mdc-form-field-input-control.mat-mdc-form-field-input-control {
  24. @include vendor-prefixes.smooth-font();
  25. font: inherit;
  26. letter-spacing: inherit;
  27. text-decoration: inherit;
  28. text-transform: inherit;
  29. border: none;
  30. }
  31. .mat-mdc-form-field .mat-mdc-floating-label.mdc-floating-label {
  32. @include vendor-prefixes.smooth-font();
  33. // In order to ensure proper alignment of the floating label, we reset its line-height.
  34. // The line-height is not important as the element is absolutely positioned and only has one
  35. // line of text.
  36. line-height: normal;
  37. // This allows users to focus the input by clicking the part of the label above the outline box,
  38. // and makes migration from the legacy form-field easier for tests that were depending on
  39. // clicking the label to focus the input.
  40. pointer-events: all;
  41. @if ($_enable-form-field-will-change-reset) {
  42. will-change: auto;
  43. }
  44. }
  45. .mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label {
  46. // Style the cursor the same way as the rest of the input
  47. cursor: inherit;
  48. }
  49. // Reset the height that MDC sets on native input elements. We cannot rely on their
  50. // fixed height as we handle vertical spacing differently. MDC sets a fixed height for
  51. // inputs and modifies the baseline so that the textfield matches the spec. This does
  52. // not work for us since we support arbitrary form field controls which don't necessarily
  53. // use an `input` element. We organize the vertical spacing on the infix container.
  54. .mdc-text-field--no-label:not(.mdc-text-field--textarea)
  55. .mat-mdc-form-field-input-control.mdc-text-field__input,
  56. .mat-mdc-text-field-wrapper .mat-mdc-form-field-input-control {
  57. height: auto;
  58. }
  59. // Color inputs are a special case, because setting their height to
  60. // `auto` will collapse them. The height value is an arbitrary number
  61. // which was extracted from the user agent styles of Chrome and Firefox.
  62. .mat-mdc-text-field-wrapper
  63. .mat-mdc-form-field-input-control.mdc-text-field__input[type='color'] {
  64. height: 23px;
  65. }
  66. // Root element of the mdc-text-field. As explained in the height overwrites above, MDC
  67. // sets a default height on the text-field root element. This is not desired since we
  68. // want the element to be able to expand as needed.
  69. .mat-mdc-text-field-wrapper {
  70. height: auto;
  71. flex: auto;
  72. @if ($_enable-form-field-will-change-reset) {
  73. will-change: auto;
  74. }
  75. }
  76. // The icon prefix/suffix is closer to the edge of the form-field than the infix is in a
  77. // form-field with no prefix/suffix. Therefore the standard padding has to be removed when showing
  78. // an icon prefix or suffix. We can't rely on MDC's styles for this because we use a different
  79. // structure for our form-field in order to support arbitrary height input elements.
  80. .mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper {
  81. padding-left: 0;
  82. // Signal to the TypeScript label calculation code that the label should be offset 16px less
  83. // due to resetting the padding above.
  84. --mat-mdc-form-field-label-offset-x: -16px;
  85. }
  86. .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper {
  87. padding-right: 0;
  88. }
  89. [dir='rtl'] {
  90. // Undo the above padding removals which only apply in LTR languages.
  91. .mat-mdc-text-field-wrapper {
  92. padding-left: 16px;
  93. padding-right: 16px;
  94. }
  95. // ...and apply the correct padding resets for RTL languages.
  96. .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper {
  97. padding-left: 0;
  98. }
  99. .mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper {
  100. padding-right: 0;
  101. }
  102. }
  103. // Before the switch to the tokens MDC was setting a specific placeholder color when the input
  104. // is disabled, but now there's no token for it so we need to implement it ourselves.
  105. .mat-form-field-disabled .mdc-text-field__input {
  106. @include vendor-prefixes.input-placeholder {
  107. @include token-utils.use-tokens(
  108. tokens-mat-form-field.$prefix, tokens-mat-form-field.get-token-slots()) {
  109. @include token-utils.create-token-slot(color, disabled-input-text-placeholder-color);
  110. }
  111. }
  112. }
  113. // The default MDC text-field implementation does not support labels which always float.
  114. // MDC only renders the placeholder if the input is focused. We extend this to show the
  115. // placeholder if the form-field label is set to always float.
  116. // TODO(devversion): consider getting a mixin or variables for this (currently not available).
  117. // Stylelint no-prefixes rule disabled because MDC text-field only uses "::placeholder" too.
  118. // stylelint-disable-next-line material/no-prefixes
  119. .mat-mdc-form-field-label-always-float .mdc-text-field__input::placeholder {
  120. transition-delay: 40ms;
  121. transition-duration: 110ms;
  122. opacity: 1;
  123. }
  124. // Since we moved the horizontal spacing from the input to the form-field flex container
  125. // and the MDC floating label tries to account for the horizontal spacing, we need to reset
  126. // the shifting since there is no padding the label needs to account for. Note that we do not
  127. // want do this for labels in the notched-outline since MDC keeps those labels relative to
  128. // the notched outline container, and already applies a specific horizontal spacing which
  129. // we do not want to overwrite. *Note*: We need to have increased specificity for this
  130. // override because the `right` property will be set with higher specificity in RTL mode.
  131. .mat-mdc-text-field-wrapper .mat-mdc-form-field-infix .mat-mdc-floating-label {
  132. left: auto;
  133. right: auto;
  134. }
  135. // MDC sets the input elements in outline appearance to "display: flex". There seems to
  136. // be no particular reason why this is needed. We set it to "inline-block", as it otherwise
  137. // could shift the baseline.
  138. .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-text-field__input {
  139. display: inline-block;
  140. }
  141. // As mentioned in the override before, MDC aligns the label using percentage. This means that
  142. // MDC tries to offset the label when the parent element changes in the notched-outline. For
  143. // example, the outline stroke width changes on focus. Since we updated the label to use a fixed
  144. // position, we don't need the vertical offsetting (that will shift the label incorrectly now).
  145. // Note: Increased specificity needed here since MDC overwrites the padding on `:focus`.
  146. .mat-mdc-form-field .mat-mdc-text-field-wrapper.mdc-text-field .mdc-notched-outline__notch {
  147. padding-top: 0;
  148. }
  149. // This fixes an issue where the notch appears to be thicker than the rest of the outline when
  150. // zoomed in on Chrome. The border inconsistency seems to be some kind of rendering artifact
  151. // that arises from a combination of the fact that the notch contains text, while the leading
  152. // and trailing outline do not, combined with the fact that the border is semi-transparent.
  153. // Experimentally, I discovered that adding a transparent left border fixes the inconsistency.
  154. // Note: class name is repeated to achieve sufficient specificity over the various MDC states.
  155. // (hover, focus, etc.)
  156. // TODO(mmalerba): port this fix into MDC
  157. .mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field {
  158. &.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch {
  159. border-left: 1px solid transparent;
  160. }
  161. }
  162. [dir='rtl'] .mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field {
  163. &.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch {
  164. border-left: none;
  165. border-right: 1px solid transparent;
  166. }
  167. }
  168. }