2614 lines
78 KiB
SCSS
2614 lines
78 KiB
SCSS
|
//
|
||
|
// Copyright 2017 Google Inc.
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
// of this software and associated documentation files (the "Software"), to deal
|
||
|
// in the Software without restriction, including without limitation the rights
|
||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
// copies of the Software, and to permit persons to whom the Software is
|
||
|
// furnished to do so, subject to the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be included in
|
||
|
// all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
// THE SOFTWARE.
|
||
|
//
|
||
|
|
||
|
// Selector '.mdc-*' should only be used in this project.
|
||
|
// stylelint-disable selector-class-pattern --
|
||
|
// TODO: document why this disable is neccessary
|
||
|
|
||
|
@use 'sass:math';
|
||
|
@use 'sass:list';
|
||
|
@use 'sass:meta';
|
||
|
@use '@material/animation/animation';
|
||
|
@use '@material/density/functions' as density-functions;
|
||
|
@use '@material/dom/dom';
|
||
|
@use '@material/floating-label/mixins' as floating-label-mixins;
|
||
|
@use '@material/floating-label/variables' as floating-label-variables;
|
||
|
@use '@material/line-ripple/mixins' as line-ripple-mixins;
|
||
|
@use '@material/notched-outline/mixins' as notched-outline-mixins;
|
||
|
@use '@material/notched-outline/variables' as notched-outline-variables;
|
||
|
@use '@material/ripple/ripple';
|
||
|
@use '@material/ripple/ripple-theme';
|
||
|
@use '@material/theme/custom-properties';
|
||
|
@use '@material/theme/theme';
|
||
|
@use '@material/shape/mixins' as shape-mixins;
|
||
|
@use '@material/shape/functions' as shape-functions;
|
||
|
@use '@material/feature-targeting/feature-targeting';
|
||
|
@use '@material/typography/typography';
|
||
|
@use 'helper-text/mixins' as helper-text-mixins;
|
||
|
@use 'character-counter/mixins' as character-counter-mixins;
|
||
|
@use 'icon/mixins' as icon-mixins;
|
||
|
@use 'icon/variables' as icon-variables;
|
||
|
@use './variables';
|
||
|
@use '@material/rtl/rtl';
|
||
|
|
||
|
@mixin core-styles($query: feature-targeting.all()) {
|
||
|
@include ripple($query);
|
||
|
@include without-ripple($query);
|
||
|
@include helper-text-mixins.helper-text-core-styles($query);
|
||
|
@include character-counter-mixins.character-counter-core-styles($query);
|
||
|
@include icon-mixins.icon-core-styles($query);
|
||
|
}
|
||
|
|
||
|
@mixin without-ripple($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
// Baseline
|
||
|
// postcss-bem-linter: define text-field
|
||
|
.mdc-text-field {
|
||
|
@include _base($query);
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include _input($query);
|
||
|
|
||
|
@include placeholder-selector_ {
|
||
|
@include _input-placeholder($query);
|
||
|
}
|
||
|
|
||
|
// Always show placeholder for text fields that has no
|
||
|
// label and show only on focused state when label is present.
|
||
|
.mdc-text-field--no-label &,
|
||
|
.mdc-text-field--focused & {
|
||
|
@include placeholder-selector_ {
|
||
|
@include _input-placeholder-visible($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix {
|
||
|
@include _affix($query: $query);
|
||
|
|
||
|
.mdc-text-field--label-floating &,
|
||
|
.mdc-text-field--no-label & {
|
||
|
@include _affix-visible($query: $query);
|
||
|
}
|
||
|
|
||
|
// Safari only
|
||
|
@supports (-webkit-hyphens: none) {
|
||
|
.mdc-text-field--outlined & {
|
||
|
@include _centered-affix-safari-support($query: $query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--prefix {
|
||
|
@include _prefix($query: $query);
|
||
|
|
||
|
.mdc-text-field--end-aligned & {
|
||
|
@include _prefix-end-aligned($query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--suffix {
|
||
|
@include _suffix($query: $query);
|
||
|
|
||
|
.mdc-text-field--end-aligned & {
|
||
|
@include _suffix-end-aligned($query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Variants
|
||
|
|
||
|
.mdc-text-field--filled {
|
||
|
@include _filled($query);
|
||
|
|
||
|
&.mdc-text-field--no-label {
|
||
|
@include _filled-no-label($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--outlined {
|
||
|
@include outlined_($query);
|
||
|
|
||
|
.mdc-notched-outline {
|
||
|
@include _outlined-notched-outline($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Other Variations
|
||
|
|
||
|
.mdc-text-field--textarea {
|
||
|
@include textarea_($query);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include _textarea-input($query);
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--filled {
|
||
|
@include _textarea-filled($query);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include _textarea-filled-input($query);
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--no-label {
|
||
|
.mdc-text-field__input {
|
||
|
@include _textarea-filled-no-label-input($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--outlined {
|
||
|
@include _textarea-outlined($query);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include _textarea-outlined-input($query);
|
||
|
}
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include _textarea-outlined-floating-label($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--with-internal-counter {
|
||
|
.mdc-text-field__input {
|
||
|
@include _textarea-input-with-internal-counter($query);
|
||
|
}
|
||
|
|
||
|
.mdc-text-field-character-counter {
|
||
|
@include _textarea-internal-counter($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Resizer element does not need to be under mdc-text-field--textarea, that
|
||
|
// just adds specificity
|
||
|
.mdc-text-field__resizer {
|
||
|
@include _textarea-resizer($query);
|
||
|
|
||
|
.mdc-text-field--filled & {
|
||
|
@include _textarea-filled-resizer($query);
|
||
|
|
||
|
.mdc-text-field__input,
|
||
|
.mdc-text-field-character-counter {
|
||
|
@include _textarea-filled-resizer-children($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--outlined & {
|
||
|
@include _textarea-outlined-resizer($query);
|
||
|
|
||
|
.mdc-text-field__input,
|
||
|
.mdc-text-field-character-counter {
|
||
|
@include _textarea-outlined-resizer-children($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--with-leading-icon {
|
||
|
@include _padding-horizontal-with-leading-icon($query);
|
||
|
|
||
|
&.mdc-text-field--filled {
|
||
|
@include with-leading-icon_($query);
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--outlined {
|
||
|
@include outlined-with-leading-icon_($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--with-trailing-icon {
|
||
|
@include _padding-horizontal-with-trailing-icon($query);
|
||
|
|
||
|
&.mdc-text-field--filled {
|
||
|
@include _with-trailing-icon($query);
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--outlined {
|
||
|
@include _outlined-with-trailing-icon($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon {
|
||
|
@include _padding-horizontal-with-both-icons($query);
|
||
|
|
||
|
&.mdc-text-field--filled {
|
||
|
@include _with-leading-and-trailing-icon($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// postcss-bem-linter: define text-field-helper-text
|
||
|
// stylelint-disable plugin/selector-bem-pattern --
|
||
|
// TODO: document why this disable is neccessary
|
||
|
.mdc-text-field-helper-line {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
display: flex;
|
||
|
justify-content: space-between;
|
||
|
box-sizing: border-box;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field + & {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
padding-right: variables.$helper-line-padding;
|
||
|
padding-left: variables.$helper-line-padding;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// stylelint-enable plugin/selector-bem-pattern
|
||
|
// postcss-bem-linter: end
|
||
|
|
||
|
// mdc-form-field tweaks to align text field label correctly
|
||
|
// stylelint-disable selector-max-type --
|
||
|
// TODO: document why this disable is neccessary
|
||
|
.mdc-form-field > .mdc-text-field + label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
align-self: flex-start;
|
||
|
}
|
||
|
}
|
||
|
// stylelint-enable selector-max-type
|
||
|
|
||
|
// States
|
||
|
.mdc-text-field--focused {
|
||
|
@include focused_($query);
|
||
|
|
||
|
&.mdc-text-field--outlined {
|
||
|
@include _focused-outlined($query);
|
||
|
|
||
|
&.mdc-text-field--textarea {
|
||
|
@include _focused-outlined-textarea($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--invalid {
|
||
|
@include invalid_($query);
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--disabled {
|
||
|
@include disabled_($query);
|
||
|
|
||
|
&.mdc-text-field--filled {
|
||
|
@include _disabled-filled($query);
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include _disabled-input($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--end-aligned {
|
||
|
@include end-aligned_($query);
|
||
|
}
|
||
|
|
||
|
.mdc-text-field--ltr-text {
|
||
|
@include _ltr-text($query);
|
||
|
|
||
|
&.mdc-text-field--end-aligned {
|
||
|
@include _ltr-text-end-aligned($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This API is intended for use by frameworks that may want to separate the ripple-related styles
|
||
|
// from the other text field styles. It is recommended that most users use `mdc-text-field-core-styles` instead.
|
||
|
@mixin ripple($query: feature-targeting.all()) {
|
||
|
@include ripple.common($query); // COPYBARA_COMMENT_THIS_LINE
|
||
|
|
||
|
.mdc-text-field--filled {
|
||
|
@include ripple.surface(
|
||
|
$query: $query,
|
||
|
$ripple-target: variables.$ripple-target
|
||
|
);
|
||
|
@include ripple.radius-bounded(
|
||
|
$query: $query,
|
||
|
$ripple-target: variables.$ripple-target
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#{variables.$ripple-target} {
|
||
|
@include ripple.target-common($query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets density scale for default text field variant.
|
||
|
///
|
||
|
/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
|
||
|
/// `-3`, `-2`, `-1`, `0`. Default is `0`.
|
||
|
/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
|
||
|
/// filled textfields at which to allow floating labels.
|
||
|
///
|
||
|
@mixin density(
|
||
|
$density-scale,
|
||
|
$minimum-height-for-filled-label: variables.$minimum-height-for-filled-label,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
|
||
|
@include height(
|
||
|
$height,
|
||
|
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
|
||
|
$query: $query
|
||
|
);
|
||
|
// TODO(b/151839219): resize icons and adjust label position
|
||
|
// @if $density-scale < 0 {
|
||
|
// @include icon-mixins.size(icon-variables.$dense-icon-size);
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets density scale for outlined text field (Excluding outlined text field with leading icon).
|
||
|
///
|
||
|
/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
|
||
|
/// `-3`, `-2`, `-1`, `0`. Default is `0`.
|
||
|
///
|
||
|
@mixin outlined-density($density-scale, $query: feature-targeting.all()) {
|
||
|
$height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
|
||
|
@include outlined-height($height, $query: $query);
|
||
|
// TODO(b/151839219): resize icons and adjust label position
|
||
|
// @if $density-scale < 0 {
|
||
|
// @include icon-mixins.size(icon-variables.$dense-icon-size);
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets density scale for outlined text field with leading icon.
|
||
|
///
|
||
|
/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
|
||
|
/// `-3`, `-2`, `-1`, `0`. Default is `0`.
|
||
|
///
|
||
|
@mixin outlined-with-leading-icon-density(
|
||
|
$density-scale,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
|
||
|
@include outlined-with-leading-icon-height($height, $query: $query);
|
||
|
// TODO(b/151839219): resize icons and adjust label position
|
||
|
// @if $density-scale < 0 {
|
||
|
// @include icon-mixins.size(icon-variables.$dense-icon-size);
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets density scale for filled textarea.
|
||
|
///
|
||
|
/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
|
||
|
/// `-3`, `-2`, `-1`, `0`. Default is `0`.
|
||
|
///
|
||
|
@mixin filled-textarea-density(
|
||
|
$density-scale,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$textfield-height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
$no-label-margin-top: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-filled-no-label-density-config,
|
||
|
$density-scale: math.div($density-scale, 2),
|
||
|
$property-name: margin-top,
|
||
|
);
|
||
|
$no-label-margin-bottom: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-filled-no-label-density-config,
|
||
|
$density-scale: math.div($density-scale, 2),
|
||
|
$property-name: margin-bottom,
|
||
|
);
|
||
|
|
||
|
// Textarea mixins require two modifier classes since two are used internally
|
||
|
// for styles (textarea and filled). An extra class is added for the public
|
||
|
// mixin so that only a single public class is needed for specificity.
|
||
|
&.mdc-text-field--filled {
|
||
|
.mdc-text-field__resizer {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
min-height: $textfield-height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@if $density-scale >= -1 {
|
||
|
$keyframe-suffix: text-field-filled-#{$density-scale};
|
||
|
$label-top: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-filled-label-density-config,
|
||
|
$density-scale: math.div($density-scale, 2),
|
||
|
$property-name: top,
|
||
|
);
|
||
|
|
||
|
// Adjust the floating position and animation/keyframes of the floating
|
||
|
// label by the new position of the resting label
|
||
|
$label-top-difference: variables.$textarea-outlined-label-top -
|
||
|
$label-top;
|
||
|
|
||
|
// Floating label position
|
||
|
@include floating-label-mixins.float-position(
|
||
|
variables.$textarea-filled-label-position-y - $label-top-difference,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label animation
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
$keyframe-suffix,
|
||
|
$query: $query
|
||
|
);
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
$keyframe-suffix,
|
||
|
variables.$textarea-filled-label-position-y - $label-top-difference,
|
||
|
0%,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Resting label position
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
top: $label-top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$margin-bottom: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-filled-density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: margin-bottom,
|
||
|
);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-bottom: $margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
} @else {
|
||
|
// The textarea is too dense to show a floating label
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
display: none;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-top: $no-label-margin-top;
|
||
|
margin-bottom: $no-label-margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--no-label {
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-top: $no-label-margin-top;
|
||
|
margin-bottom: $no-label-margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--with-internal-counter {
|
||
|
.mdc-text-field__input {
|
||
|
// Space between textarea and internal counter should not be affected
|
||
|
@include _textarea-input-with-internal-counter($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets density scale for outlined textarea.
|
||
|
///
|
||
|
/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
|
||
|
/// `-3`, `-2`, `-1`, `0`. Default is `0`.
|
||
|
///
|
||
|
@mixin outlined-textarea-density(
|
||
|
$density-scale,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$keyframe-suffix: text-field-outlined-#{$density-scale};
|
||
|
$label-top: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-outlined-label-density-config,
|
||
|
$density-scale: math.div($density-scale, 2),
|
||
|
$property-name: top,
|
||
|
);
|
||
|
$textfield-height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
$margin-top: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-outlined-density-config,
|
||
|
$density-scale: math.div($density-scale, 2),
|
||
|
$property-name: margin-top,
|
||
|
);
|
||
|
$margin-bottom: density-functions.prop-value(
|
||
|
$density-config: variables.$textarea-outlined-density-config,
|
||
|
$density-scale: math.div($density-scale, 2),
|
||
|
$property-name: margin-bottom,
|
||
|
);
|
||
|
|
||
|
// Textarea mixins require two modifier classes since two are used internally
|
||
|
// for styles (textarea and outlined). An extra class is added for the public
|
||
|
// mixin so that only a single public class is needed for specificity.
|
||
|
&.mdc-text-field--outlined {
|
||
|
// Adjust the floating position and animation/keyframes of the floating
|
||
|
// label by the new position of the resting label
|
||
|
$label-top-difference: variables.$textarea-outlined-label-top - $label-top;
|
||
|
|
||
|
// Floating label position
|
||
|
@include notched-outline-mixins.floating-label-float-position-absolute(
|
||
|
variables.$textarea-outlined-label-position-y - $label-top-difference,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label animation
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
$keyframe-suffix,
|
||
|
$query: $query
|
||
|
);
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
$keyframe-suffix,
|
||
|
variables.$textarea-outlined-label-position-y - $label-top-difference,
|
||
|
0%,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Resting label position
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
top: $label-top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__resizer {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
min-height: $textfield-height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-top: $margin-top;
|
||
|
margin-bottom: $margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--with-internal-counter {
|
||
|
.mdc-text-field__input {
|
||
|
// Space between textarea and internal counter should not be affected
|
||
|
@include _textarea-input-with-internal-counter($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets the minimum number of rows for a textarea a textarea may be resized to.
|
||
|
///
|
||
|
/// For IE11 this mixin can be used instead of the rows attribute.
|
||
|
///
|
||
|
/// @param {Number} $rows - The minimum number of rows for a textarea.
|
||
|
/// @param {Number} $line-height - The line-height of the textarea.
|
||
|
///
|
||
|
@mixin textarea-min-rows(
|
||
|
$rows,
|
||
|
$line-height: variables.$textarea-line-height,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
min-height: $rows * $line-height;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets height of default text field variant.
|
||
|
///
|
||
|
/// @param {Number} $height
|
||
|
/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
|
||
|
/// filled textfields at which to allow floating labels.
|
||
|
/// @access public
|
||
|
///
|
||
|
@mixin height(
|
||
|
$height,
|
||
|
$minimum-height-for-filled-label: variables.$minimum-height-for-filled-label,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
height: $height;
|
||
|
}
|
||
|
|
||
|
@if $height < $minimum-height-for-filled-label {
|
||
|
@include _filled-no-label($query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets height of outlined text field variant (Excluding outlined text field with leading icon).
|
||
|
///
|
||
|
/// @param {Number} $height
|
||
|
/// @param {String} $keyframe-suffix - Optional suffix to use for generated
|
||
|
/// floating label keyframes
|
||
|
/// @access public
|
||
|
///
|
||
|
@mixin outlined-height(
|
||
|
$height,
|
||
|
$keyframe-suffix: text-field-outlined-#{$height},
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$positionY: variables.get-outlined-label-position-y($height);
|
||
|
|
||
|
// Floating label position
|
||
|
@include notched-outline-mixins.floating-label-float-position-absolute(
|
||
|
$positionY,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label animation
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
$keyframe-suffix,
|
||
|
$query: $query
|
||
|
);
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
$keyframe-suffix,
|
||
|
$positionY,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
height: $height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets height of outlined text field with leading icon variant.
|
||
|
///
|
||
|
/// @param {Number} $height
|
||
|
/// @param {String} $keyframe-suffix - Optional suffix to use for generated
|
||
|
/// floating label keyframes
|
||
|
/// @access public
|
||
|
///
|
||
|
@mixin outlined-with-leading-icon-height(
|
||
|
$height,
|
||
|
$keyframe-suffix: null,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
// This extra specificity is needed because textfield applies the below mixin
|
||
|
// already to two selectors (outlined + with-leading-icon). To override
|
||
|
// them with a new label position and animation, another selector is needed.
|
||
|
&.mdc-text-field--outlined {
|
||
|
@include _outlined-with-leading-icon-floating-label-position-animation(
|
||
|
$height,
|
||
|
$keyframe-suffix,
|
||
|
$query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
height: $height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Mixin that sets the floating label position and animations for a given height.
|
||
|
// This mixin is separate to allow outlined-with-leading-icon-height() to
|
||
|
// provide greater specificity over the default mixin that adds styles for
|
||
|
// outlined with leading icons.
|
||
|
@mixin _outlined-with-leading-icon-floating-label-position-animation(
|
||
|
$height,
|
||
|
$keyframe-suffix: text-field-outlined-with-leading-icon-#{$height},
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$positionY: variables.get-outlined-label-position-y($height);
|
||
|
|
||
|
// Floating label position
|
||
|
@include notched-outline-mixins.floating-label-float-position-absolute(
|
||
|
$positionY,
|
||
|
variables.$outlined-with-leading-icon-label-position-x,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label animation
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
$keyframe-suffix,
|
||
|
$query: $query
|
||
|
);
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
$keyframe-suffix,
|
||
|
$positionY,
|
||
|
variables.$outlined-with-leading-icon-label-position-x,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$keyframe-suffix-rtl: #{$keyframe-suffix}-rtl;
|
||
|
@include rtl.rtl {
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
$keyframe-suffix,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
$keyframe-suffix-rtl,
|
||
|
$positionY,
|
||
|
-(variables.$outlined-with-leading-icon-label-position-x),
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets shape radius of default text field variant.
|
||
|
///
|
||
|
/// @param {Number} $radius Shape radius value in `px` or in percentage.
|
||
|
/// @param {Number} $text-field-height Height of default text field variant. Required only when `$radius` is in
|
||
|
/// percentage unit and if text field has custom height. Defaults to `variables.$height`.
|
||
|
/// @param {Boolean} $rtl-reflexive Set to true to flip shape radius in RTL context. Defaults to `false`.
|
||
|
///
|
||
|
@mixin shape-radius(
|
||
|
$radius,
|
||
|
$density-scale: variables.$density-scale,
|
||
|
$rtl-reflexive: false,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
@if meta.type-of($radius) == 'list' and list.length($radius) > 2 {
|
||
|
@error "mdc-textfield: Invalid radius #{$radius}. Only top-left and top-right corners may be customized.";
|
||
|
}
|
||
|
|
||
|
$height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
|
||
|
$masked-radius: shape-functions.mask-radius($radius, 1 1 0 0);
|
||
|
|
||
|
@include shape-mixins.radius(
|
||
|
$masked-radius,
|
||
|
$rtl-reflexive,
|
||
|
$component-height: $height,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@mixin textarea-shape-radius(
|
||
|
$radius,
|
||
|
$rtl-reflexive: false,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
@include notched-outline-mixins.shape-radius(
|
||
|
$radius,
|
||
|
$rtl-reflexive,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the text entered into an enabled text field.
|
||
|
/// @param {Color} $color - The desired input text color.
|
||
|
///
|
||
|
@mixin ink-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include ink-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the entered text in a disabled text field.
|
||
|
/// @param {Color} $color - The desired input text color.
|
||
|
///
|
||
|
@mixin disabled-ink-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include ink-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the placeholder in an enabled text field.
|
||
|
/// @param {Color} $color - The desired placeholder text color.
|
||
|
///
|
||
|
@mixin placeholder-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include placeholder-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the placeholder in a disabled text field.
|
||
|
/// @param {Color} $color - The desired placeholder text color.
|
||
|
///
|
||
|
@mixin disabled-placeholder-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include placeholder-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the background color of the text field or textarea when enabled.
|
||
|
/// @param {Color} $color - The desired background color.
|
||
|
///
|
||
|
@mixin fill-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include fill-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the background color of the text field or textarea when disabled.
|
||
|
/// @param {Color} $color - The desired background color.
|
||
|
///
|
||
|
@mixin disabled-fill-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include fill-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the text field bottom line color for the filled variant.
|
||
|
/// @param {Color} $color - The desired bottom line color.
|
||
|
///
|
||
|
@mixin bottom-line-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include bottom-line-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the disabled text field bottom line color for the filled variant.
|
||
|
/// @param {Color} $color - The desired bottom line color.
|
||
|
///
|
||
|
@mixin disabled-bottom-line-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include bottom-line-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the hover text field bottom line color for the filled variant.
|
||
|
/// @param {Color} $color - The desired bottom line color.
|
||
|
///
|
||
|
@mixin hover-bottom-line-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include hover-bottom-line-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the default line ripple of the text field.
|
||
|
/// @param {Color} $color - The desired line ripple color.
|
||
|
///
|
||
|
@mixin line-ripple-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include line-ripple-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the text color of the label in an enabled text field.
|
||
|
/// @param {Color} $color - The desired label text color.
|
||
|
///
|
||
|
@mixin label-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include label-ink-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the text color of the label in a disabled text field.
|
||
|
/// @param {Color} $color - The desired label text color.
|
||
|
///
|
||
|
@mixin disabled-label-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include label-ink-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the border color of the outlined text field or textarea.
|
||
|
/// @param {Color} $color - The desired outline border color.
|
||
|
///
|
||
|
@mixin outline-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include notched-outline-mixins.color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the outline border color when the text field or textarea is hovered.
|
||
|
/// @param {Color} $color - The desired outline border color.
|
||
|
///
|
||
|
@mixin hover-outline-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include hover-outline-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the outline border color when the text field or textarea is focused.
|
||
|
/// @param {Color} $color - The desired outline border color.
|
||
|
///
|
||
|
@mixin focused-outline-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include focused-outline-color_($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the outline border color when the text field or textarea is disabled.
|
||
|
/// @param {Color} $color - The desired outline border color.
|
||
|
///
|
||
|
@mixin disabled-outline-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include notched-outline-mixins.color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the caret color of the text field or textarea.
|
||
|
/// @param {Color} $color - The desired caret color.
|
||
|
///
|
||
|
@mixin caret-color($color, $query: feature-targeting.all()) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-color) {
|
||
|
@include theme.prop(caret-color, $color);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the prefix text for an enabled text field.
|
||
|
/// @param {Color} $color - The desired prefix text color.
|
||
|
///
|
||
|
@mixin prefix-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include _prefix-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the prefix text for a disabled text field.
|
||
|
/// @param {Color} $color - The desired prefix text color.
|
||
|
///
|
||
|
@mixin disabled-prefix-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include _prefix-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the suffix text for an enabled text field.
|
||
|
/// @param {Color} $color - The desired suffix text color.
|
||
|
///
|
||
|
@mixin suffix-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-enabled_ {
|
||
|
@include _suffix-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Customizes the color of the suffix text for a disabled text field.
|
||
|
/// @param {Color} $color - The desired suffix text color.
|
||
|
///
|
||
|
@mixin disabled-suffix-color($color, $query: feature-targeting.all()) {
|
||
|
@include if-disabled_ {
|
||
|
@include _suffix-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets shape radius of outlined text field variant.
|
||
|
///
|
||
|
/// @param {Number} $radius Shape radius value in `px` or in percentage.
|
||
|
/// @param {Number} $text-field-height Height of outlined text field variant. Required only when `$radius` is in
|
||
|
/// percentage unit and if text field has custom height. Defaults to `variables.$height`.
|
||
|
/// @param {Boolean} $rtl-reflexive Set to true to flip shape radius in RTL context. Defaults to `false`.
|
||
|
///
|
||
|
@mixin outline-shape-radius(
|
||
|
$radius,
|
||
|
$density-scale: variables.$density-scale,
|
||
|
$rtl-reflexive: false,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$height: density-functions.prop-value(
|
||
|
$density-config: variables.$density-config,
|
||
|
$density-scale: $density-scale,
|
||
|
$property-name: height,
|
||
|
);
|
||
|
|
||
|
.mdc-notched-outline {
|
||
|
@include notched-outline-mixins.shape-radius(
|
||
|
$radius,
|
||
|
$rtl-reflexive,
|
||
|
$component-height: $height,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$resolved-radius: shape-functions.resolve-radius(
|
||
|
$radius,
|
||
|
$component-height: $height
|
||
|
);
|
||
|
$unpacked-radius: shape-functions.unpack-radius($resolved-radius);
|
||
|
$top-left-radius: list.nth($unpacked-radius, 1);
|
||
|
$top-left-is-custom-prop: custom-properties.is-custom-prop($top-left-radius);
|
||
|
$top-left-radius-px: $top-left-radius;
|
||
|
@if ($top-left-is-custom-prop) {
|
||
|
$top-left-radius-px: custom-properties.get-fallback($top-left-radius);
|
||
|
}
|
||
|
$top-right-radius: list.nth($unpacked-radius, 2);
|
||
|
$top-right-is-custom-prop: custom-properties.is-custom-prop(
|
||
|
$top-right-radius
|
||
|
);
|
||
|
|
||
|
@if (
|
||
|
$top-left-is-custom-prop or
|
||
|
$top-right-is-custom-prop or
|
||
|
$top-left-radius-px >
|
||
|
notched-outline-variables.$leading-width
|
||
|
) {
|
||
|
// The horizontal padding only needs to be overriden from the base padding
|
||
|
// if the radius is a custom property, or if the top-left radius is a value
|
||
|
// that is large than that default notched outline's leading width.
|
||
|
@include _outline-shape-radius-horizontal-padding(
|
||
|
$top-left-radius,
|
||
|
$top-right-radius,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
+ .mdc-text-field-helper-line {
|
||
|
@include _outline-shape-radius-horizontal-padding(
|
||
|
$top-left-radius,
|
||
|
$top-right-radius,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Ensure that leading/trailing icon padding is overriden. Even if the
|
||
|
// top left/right isn't a custom property or the leading isn't larger, we
|
||
|
// still need to override. The above left/right padding rules have more
|
||
|
// specificty than the original leading/trailing icon rules, so we need to
|
||
|
// re-apply them.
|
||
|
// Additionally, if the top left/right radii _are_ custom properties, we
|
||
|
// should use those instead.
|
||
|
|
||
|
&.mdc-text-field--with-leading-icon {
|
||
|
@if ($top-right-is-custom-prop) {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-left: 0;
|
||
|
}
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-right,
|
||
|
$top-right-radius,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
@include rtl.rtl {
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-left,
|
||
|
$top-right-radius,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-right: 0;
|
||
|
}
|
||
|
}
|
||
|
} @else {
|
||
|
@include _padding-horizontal-with-leading-icon($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--with-trailing-icon {
|
||
|
@if (
|
||
|
$top-left-is-custom-prop or
|
||
|
$top-left-radius-px >
|
||
|
notched-outline-variables.$leading-width
|
||
|
) {
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-left,
|
||
|
$top-left-radius,
|
||
|
$add-label-padding: true,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-right: 0;
|
||
|
}
|
||
|
|
||
|
@include rtl.rtl {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-left: 0;
|
||
|
}
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-right,
|
||
|
$top-left-radius,
|
||
|
$add-label-padding: true,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
} @else {
|
||
|
@include _padding-horizontal-with-trailing-icon($query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon {
|
||
|
@include _padding-horizontal-with-both-icons($query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _outline-shape-radius-horizontal-padding(
|
||
|
$top-left-radius,
|
||
|
$top-right-radius,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-left,
|
||
|
$top-left-radius,
|
||
|
$add-label-padding: true,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-right,
|
||
|
$top-right-radius,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
$top-left-is-custom-prop: custom-properties.is-custom-prop($top-left-radius);
|
||
|
$top-left-radius-px: $top-left-radius;
|
||
|
@if ($top-left-is-custom-prop) {
|
||
|
$top-left-radius-px: custom-properties.get-fallback($top-left-radius);
|
||
|
}
|
||
|
$top-right-is-custom-prop: custom-properties.is-custom-prop(
|
||
|
$top-right-radius
|
||
|
);
|
||
|
$top-right-radius-px: $top-right-radius;
|
||
|
@if ($top-right-is-custom-prop) {
|
||
|
$top-right-radius-px: custom-properties.get-fallback($top-right-radius);
|
||
|
}
|
||
|
|
||
|
@if (
|
||
|
(
|
||
|
$top-left-is-custom-prop and
|
||
|
$top-right-is-custom-prop and not
|
||
|
custom-properties.are-equal($top-left-radius, $top-right-radius)
|
||
|
) or
|
||
|
$top-left-radius-px !=
|
||
|
$top-right-radius-px
|
||
|
) {
|
||
|
// Normally base horizontal padding doesn't need RTL, but if the values
|
||
|
// are different or they are two different custom properties, they need to
|
||
|
// be reversed.
|
||
|
@include rtl.rtl {
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-right,
|
||
|
$top-left-radius,
|
||
|
$add-label-padding: true,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include _apply-outline-shape-padding(
|
||
|
padding-left,
|
||
|
$top-right-radius,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _apply-outline-shape-padding(
|
||
|
$property,
|
||
|
$padding,
|
||
|
$add-label-padding: false,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$padding-is-custom-prop: custom-properties.is-custom-prop($padding);
|
||
|
$padding-px: $padding;
|
||
|
@if ($padding-is-custom-prop) {
|
||
|
$padding-px: custom-properties.get-fallback($padding);
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// The shape should only change the padding if the radius becomes greater
|
||
|
// than the default padding. That means we need to add more padding.
|
||
|
@if ($padding-px > variables.$padding-horizontal) {
|
||
|
// Set a px value if it's greater. This is either the only value (if
|
||
|
// we're given an exact value), or an IE11 fallback if we're given a
|
||
|
// custom property and the fallback value is greater than the padding.
|
||
|
$value: $padding-px;
|
||
|
@if ($add-label-padding) {
|
||
|
// If this is for the top-left leading, add the notched outline padding
|
||
|
// to keep it aligned with the label
|
||
|
$value: $padding-px + notched-outline-variables.$padding;
|
||
|
}
|
||
|
|
||
|
@include rtl.ignore-next-line();
|
||
|
#{$property}: $value;
|
||
|
@if ($padding-is-custom-prop) {
|
||
|
// Add an alternate GSS tag b/c this was an IE11 fallback and we're
|
||
|
// going to add another property with the var() value
|
||
|
/* @alternate */
|
||
|
}
|
||
|
}
|
||
|
@if ($padding-is-custom-prop) {
|
||
|
// If it's a custom property, always add it since the value may change
|
||
|
// to be greater than the padding at runtime, even if the fallback is
|
||
|
// not currently greater than the default padding.
|
||
|
$value: custom-properties.create-var($padding);
|
||
|
@if ($add-label-padding) {
|
||
|
$value: calc(#{$value} + #{notched-outline-variables.$padding});
|
||
|
}
|
||
|
|
||
|
// Interpolation is a workaround for sass/sass#3259.
|
||
|
@supports (top: max(#{0%})) {
|
||
|
// A max() function makes this runtime dynamic. The padding will be
|
||
|
// whichever is greater: the default horizontal padding, or the calculated
|
||
|
// custom property plus extra padding.
|
||
|
@include rtl.ignore-next-line();
|
||
|
#{$property}: max(#{variables.$padding-horizontal}, #{$value});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets the CSS transition for the floating label's 'float' animation.
|
||
|
///
|
||
|
/// @param {Number} $duration-ms - Duration (in ms) of the animation.
|
||
|
/// @param {String} $timing-function - Optionally overrides the default animation timing function.
|
||
|
///
|
||
|
@mixin floating-label-float-transition(
|
||
|
$duration-ms,
|
||
|
$timing-function: null,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
.mdc-floating-label {
|
||
|
@include floating-label-mixins.float-transition(
|
||
|
$duration-ms,
|
||
|
$timing-function,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets custom font size of the input.
|
||
|
///
|
||
|
/// @param {number} $font-size - Overrides the font size.
|
||
|
///
|
||
|
@mixin input-font-size($font-size, $query: feature-targeting.all()) {
|
||
|
$feat-typography: feature-targeting.create-target($query, typography);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-typography) {
|
||
|
font-size: $font-size;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Sets custom font family of the input.
|
||
|
///
|
||
|
/// @param {String} $font-family - Selected font family.
|
||
|
///
|
||
|
@mixin input-font-family($font-family, $query: feature-targeting.all()) {
|
||
|
$feat-typography: feature-targeting.create-target($query, typography);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-typography) {
|
||
|
font-family: $font-family;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Private mixins
|
||
|
|
||
|
// Base shared styles
|
||
|
@mixin _base($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
// Shape
|
||
|
@include shape-radius(variables.$shape-radius, $query: $query);
|
||
|
|
||
|
// Colors
|
||
|
@include label-color(variables.$label, $query: $query);
|
||
|
@include ink-color(variables.$ink-color, $query: $query);
|
||
|
@include placeholder-color(variables.$placeholder-ink-color, $query: $query);
|
||
|
@include caret-color(primary, $query: $query);
|
||
|
@include helper-text-mixins.helper-text-color(
|
||
|
variables.$helper-text-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include character-counter-mixins.character-counter-color(
|
||
|
variables.$helper-text-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include icon-mixins.leading-icon-color(
|
||
|
variables.$icon-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include icon-mixins.trailing-icon-color(
|
||
|
variables.$icon-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include prefix-color(variables.$affix-color, $query: $query);
|
||
|
@include suffix-color(variables.$affix-color, $query: $query);
|
||
|
|
||
|
// Floating Label
|
||
|
@include floating-label_($query);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// display and align-items are necessary to make the text field participate
|
||
|
// in baseline alignment, even though some variants are 'centered'. Those
|
||
|
// variants should use the _baseline-center-aligned() mixin
|
||
|
display: inline-flex;
|
||
|
align-items: baseline;
|
||
|
padding: 0 variables.$padding-horizontal;
|
||
|
position: relative;
|
||
|
box-sizing: border-box;
|
||
|
overflow: hidden;
|
||
|
/* @alternate */
|
||
|
will-change: opacity, transform, color;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This mixin adds styles to visually center the text within the text field.
|
||
|
// Sibling text will align to the baseline and appear centered next to the
|
||
|
// text field.
|
||
|
@mixin _baseline-center-aligned($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// In order for a flexbox container to participate in baseline alignment,
|
||
|
// it follows these rules to determine where its baseline is:
|
||
|
// https://www.w3.org/TR/css-flexbox-1/#flex-baselines
|
||
|
//
|
||
|
// In order to avoid leading icons 'controlling' the baseline (since they
|
||
|
// are the first child), flexbox will generate a baseline from any child
|
||
|
// flex items that participate in baseline alignment.
|
||
|
//
|
||
|
// Icons are set to "align-self: center", while all other children are
|
||
|
// aligned to baseline. The next problem is deciding which child is
|
||
|
// used to determine the baseline.
|
||
|
//
|
||
|
// According to spec, the item with the largest distance between its
|
||
|
// baseline and the edge of the cross axis is placed flush with that edge,
|
||
|
// making it the baseline of the container.
|
||
|
// https://www.w3.org/TR/css-flexbox-1/#baseline-participation
|
||
|
//
|
||
|
// For the filled variant, the pseudo ::before strut is the 'largest'
|
||
|
// child since the input has a height of 28px and the strut is 40px. We
|
||
|
// can emulate center alignment and force the baseline to use the input
|
||
|
// text by making the input the full height of the container and removing
|
||
|
// the baseline strut.
|
||
|
|
||
|
// IE11 does not respect this, and makes the leading icon (if present) the
|
||
|
// baseline. This is a gap with IE11 that we have accepted.
|
||
|
.mdc-text-field__input {
|
||
|
height: 100%;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _padding-horizontal-with-leading-icon($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-property(padding, 0, variables.$padding-horizontal);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _padding-horizontal-with-trailing-icon($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-property(padding, variables.$padding-horizontal, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _padding-horizontal-with-both-icons($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-left: 0;
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-right: 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin floating-label_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
top: 50%;
|
||
|
transform: translateY(-50%);
|
||
|
pointer-events: none;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Filled
|
||
|
|
||
|
@mixin _filled($query: feature-targeting.all()) {
|
||
|
// Text Field intentionally omits press ripple, so each state needs to be specified individually.
|
||
|
@include ripple-theme.states-base-color(
|
||
|
variables.$ink-color,
|
||
|
$query: $query,
|
||
|
$ripple-target: variables.$ripple-target
|
||
|
);
|
||
|
@include ripple-theme.states-hover-opacity(
|
||
|
ripple-theme.states-opacity(variables.$ink-color, hover),
|
||
|
$query: $query,
|
||
|
$ripple-target: variables.$ripple-target
|
||
|
);
|
||
|
@include ripple-theme.states-focus-opacity(
|
||
|
ripple-theme.states-opacity(variables.$ink-color, focus),
|
||
|
$query: $query,
|
||
|
$ripple-target: variables.$ripple-target
|
||
|
);
|
||
|
|
||
|
@include height(variables.$height, $query: $query);
|
||
|
@include typography.baseline-top(
|
||
|
variables.$filled-baseline-top,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include fill-color(variables.$background, $query: $query);
|
||
|
@include bottom-line-color(variables.$bottom-line-idle, $query: $query);
|
||
|
@include hover-bottom-line-color(
|
||
|
variables.$bottom-line-hover,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include line-ripple-color_(primary, $query: $query);
|
||
|
@include _filled-floating-label($query);
|
||
|
}
|
||
|
|
||
|
@mixin _filled-floating-label($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-position(left, variables.$label-offset);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@include floating-label-mixins.float-position(
|
||
|
variables.$label-position-y,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Filled variant with no label. This variant centers the text elements and
|
||
|
// hides the label and is used with there is explicitly no label provided or
|
||
|
// when the height of the text field is too small for a label to be allowed.
|
||
|
@mixin _filled-no-label($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include _baseline-center-aligned($query);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
.mdc-floating-label {
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
&::before {
|
||
|
// Remove baseline-top strut
|
||
|
display: none;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Safari only
|
||
|
@supports (-webkit-hyphens: none) {
|
||
|
.mdc-text-field__affix {
|
||
|
@include _centered-affix-safari-support($query: $query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Outlined
|
||
|
|
||
|
@mixin outlined_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include outlined-height(
|
||
|
$height: variables.$height,
|
||
|
$keyframe-suffix: text-field-outlined,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include _baseline-center-aligned($query: $query);
|
||
|
@include outline-color(variables.$outlined-idle-border, $query: $query);
|
||
|
@include hover-outline-color(
|
||
|
variables.$outlined-hover-border,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include focused-outline-color(primary, $query: $query);
|
||
|
@include outline-shape-radius(variables.$shape-radius, $query: $query);
|
||
|
@include notched-outline-mixins.notch-offset(
|
||
|
notched-outline-variables.$border-width,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include ripple-theme.states-base-color(
|
||
|
transparent,
|
||
|
$query: $query,
|
||
|
$ripple-target: variables.$ripple-target
|
||
|
);
|
||
|
@include _outlined-floating-label($query);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
overflow: visible;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// TODO(b/154349735): Investigate the neccessity of these styles
|
||
|
display: flex;
|
||
|
border: none !important; // FF adds unwanted border in HC mode on windows.
|
||
|
background-color: transparent;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _outlined-floating-label($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-position(left, notched-outline-variables.$padding);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _outlined-notched-outline($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// Force the outline to appear "above" the textfield elements, even though
|
||
|
// it is absolutely positioned and comes before the input in the DOM. This
|
||
|
// is primarily for the textarea scrollbar and resize elements, which may
|
||
|
// clip with with outline border.
|
||
|
z-index: 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// States
|
||
|
|
||
|
@mixin disabled_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include ink-color_(variables.$disabled-ink-color, $query: $query);
|
||
|
@include placeholder-color_(
|
||
|
variables.$disabled-placeholder-ink-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include label-ink-color_(variables.$disabled-label-color, $query: $query);
|
||
|
@include helper-text-mixins.helper-text-color_(
|
||
|
variables.$disabled-helper-text-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include character-counter-mixins.character-counter-color_(
|
||
|
variables.$disabled-helper-text-color,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include icon-mixins.leading-icon-color_(
|
||
|
variables.$disabled-icon,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include icon-mixins.trailing-icon-color_(
|
||
|
variables.$disabled-icon,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include _prefix-color(variables.$disabled-affix-color, $query: $query);
|
||
|
@include _suffix-color(variables.$disabled-affix-color, $query: $query);
|
||
|
|
||
|
// Mixins that are ok to include since they target variant-specific elements
|
||
|
@include bottom-line-color_(variables.$disabled-border, $query: $query);
|
||
|
@include notched-outline-mixins.color(
|
||
|
variables.$outlined-disabled-border,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
@include dom.forced-colors-mode {
|
||
|
@include placeholder-color_(GrayText, $query: $query);
|
||
|
@include label-ink-color_(GrayText, $query: $query);
|
||
|
@include helper-text-mixins.helper-text-color_(GrayText, $query: $query);
|
||
|
@include character-counter-mixins.character-counter-color_(
|
||
|
GrayText,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include icon-mixins.leading-icon-color_(GrayText, $query: $query);
|
||
|
@include icon-mixins.trailing-icon-color_(GrayText, $query: $query);
|
||
|
@include _prefix-color(GrayText, $query: $query);
|
||
|
@include _suffix-color(GrayText, $query: $query);
|
||
|
|
||
|
// Mixins that are ok to include since they target variant-specific elements
|
||
|
@include bottom-line-color_(GrayText, $query: $query);
|
||
|
@include notched-outline-mixins.color(GrayText, $query: $query);
|
||
|
}
|
||
|
|
||
|
@include dom.forced-colors-mode($exclude-ie11: true) {
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
background-color: Window;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
z-index: 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
pointer-events: none;
|
||
|
}
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
cursor: default;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _disabled-input($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// disabled inputs should still allow users to interact with them to select
|
||
|
// text and scroll for textareas
|
||
|
pointer-events: auto;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _disabled-filled($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include fill-color_(variables.$disabled-background, $query: $query);
|
||
|
|
||
|
#{variables.$ripple-target} {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// prevent ripple from displaying on hover when some interactible
|
||
|
// elements like input and resize handles are hovered
|
||
|
display: none;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin invalid_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include hover-bottom-line-color(variables.$error, $query: $query);
|
||
|
@include line-ripple-color(variables.$error, $query: $query);
|
||
|
@include label-color(variables.$error, $query: $query);
|
||
|
@include helper-text-mixins.helper-text-validation-color(
|
||
|
variables.$error,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include caret-color(variables.$error, $query: $query);
|
||
|
@include icon-mixins.trailing-icon-color(variables.$error, $query: $query);
|
||
|
|
||
|
// Mixins that are ok to include since they target variant-specific elements
|
||
|
@include bottom-line-color(variables.$error, $query: $query);
|
||
|
@include outline-color(variables.$error, $query: $query);
|
||
|
@include hover-outline-color(variables.$error, $query: $query);
|
||
|
@include focused-outline-color(variables.$error, $query: $query);
|
||
|
|
||
|
+ .mdc-text-field-helper-line .mdc-text-field-helper-text--validation-msg {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin focused_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include label-color(variables.$focused-label-color, $query: $query);
|
||
|
|
||
|
// Mixins that are ok to include since they target variant-specific elements
|
||
|
@include notched-outline-mixins.stroke-width(
|
||
|
variables.$outlined-stroke-width,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
+ .mdc-text-field-helper-line
|
||
|
.mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg) {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _focused-outlined($query: feature-targeting.all()) {
|
||
|
@include notched-outline-mixins.notch-offset(
|
||
|
variables.$outlined-stroke-width,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@mixin _focused-outlined-textarea($query: feature-targeting.all()) {
|
||
|
@include notched-outline-mixins.notch-offset(0, $query: $query);
|
||
|
}
|
||
|
|
||
|
// Icons
|
||
|
|
||
|
@mixin with-leading-icon_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
$icon-padding: icon-variables.$leading-icon-padding-left +
|
||
|
icon-variables.$icon-size + icon-variables.$leading-icon-padding-right;
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include _truncate-floating-label-max-width($icon-padding, $query: $query);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-position(left, $icon-padding);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$truncation: $icon-padding + variables.$padding-horizontal;
|
||
|
|
||
|
.mdc-floating-label--float-above {
|
||
|
@include _truncate-floating-label-floated-max-width(
|
||
|
$truncation,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _with-trailing-icon($query: feature-targeting.all()) {
|
||
|
$truncation: icon-variables.$trailing-icon-padding-left +
|
||
|
icon-variables.$icon-size + icon-variables.$trailing-icon-padding-right +
|
||
|
variables.$label-offset;
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include _truncate-floating-label-max-width($truncation, $query: $query);
|
||
|
}
|
||
|
|
||
|
.mdc-floating-label--float-above {
|
||
|
@include _truncate-floating-label-floated-max-width(
|
||
|
$truncation,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _with-leading-and-trailing-icon($query: feature-targeting.all()) {
|
||
|
$leading-icon: icon-variables.$leading-icon-padding-left +
|
||
|
icon-variables.$icon-size + icon-variables.$leading-icon-padding-right;
|
||
|
$trailing-icon: icon-variables.$trailing-icon-padding-left +
|
||
|
icon-variables.$icon-size + icon-variables.$trailing-icon-padding-right;
|
||
|
$truncation: $leading-icon + $trailing-icon;
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include _truncate-floating-label-max-width($truncation, $query: $query);
|
||
|
}
|
||
|
|
||
|
.mdc-floating-label--float-above {
|
||
|
@include _truncate-floating-label-floated-max-width(
|
||
|
$truncation,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin outlined-with-leading-icon_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
// Resting label position
|
||
|
$icon-padding: icon-variables.$leading-icon-padding-left +
|
||
|
icon-variables.$icon-size + icon-variables.$leading-icon-padding-right;
|
||
|
$left-spacing: $icon-padding - notched-outline-variables.$leading-width;
|
||
|
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-position(left, $left-spacing);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Notch width
|
||
|
$notch-truncation: $icon-padding + notched-outline-variables.$leading-width;
|
||
|
@include _truncate-notched-outline-max-width(
|
||
|
$notch-truncation,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label position and animation
|
||
|
@include _outlined-with-leading-icon-floating-label-position-animation(
|
||
|
$height: variables.$height,
|
||
|
$keyframe-suffix: text-field-outlined-leading-icon,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Applied to the outlined text field with a trailing icon
|
||
|
///
|
||
|
@mixin _outlined-with-trailing-icon($query: feature-targeting.all()) {
|
||
|
// Resting label position
|
||
|
$icon-padding: icon-variables.$trailing-icon-padding-left +
|
||
|
icon-variables.$icon-size + icon-variables.$trailing-icon-padding-right;
|
||
|
// Notch width
|
||
|
$notch-truncation: $icon-padding + notched-outline-variables.$leading-width;
|
||
|
|
||
|
@include _truncate-notched-outline-max-width(
|
||
|
$notch-truncation,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Truncates the max-width of the notched outline by the given amount
|
||
|
///
|
||
|
/// @param {Number} $truncation - Amount to truncate the notched outline max-width
|
||
|
///
|
||
|
@mixin _truncate-notched-outline-max-width(
|
||
|
$truncation,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
@include notched-outline-mixins.notch-max-width(
|
||
|
calc(100% - #{$truncation}),
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Truncates the max-width of the floating label by the given amount
|
||
|
///
|
||
|
/// @param {Number} $truncation - Amount to truncate the floating label max-width
|
||
|
///
|
||
|
@mixin _truncate-floating-label-max-width(
|
||
|
$truncation,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
@include floating-label-mixins.max-width(
|
||
|
calc(100% - #{$truncation}),
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Truncates the max-width of the floating label by the given amount while scaling by the given scale value
|
||
|
///
|
||
|
/// @param {Number} $truncation - Amount to truncate the floating label max-width
|
||
|
///
|
||
|
@mixin _truncate-floating-label-floated-max-width(
|
||
|
$truncation,
|
||
|
$query: feature-targeting.all()
|
||
|
) {
|
||
|
$scale: floating-label-variables.$float-scale;
|
||
|
@include floating-label-mixins.max-width(
|
||
|
calc(100% / #{$scale} - #{$truncation} / #{$scale}),
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Textarea
|
||
|
|
||
|
@mixin textarea_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$feat-animation: feature-targeting.create-target($query, animation);
|
||
|
|
||
|
@include _textarea-floating-label($query);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
flex-direction: column;
|
||
|
align-items: center;
|
||
|
width: auto;
|
||
|
height: auto;
|
||
|
padding: 0; // see below for explanation
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-animation) {
|
||
|
transition: none;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-resizer($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
align-self: stretch;
|
||
|
display: inline-flex;
|
||
|
flex-direction: column;
|
||
|
flex-grow: 1;
|
||
|
max-height: 100%;
|
||
|
max-width: 100%;
|
||
|
min-height: variables.$height;
|
||
|
// stylelint-disable declaration-block-no-duplicate-properties --
|
||
|
// TODO: document why this disable is neccessary
|
||
|
|
||
|
// 'stretch' is the preferred rule here. It will allow the textarea to grow
|
||
|
// to the min/max width of the container, but if an explicit width is set,
|
||
|
// it cannot be resized horizontally.
|
||
|
// Stretch is still a working draft. Chrome and Firefox have it implemented
|
||
|
// with 'available' prefixes. fit-content is another good target for
|
||
|
// Safari since it works in almost all use cases except when an explicit
|
||
|
// width is set (the user can make the textarea smaller than the container).
|
||
|
// None of this matters for IE11, which doesn't support resize.
|
||
|
min-width: fit-content;
|
||
|
/* @alternate */
|
||
|
min-width: -moz-available;
|
||
|
/* @alternate */
|
||
|
min-width: -webkit-fill-available;
|
||
|
// stylelint-enable declaration-block-no-duplicate-properties
|
||
|
overflow: hidden;
|
||
|
resize: both;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-filled-resizer($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
// Shift the resizer element up by a margin amount to make space for the
|
||
|
// resize handle. For filled elements, the resize handle directly touches
|
||
|
// the bottom line and is hard to see.
|
||
|
// Using a margin affects the width and positioning of the overall component
|
||
|
// and underlying textarea, which is why a transform is used instead.
|
||
|
$y: -1 * variables.$textarea-input-handle-margin;
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
transform: translateY($y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-filled-resizer-children($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
// See above. After shifting the resize wrapper element, all of its children
|
||
|
// should be shifted in the opposite direction (down) to compensate.
|
||
|
$y: variables.$textarea-input-handle-margin;
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
transform: translateY($y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-outlined-resizer($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
// Shift the resizer element left/up by a margin amount to make space for the
|
||
|
// resize handle. For outlined elements, the resize handle directly touches
|
||
|
// the outline and is hard to see.
|
||
|
// Using a margin affects the width and positioning of the overall component
|
||
|
// and underlying textarea, which is why a transform is used instead.
|
||
|
$x: -1 * variables.$textarea-input-handle-margin;
|
||
|
$y: -1 * variables.$textarea-input-handle-margin;
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
transform: translateX($x) translateY($y);
|
||
|
|
||
|
@include rtl.rtl {
|
||
|
// Flip the horizontal shifting direction for RTL
|
||
|
@include rtl.ignore-next-line();
|
||
|
transform: translateX(-1 * $x) translateY($y);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-outlined-resizer-children($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
// See above. After shifting the resize wrapper element, all of its children
|
||
|
// should be shifted in the opposite direction (right and down) to compensate.
|
||
|
$x: variables.$textarea-input-handle-margin;
|
||
|
$y: variables.$textarea-input-handle-margin;
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
transform: translateX($x) translateY($y);
|
||
|
|
||
|
@include rtl.rtl {
|
||
|
// Flip the horizontal shifting direction for RTL
|
||
|
@include rtl.ignore-next-line();
|
||
|
transform: translateX(-1 * $x) translateY($y);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-floating-label($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
// Resting label position
|
||
|
.mdc-floating-label {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
top: variables.$textarea-label-top;
|
||
|
}
|
||
|
|
||
|
// Resets center aligning the floating label.
|
||
|
&:not(.mdc-floating-label--float-above) {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
transform: none;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-input($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
$feat-typography: feature-targeting.create-target($query, typography);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
flex-grow: 1;
|
||
|
height: auto;
|
||
|
min-height: variables.$textarea-line-height;
|
||
|
overflow-x: hidden; // https://bugzilla.mozilla.org/show_bug.cgi?id=33654
|
||
|
overflow-y: auto;
|
||
|
box-sizing: border-box;
|
||
|
resize: none;
|
||
|
// Textarea has horizontal padding instead of the container. This allows the
|
||
|
// resize handle to extend to the edge of the container.
|
||
|
padding: 0 variables.$padding-horizontal;
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-typography) {
|
||
|
line-height: variables.$textarea-line-height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-internal-counter($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include typography.baseline-bottom(
|
||
|
variables.$textarea-internal-counter-baseline-bottom,
|
||
|
$query: $query
|
||
|
);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
align-self: flex-end;
|
||
|
// Needed since padding is on the textarea and not the container
|
||
|
padding: 0 variables.$padding-horizontal;
|
||
|
|
||
|
&::before {
|
||
|
// Remove baseline-top
|
||
|
display: none;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-input-with-internal-counter($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-bottom: variables.$textarea-internal-counter-input-margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-filled($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
&::before {
|
||
|
// <textarea> does not align to baseline when it does not have a value,
|
||
|
// unlike <input>, so we have to use padding to fake it instead
|
||
|
display: none;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Floating label position
|
||
|
@include floating-label-mixins.float-position(
|
||
|
variables.$textarea-filled-label-position-y,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label animation
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
textarea-filled,
|
||
|
$query: $query
|
||
|
);
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
textarea-filled,
|
||
|
variables.$textarea-filled-label-position-y,
|
||
|
0%,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-filled-input($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-top: variables.$textarea-filled-input-margin-top;
|
||
|
margin-bottom: variables.$textarea-filled-input-margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-filled-no-label-input($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-top: variables.$textarea-filled-no-label-input-margin-top;
|
||
|
margin-bottom: variables.$textarea-filled-no-label-input-margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-outlined($query: feature-targeting.all()) {
|
||
|
@include notched-outline-mixins.notch-offset(0, $query: $query);
|
||
|
|
||
|
// Floating label position
|
||
|
@include notched-outline-mixins.floating-label-float-position-absolute(
|
||
|
variables.$textarea-outlined-label-position-y,
|
||
|
$query: $query
|
||
|
);
|
||
|
|
||
|
// Floating label animation
|
||
|
@include floating-label-mixins.shake-animation(
|
||
|
textarea-outlined,
|
||
|
$query: $query
|
||
|
);
|
||
|
@at-root {
|
||
|
@include floating-label-mixins.shake-keyframes(
|
||
|
textarea-outlined,
|
||
|
variables.$textarea-outlined-label-position-y,
|
||
|
0%,
|
||
|
$query: $query
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-outlined-floating-label($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
top: variables.$textarea-outlined-label-top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _textarea-outlined-input($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
margin-top: variables.$textarea-outlined-input-margin-top;
|
||
|
margin-bottom: variables.$textarea-outlined-input-margin-bottom;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Text, Prefix and Suffix
|
||
|
|
||
|
// Common styles for the text of the text field, including the prefix, suffix,
|
||
|
// and input.
|
||
|
@mixin _text($query: feature-targeting.all()) {
|
||
|
$feat-animation: feature-targeting.create-target($query, animation);
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
// Exclude setting line-height to keep caret (text cursor) same height as the input text in iOS browser.
|
||
|
@include typography.typography(
|
||
|
subtitle1,
|
||
|
$exclude-props: (line-height),
|
||
|
$query: $query
|
||
|
);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
height: variables.$input-height;
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-animation) {
|
||
|
transition: animation.standard(opacity, 150ms);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _input($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include _text($query: $query);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
width: 100%;
|
||
|
min-width: 0; // Fixes flex issues on Firefox
|
||
|
border: none;
|
||
|
border-radius: 0;
|
||
|
background: none;
|
||
|
appearance: none;
|
||
|
padding: 0;
|
||
|
|
||
|
// Remove built-in trailing clear icon on IE11. IE vendor prefixes cannot
|
||
|
// be combined with other vendor prefixes like the webkit one below.
|
||
|
&::-ms-clear {
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
// Remove built-in datepicker icon on Chrome
|
||
|
&::-webkit-calendar-picker-indicator {
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
&:focus {
|
||
|
outline: none;
|
||
|
}
|
||
|
|
||
|
// Remove red outline on firefox
|
||
|
&:invalid {
|
||
|
box-shadow: none;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _input-placeholder($query: feature-targeting.all()) {
|
||
|
$feat-animation: feature-targeting.create-target($query, animation);
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-animation) {
|
||
|
transition: animation.standard(opacity, 67ms);
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
opacity: 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _input-placeholder-visible($query: feature-targeting.all()) {
|
||
|
$feat-animation: feature-targeting.create-target($query, animation);
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-animation) {
|
||
|
transition-delay: 40ms;
|
||
|
transition-duration: 110ms;
|
||
|
}
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _affix($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include _text($query: $query);
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
opacity: 0;
|
||
|
white-space: nowrap;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TODO(b/155467610): Remove when Safari supports baseline alignment
|
||
|
// https://github.com/material-components/material-components-web/issues/5879
|
||
|
@mixin _centered-affix-safari-support($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
align-items: center;
|
||
|
align-self: center;
|
||
|
display: inline-flex;
|
||
|
height: 100%;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _affix-visible($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _prefix($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-box(padding, right, variables.$prefix-padding);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _prefix-end-aligned($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-box(
|
||
|
padding,
|
||
|
right,
|
||
|
variables.$prefix-end-aligned-padding
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _suffix($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-box(padding, left, variables.$suffix-padding);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _suffix-end-aligned($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.reflexive-box(
|
||
|
padding,
|
||
|
left,
|
||
|
variables.$suffix-end-aligned-padding
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// End aligned
|
||
|
@mixin end-aligned_($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
// IE11 does not support text-align: end
|
||
|
@include rtl.ignore-next-line();
|
||
|
text-align: right;
|
||
|
}
|
||
|
|
||
|
@include rtl.rtl {
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.ignore-next-line();
|
||
|
text-align: left;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Forces input, prefix, and suffix to be LTR when in an RTL environment. Other
|
||
|
// elements such as labels and icons will remain RTL.
|
||
|
@mixin _ltr-text($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.rtl {
|
||
|
.mdc-text-field__input,
|
||
|
.mdc-text-field__affix {
|
||
|
@include rtl.ignore-next-line();
|
||
|
direction: ltr;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--prefix {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-left: 0;
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-right: variables.$prefix-padding;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--suffix {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-left: variables.$suffix-padding;
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-right: 0;
|
||
|
}
|
||
|
|
||
|
// Need to specify an order for all elements since icons maintain their
|
||
|
// original positions. We can't just reverse the container.
|
||
|
.mdc-text-field__icon--leading {
|
||
|
order: 1;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--suffix {
|
||
|
order: 2;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
order: 3;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--prefix {
|
||
|
order: 4;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__icon--trailing {
|
||
|
order: 5;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Forces input, prefix, and suffix that are already forced to LTR to also be
|
||
|
// end-aligned. This mixin should be used alongside the styles provided in
|
||
|
// _ltr-text().
|
||
|
@mixin _ltr-text-end-aligned($query: feature-targeting.all()) {
|
||
|
$feat-structure: feature-targeting.create-target($query, structure);
|
||
|
|
||
|
@include feature-targeting.targets($feat-structure) {
|
||
|
@include rtl.rtl {
|
||
|
.mdc-text-field__input {
|
||
|
// IE11 does not support text-align: end, so we need to duplicate
|
||
|
// the LTR end-aligned style here.
|
||
|
@include rtl.ignore-next-line();
|
||
|
text-align: right;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--prefix {
|
||
|
// padding-left: 0 provided by _ltr-text mixin
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-right: variables.$prefix-end-aligned-padding;
|
||
|
}
|
||
|
|
||
|
.mdc-text-field__affix--suffix {
|
||
|
@include rtl.ignore-next-line();
|
||
|
padding-left: variables.$suffix-end-aligned-padding;
|
||
|
// padding-right: 0 provided by _ltr-text mixin
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Customization
|
||
|
|
||
|
@mixin ink-color_($color, $query: feature-targeting.all()) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
.mdc-text-field__input {
|
||
|
@include feature-targeting.targets($feat-color) {
|
||
|
@include theme.prop(color, $color);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin placeholder-color_($color, $query: feature-targeting.all()) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
@include feature-targeting.targets($feat-color) {
|
||
|
.mdc-text-field__input {
|
||
|
@include placeholder-selector_ {
|
||
|
@include theme.prop(color, $color);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin fill-color_(
|
||
|
$color,
|
||
|
$query: feature-targeting.all(),
|
||
|
$addAlternate: false
|
||
|
) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
@include feature-targeting.targets($feat-color) {
|
||
|
@if ($addAlternate) {
|
||
|
/* @alternate */
|
||
|
}
|
||
|
@include theme.prop(background-color, $color);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin bottom-line-color_($color, $query: feature-targeting.all()) {
|
||
|
.mdc-line-ripple {
|
||
|
@include line-ripple-mixins.inactive-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin hover-bottom-line-color_($color, $query: feature-targeting.all()) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
&:hover .mdc-line-ripple {
|
||
|
@include line-ripple-mixins.inactive-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin line-ripple-color_($color, $query: feature-targeting.all()) {
|
||
|
.mdc-line-ripple {
|
||
|
@include line-ripple-mixins.active-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin hover-outline-color_($color, $query: feature-targeting.all()) {
|
||
|
&:not(.mdc-text-field--focused):hover {
|
||
|
.mdc-notched-outline {
|
||
|
@include notched-outline-mixins.color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin focused-outline-color_($color, $query: feature-targeting.all()) {
|
||
|
&.mdc-text-field--focused {
|
||
|
@include notched-outline-mixins.color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin label-ink-color_($color, $query: feature-targeting.all()) {
|
||
|
.mdc-floating-label {
|
||
|
@include floating-label-mixins.ink-color($color, $query: $query);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _prefix-color($color, $query: feature-targeting.all()) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
@include feature-targeting.targets($feat-color) {
|
||
|
.mdc-text-field__affix--prefix {
|
||
|
@include theme.prop(color, $color);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@mixin _suffix-color($color, $query: feature-targeting.all()) {
|
||
|
$feat-color: feature-targeting.create-target($query, color);
|
||
|
|
||
|
@include feature-targeting.targets($feat-color) {
|
||
|
.mdc-text-field__affix--suffix {
|
||
|
@include theme.prop(color, $color);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Selectors
|
||
|
|
||
|
@mixin placeholder-selector_ {
|
||
|
// GSS will combine selectors with the same content, and some browsers have a
|
||
|
// CSS quirk where it drops a rule if it does not recognize one of the
|
||
|
// selectors.
|
||
|
// To avoid GSS combining the ::placeholder and :-ms-input-placeholder
|
||
|
// selectors, we wrap them in `@media all`.
|
||
|
// TODO(b/142329051)
|
||
|
@media all {
|
||
|
// ::placeholder needs to be wrapped because IE11 will drop other selectors
|
||
|
// with the same content
|
||
|
&::placeholder {
|
||
|
@content;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@media all {
|
||
|
// :-ms-input-placeholder needs to be wrapped because Firefox will drop
|
||
|
// other selectors with the same content
|
||
|
&:-ms-input-placeholder {
|
||
|
@content;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// State qualifiers
|
||
|
|
||
|
///
|
||
|
/// Helps style the text-field only when it's enabled.
|
||
|
/// @access private
|
||
|
///
|
||
|
@mixin if-enabled_ {
|
||
|
&:not(.mdc-text-field--disabled) {
|
||
|
@content;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///
|
||
|
/// Helps style the text-field only when it's disabled.
|
||
|
/// @access private
|
||
|
///
|
||
|
@mixin if-disabled_ {
|
||
|
&.mdc-text-field--disabled {
|
||
|
@content;
|
||
|
}
|
||
|
}
|