@use '@angular/cdk'; @use '../core/style/vendor-prefixes'; @use '../core/tokens/token-utils'; @use '../core/tokens/m2/mdc/filled-text-field' as tokens-mdc-filled-text-field; @use '../core/tokens/m2/mdc/outlined-text-field' as tokens-mdc-outlined-text-field; // Includes the structural styles for the form field inherited from MDC. @mixin private-text-field-structure { $filled-slots: ( tokens-mdc-filled-text-field.$prefix, tokens-mdc-filled-text-field.get-token-slots() ); $outlined-slots: ( tokens-mdc-outlined-text-field.$prefix, tokens-mdc-outlined-text-field.get-token-slots() ); .mdc-text-field { display: inline-flex; align-items: baseline; padding: 0 16px; position: relative; box-sizing: border-box; overflow: hidden; will-change: opacity, transform, color; // TODO(crisbeto): The filled form field overrides these while the outlined doesn't. // The correct thing to do would be to remove them from here and have the one based on the // token in the outlined appearance. We keep them as is for now to avoid screenshot diffs. border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .mdc-text-field__input { width: 100%; min-width: 0; border: none; border-radius: 0; background: none; padding: 0; -moz-appearance: none; -webkit-appearance: none; // TODO(crisbeto): this height gets overwritten eventually, but there are some internal // tests that depend on this being here in weird ways so we're keeping it around for now. height: 28px; // Note that while this style and the `-ms-clear` are identical, we can't combine // them because if one of them isn't supported, it'll invalidate the whole rule. &::-webkit-calendar-picker-indicator { display: none; } &::-ms-clear { display: none; } &:focus { outline: none; } &:invalid { box-shadow: none; } @include vendor-prefixes.input-placeholder { opacity: 0; } .mdc-text-field--no-label &, .mdc-text-field--focused & { @include vendor-prefixes.input-placeholder { opacity: 1; } } .mdc-text-field--disabled:not(.mdc-text-field--no-label) &.mat-mdc-input-disabled-interactive { @include vendor-prefixes.input-placeholder { opacity: 0; } } .mdc-text-field--outlined &, .mdc-text-field--filled.mdc-text-field--no-label & { height: 100%; } .mdc-text-field--outlined & { display: flex; border: none !important; background-color: transparent; } .mdc-text-field--disabled & { pointer-events: auto; } @include token-utils.use-tokens($filled-slots...) { @include _input-tokens('.mdc-text-field--filled'); } @include token-utils.use-tokens($outlined-slots...) { @include _input-tokens('.mdc-text-field--outlined'); } @include cdk.high-contrast { .mdc-text-field--disabled & { background-color: Window; } } } .mdc-text-field--filled { height: 56px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; @include token-utils.use-tokens($filled-slots...) { @include token-utils.create-token-slot(border-top-left-radius, container-shape); @include token-utils.create-token-slot(border-top-right-radius, container-shape); &:not(.mdc-text-field--disabled) { @include token-utils.create-token-slot(background-color, container-color); } &.mdc-text-field--disabled { @include token-utils.create-token-slot(background-color, disabled-container-color); } } } .mdc-text-field--outlined { height: 56px; overflow: visible; @include token-utils.use-tokens($outlined-slots...) { $shape-var: token-utils.get-token-variable(container-shape); padding-right: max(16px, #{$shape-var}); padding-left: max(16px, calc(#{$shape-var} + 4px)); [dir='rtl'] & { padding-right: max(16px, calc(#{$shape-var} + 4px)); padding-left: max(16px, #{$shape-var}); } } } .mdc-floating-label { position: absolute; left: 0; transform-origin: left top; line-height: 1.15rem; text-align: left; text-overflow: ellipsis; white-space: nowrap; cursor: text; overflow: hidden; will-change: transform; [dir='rtl'] & { right: 0; left: auto; transform-origin: right top; text-align: right; } .mdc-text-field & { top: 50%; transform: translateY(-50%); pointer-events: none; } .mdc-notched-outline & { display: inline-block; position: relative; max-width: 100%; } .mdc-text-field--outlined & { left: 4px; right: auto; } [dir='rtl'] .mdc-text-field--outlined & { left: auto; right: 4px; } .mdc-text-field--filled & { left: 16px; right: auto; } [dir='rtl'] .mdc-text-field--filled & { left: auto; right: 16px; } .mdc-text-field--disabled & { cursor: default; @include cdk.high-contrast { z-index: 1; } } .mdc-text-field--filled.mdc-text-field--no-label & { display: none; } @include token-utils.use-tokens($filled-slots...) { @include _floating-label-tokens('.mdc-text-field--filled'); } @include token-utils.use-tokens($outlined-slots...) { @include _floating-label-tokens('.mdc-text-field--outlined'); } } .mdc-floating-label--float-above { cursor: auto; transform: translateY(-106%) scale(0.75); .mdc-text-field--filled & { transform: translateY(-106%) scale(0.75); } .mdc-text-field--outlined & { transform: translateY(-37.25px) scale(1); font-size: 0.75rem; } .mdc-notched-outline & { text-overflow: clip; } .mdc-notched-outline--upgraded & { max-width: 133.3333333333%; } .mdc-text-field--outlined.mdc-notched-outline--upgraded &, .mdc-text-field--outlined .mdc-notched-outline--upgraded & { transform: translateY(-34.75px) scale(0.75); } .mdc-text-field--outlined.mdc-notched-outline--upgraded &, .mdc-text-field--outlined .mdc-notched-outline--upgraded & { font-size: 1rem; } } .mdc-floating-label--required { &:not(.mdc-floating-label--hide-required-marker)::after { margin-left: 1px; margin-right: 0; content: '*'; [dir='rtl'] & { margin-left: 0; margin-right: 1px; } } } .mdc-notched-outline { display: flex; position: absolute; top: 0; right: 0; left: 0; box-sizing: border-box; width: 100%; max-width: 100%; height: 100%; text-align: left; pointer-events: none; [dir='rtl'] & { text-align: right; } .mdc-text-field--outlined & { z-index: 1; } } .mat-mdc-notch-piece { box-sizing: border-box; height: 100%; pointer-events: none; border-top: 1px solid; border-bottom: 1px solid; .mdc-text-field--focused & { border-width: 2px; } @include token-utils.use-tokens($outlined-slots...) { // Moved out into variables because the selectors we inherited were too long. $enabled-selector: '.mdc-text-field--outlined:not(.mdc-text-field--disabled)'; $hover-selector: ':not(.mdc-text-field--focused):hover'; #{$enabled-selector} & { @include token-utils.create-token-slot(border-color, outline-color); @include token-utils.create-token-slot(border-width, outline-width); } #{$enabled-selector}#{$hover-selector} & { @include token-utils.create-token-slot(border-color, hover-outline-color); } #{$enabled-selector}.mdc-text-field--focused & { @include token-utils.create-token-slot(border-color, focus-outline-color); } .mdc-text-field--outlined.mdc-text-field--disabled & { @include token-utils.create-token-slot(border-color, disabled-outline-color); } #{$enabled-selector}.mdc-text-field--invalid & { @include token-utils.create-token-slot(border-color, error-outline-color); } #{$enabled-selector}.mdc-text-field--invalid#{$hover-selector} .mdc-notched-outline & { @include token-utils.create-token-slot(border-color, error-hover-outline-color); } #{$enabled-selector}.mdc-text-field--invalid.mdc-text-field--focused & { @include token-utils.create-token-slot(border-color, error-focus-outline-color); } #{$enabled-selector}.mdc-text-field--focused .mdc-notched-outline & { @include token-utils.create-token-slot(border-width, focus-outline-width); } } } .mdc-notched-outline__leading { border-left: 1px solid; border-right: none; border-top-right-radius: 0; border-bottom-right-radius: 0; @include token-utils.use-tokens($outlined-slots...) { @include token-utils.create-token-slot(border-top-left-radius, container-shape); @include token-utils.create-token-slot(border-bottom-left-radius, container-shape); .mdc-text-field--outlined .mdc-notched-outline & { $shape-var: token-utils.get-token-variable(container-shape); width: max(12px, #{$shape-var}); } } [dir='rtl'] & { border-left: none; border-right: 1px solid; border-bottom-left-radius: 0; border-top-left-radius: 0; @include token-utils.use-tokens($outlined-slots...) { @include token-utils.create-token-slot(border-top-right-radius, container-shape); @include token-utils.create-token-slot(border-bottom-right-radius, container-shape); } } } .mdc-notched-outline__trailing { flex-grow: 1; border-left: none; border-right: 1px solid; border-top-left-radius: 0; border-bottom-left-radius: 0; @include token-utils.use-tokens($outlined-slots...) { @include token-utils.create-token-slot(border-top-right-radius, container-shape); @include token-utils.create-token-slot(border-bottom-right-radius, container-shape); } [dir='rtl'] & { border-left: 1px solid; border-right: none; border-top-right-radius: 0; border-bottom-right-radius: 0; @include token-utils.use-tokens($outlined-slots...) { @include token-utils.create-token-slot(border-top-left-radius, container-shape); @include token-utils.create-token-slot(border-bottom-left-radius, container-shape); } } } .mdc-notched-outline__notch { flex: 0 0 auto; width: auto; @include token-utils.use-tokens($outlined-slots...) { .mdc-text-field--outlined .mdc-notched-outline & { $shape-var: token-utils.get-token-variable(container-shape); max-width: min( var(--mat-form-field-notch-max-width, 100%), calc(100% - max(12px, #{$shape-var}) * 2) ); } } .mdc-text-field--outlined .mdc-notched-outline--notched & { padding-top: 1px; } .mdc-text-field--focused.mdc-text-field--outlined .mdc-notched-outline--notched & { padding-top: 2px; } .mdc-notched-outline--notched & { padding-left: 0; padding-right: 8px; border-top: none; --mat-form-field-notch-max-width: 100%; } [dir='rtl'] .mdc-notched-outline--notched & { padding-left: 8px; padding-right: 0; } .mdc-notched-outline--no-label & { display: none; } } .mdc-line-ripple { &::before, &::after { position: absolute; bottom: 0; left: 0; width: 100%; border-bottom-style: solid; content: ''; } &::before { z-index: 1; @include token-utils.use-tokens($filled-slots...) { $enabled-field: '.mdc-text-field--filled:not(.mdc-text-field--disabled)'; @include token-utils.create-token-slot(border-bottom-width, active-indicator-height); #{$enabled-field} & { @include token-utils.create-token-slot(border-bottom-color, active-indicator-color); } #{$enabled-field}:not(.mdc-text-field--focused):hover & { @include token-utils.create-token-slot(border-bottom-color, hover-active-indicator-color); } .mdc-text-field--filled.mdc-text-field--disabled & { @include token-utils.create-token-slot( border-bottom-color, disabled-active-indicator-color ); } #{$enabled-field}.mdc-text-field--invalid & { @include token-utils.create-token-slot(border-bottom-color, error-active-indicator-color); } #{$enabled-field}.mdc-text-field--invalid:not(.mdc-text-field--focused):hover & { @include token-utils.create-token-slot( border-bottom-color, error-hover-active-indicator-color ); } } } &::after { transform: scaleX(0); opacity: 0; z-index: 2; @include token-utils.use-tokens($filled-slots...) { .mdc-text-field--filled & { @include token-utils.create-token-slot( border-bottom-width, focus-active-indicator-height ); } .mdc-text-field--filled:not(.mdc-text-field--disabled) & { @include token-utils.create-token-slot(border-bottom-color, focus-active-indicator-color); } .mdc-text-field--filled.mdc-text-field--invalid:not(.mdc-text-field--disabled) & { @include token-utils.create-token-slot( border-bottom-color, error-focus-active-indicator-color ); } } } } .mdc-line-ripple--active::after { transform: scaleX(1); opacity: 1; } .mdc-line-ripple--deactivating::after { opacity: 0; } .mdc-text-field--disabled { pointer-events: none; } } // Includes the tokens for the floating label for a specific form field variant. @mixin _floating-label-tokens($selector) { $enabled-field: '#{$selector}:not(.mdc-text-field--disabled)'; #{$enabled-field} & { @include token-utils.create-token-slot(color, label-text-color); } #{$enabled-field}.mdc-text-field--focused & { @include token-utils.create-token-slot(color, focus-label-text-color); } #{$enabled-field}:not(.mdc-text-field--focused):hover & { @include token-utils.create-token-slot(color, hover-label-text-color); } #{$selector}.mdc-text-field--disabled & { @include token-utils.create-token-slot(color, disabled-label-text-color); } #{$enabled-field}.mdc-text-field--invalid & { @include token-utils.create-token-slot(color, error-label-text-color); } #{$enabled-field}.mdc-text-field--invalid.mdc-text-field--focused & { @include token-utils.create-token-slot(color, error-focus-label-text-color); } #{$enabled-field}.mdc-text-field--invalid:not(.mdc-text-field--disabled):hover & { @include token-utils.create-token-slot(color, error-hover-label-text-color); } #{$selector} & { @include token-utils.create-token-slot(font-family, label-text-font); @include token-utils.create-token-slot(font-size, label-text-size); @include token-utils.create-token-slot(font-weight, label-text-weight); @include token-utils.create-token-slot(letter-spacing, label-text-tracking); } } // Includes the tokens for the input for a specific form field variant. @mixin _input-tokens($selector) { #{$selector}:not(.mdc-text-field--disabled) & { @include token-utils.create-token-slot(color, input-text-color); @include token-utils.create-token-slot(caret-color, caret-color); @include vendor-prefixes.input-placeholder { @include token-utils.create-token-slot(color, input-text-placeholder-color); } } #{$selector}.mdc-text-field--invalid:not(.mdc-text-field--disabled) & { @include token-utils.create-token-slot(caret-color, error-caret-color); } #{$selector}.mdc-text-field--disabled & { @include token-utils.create-token-slot(color, disabled-input-text-color); } } // Includes the animation styles for the form field inherited from MDC. @mixin private-text-field-animations { $timing-curve: cubic-bezier(0.4, 0, 0.2, 1); .mdc-floating-label { transition: transform 150ms $timing-curve, color 150ms $timing-curve; } .mdc-text-field__input { transition: opacity 150ms $timing-curve; @include vendor-prefixes.input-placeholder { transition: opacity 67ms $timing-curve; } } &.mdc-text-field--no-label, &.mdc-text-field--focused { .mdc-text-field__input { @include vendor-prefixes.input-placeholder { transition-delay: 40ms; transition-duration: 110ms; } } } .mdc-text-field--filled:not(.mdc-ripple-upgraded):focus .mdc-text-field__ripple::before { transition-duration: 75ms; } .mdc-line-ripple::after { transition: transform 180ms $timing-curve, opacity 180ms $timing-curve; } .mat-mdc-form-field-hint-wrapper, .mat-mdc-form-field-error-wrapper { animation-duration: 300ms; } }