File: /var/www/vhost/disk-apps/pwa.sports-crowd.com/node_modules/@material/select/_select-theme.scss
//
// Copyright 2020 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 --
// NOTE: this is the implementation of the aforementioned classes.
@use 'sass:math';
@use 'sass:color';
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use '@material/tokens/resolvers';
@use '@material/density/functions' as density-functions;
@use '@material/density/variables' as density-variables;
@use '@material/elevation/elevation-theme';
@use '@material/feature-targeting/feature-targeting';
@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/list/mixins' as list-mixins;
@use '@material/list/evolution-mixins' as list-evolution-mixins;
@use '@material/menu-surface/mixins' as menu-surface-mixins;
@use '@material/notched-outline/mixins' as notched-outline-mixins;
@use '@material/notched-outline/variables' as notched-outline-variables;
@use '@material/ripple/ripple-theme';
@use '@material/rtl/rtl';
@use '@material/shape/functions' as shape-functions;
@use '@material/shape/mixins' as shape-mixins;
@use '@material/theme/css';
@use '@material/theme/custom-properties';
@use '@material/theme/gss';
@use '@material/theme/keys';
@use '@material/theme/state';
@use '@material/theme/theme';
@use '@material/theme/variables' as theme-variables;
@use '@material/typography/mixins' as typography-mixins;
@use '@material/typography/typography';
@use './select-helper-text-theme';
@use './select-icon-theme';
@use './select-shared-theme';
$ripple-target: '.mdc-select__ripple';
@function get-outlined-label-position-y($select-anchor-height) {
@if custom-properties.is-custom-prop($select-anchor-height) {
$value: custom-properties.get-declaration-value($select-anchor-height);
@return calc(
calc($value / 2) +
math.div(notched-outline-variables.$label-box-height, 2)
);
} @else {
@return math.div($select-anchor-height, 2) +
math.div(notched-outline-variables.$label-box-height, 2);
}
}
$arrow-padding: 52px !default;
$label-padding: 16px !default;
$height: 56px !default;
$minimum-height-for-filled-label: 52px !default;
$filled-baseline-top: 40px !default;
$selected-text-height: 28px !default;
$anchor-padding-left: 16px !default;
$anchor-padding-left-with-leading-icon: 0 !default;
$anchor-padding-right: 0 !default;
$outlined-stroke-width: 2px !default;
$default-width: 200px !default;
$shape-radius: small !default;
$minimum-height: 40px !default;
$minimum-height-for-filled-label: 52px !default;
$maximum-height: $height !default;
$density-scale: density-variables.$default-scale !default;
$density-config: (
height: (
default: $height,
maximum: $maximum-height,
minimum: $minimum-height,
),
) !default;
$ink-color: rgba(theme-variables.prop-value(on-surface), 0.87) !default;
$dropdown-icon-color: rgba(
theme-variables.prop-value(on-surface),
0.54
) !default;
$label-color: rgba(theme-variables.prop-value(on-surface), 0.6) !default;
$focused-label-color: rgba(theme-variables.prop-value(primary), 0.87) !default;
$bottom-line-idle-color: rgba(
theme-variables.prop-value(on-surface),
0.42
) !default;
$bottom-line-hover-color: rgba(
theme-variables.prop-value(on-surface),
0.87
) !default;
$fill-color: color.mix(
theme-variables.prop-value(on-surface),
theme-variables.prop-value(surface),
4%
) !default;
// Disabled Styles
$disabled-label-color: rgba(
theme-variables.prop-value(on-surface),
0.38
) !default;
$disabled-ink-color: rgba(
theme-variables.prop-value(on-surface),
0.38
) !default;
$disabled-fill-color: color.mix(
theme-variables.prop-value(on-surface),
theme-variables.prop-value(surface),
2%
) !default;
$disabled-fill-border: rgba(
theme-variables.prop-value(on-surface),
0.06
) !default;
$disabled-bottom-line-color: rgba(
theme-variables.prop-value(on-surface),
0.06
) !default;
$disabled-dropdown-icon-color: rgba(
theme-variables.prop-value(on-surface),
0.38
) !default;
$disabled-outline-color: rgba(
theme-variables.prop-value(on-surface),
0.06
) !default;
$outlined-idle-border: rgba(
theme-variables.prop-value(on-surface),
0.38
) !default;
$outlined-hover-border: rgba(
theme-variables.prop-value(on-surface),
0.87
) !default;
$label-position-y: 106% !default;
$outline-label-offset: 16px !default;
$outlined-label-position-y: get-outlined-label-position-y($height) !default;
$outlined-with-leading-icon-label-position-x: 32px !default;
$dropdown-transition-duration: 150ms !default;
// Transition durartions to active state
$icon-active-fade-out-duration: 0.33 * $dropdown-transition-duration !default;
$icon-active-fade-in-duration: 0.67 * $dropdown-transition-duration !default;
// Transition durartions to inactive state
$icon-inactive-fade-out-duration: 0.5 * $dropdown-transition-duration !default;
$icon-inactive-fade-in-duration: 0.5 * $dropdown-transition-duration !default;
// Error colors
$error-color: error !default;
@mixin theme-styles($theme, $resolvers: resolvers.$material) {
@include container-fill-color(
(
default: map.get($theme, text-field-container-color),
disabled: map.get($theme, text-field-disabled-container-color),
)
);
@include outline-color(
(
default: map.get($theme, text-field-outline-color),
hover: map.get($theme, text-field-hover-outline-color),
focus: map.get($theme, text-field-focus-outline-color),
disabled: map.get($theme, text-field-disabled-outline-color),
)
);
@include _error-outline-color(
(
default: map.get($theme, text-field-error-outline-color),
hover: map.get($theme, text-field-error-hover-outline-color),
focus: map.get($theme, text-field-error-focus-outline-color),
)
);
@include outline-width(
(
default: map.get($theme, text-field-outline-width),
hover: map.get($theme, text-field-hover-outline-width),
focus: map.get($theme, text-field-focus-outline-width),
)
);
@include _menu-container-color(map.get($theme, menu-container-color));
@include _menu-container-elevation(map.get($theme, menu-container-elevation));
@include _menu-container-shape(map.get($theme, menu-container-shape));
@include _menu-container-surface-tint-layer-color(
map.get($theme, menu-container-surface-tint-layer-color)
);
@include _menu-divider-color(map.get($theme, menu-divider-color));
@include _menu-divider-height(map.get($theme, menu-divider-height));
@include _menu-list-item-container-height(
map.get($theme, menu-list-item-container-height)
);
@include _menu-list-item-label-text-color(
map.get($theme, menu-list-item-label-text-color)
);
@include _menu-list-item-label-text-typography(
(
font: map.get($theme, menu-list-item-label-text-font),
line-height: map.get($theme, menu-list-item-label-text-line-height),
size: map.get($theme, menu-list-item-label-text-size),
tracking: map.get($theme, menu-list-item-label-text-tracking),
weight: map.get($theme, menu-list-item-label-text-weight),
)
);
@include _menu-list-item-state-layer(
(
focus-state-layer-color:
map.get($theme, menu-list-item-focus-state-layer-color),
focus-state-layer-opacity:
map.get($theme, menu-list-item-focus-state-layer-opacity),
hover-state-layer-color:
map.get($theme, menu-list-item-hover-state-layer-color),
hover-state-layer-opacity:
map.get($theme, menu-list-item-hover-state-layer-opacity),
pressed-state-layer-color:
map.get($theme, menu-list-item-pressed-state-layer-color),
pressed-state-layer-opacity:
map.get($theme, menu-list-item-pressed-state-layer-opacity),
)
);
@include _menu-list-item-selected-container-color(
map.get($theme, menu-list-item-selected-container-color)
);
@include _menu-list-item-with-leading-icon-leading-icon-color(
map.get($theme, menu-list-item-with-leading-icon-leading-icon-color)
);
@include _menu-list-item-with-leading-icon-leading-icon-size(
map.get($theme, menu-list-item-with-leading-icon-leading-icon-size)
);
// TODO: Create new mixin for trailing icon theming when select supports it.
@include _menu-list-item-with-leading-icon-leading-icon-color(
map.get($theme, menu-list-item-with-trailing-icon-trailing-icon-color)
);
@include _menu-list-item-with-leading-icon-leading-icon-size(
map.get($theme, menu-list-item-with-trailing-icon-trailing-icon-size)
);
@include bottom-line-color(
(
default: map.get($theme, text-field-active-indicator-color),
hover: map.get($theme, text-field-hover-active-indicator-color),
focus: map.get($theme, text-field-focus-active-indicator-color),
disabled: map.get($theme, text-field-disabled-active-indicator-color),
)
);
@include dropdown-icon-size(map.get($theme, text-field-trailing-icon-size));
@include select-icon-theme.size(
map.get($theme, text-field-leading-icon-size)
);
@include _text-field-error-active-indicator-color(
(
default: map.get($theme, text-field-error-active-indicator-color),
hover: map.get($theme, text-field-error-hover-active-indicator-color),
focus: map.get($theme, text-field-error-focus-active-indicator-color),
)
);
@include _text-field-active-indicator-height(
(
default: map.get($theme, text-field-active-indicator-height),
focus: map.get($theme, text-field-focus-active-indicator-height),
)
);
// TODO(b/259951357): Cleanup branch after fix and tokens upgrade.
@if map.has-key($theme, text-field-caret-color) or
map.has-key($theme, text-field-error-caret-color)
{
@include _text-field-trailing-icon-color(
(
default: map.get($theme, text-field-caret-color),
hover: map.get($theme, text-field-hover-caret-color),
focus: map.get($theme, text-field-focus-caret-color),
)
);
@include _text-field-error-trailing-icon-color(
(
default: map.get($theme, text-field-error-caret-color),
hover: map.get($theme, text-field-error-hover-caret-color),
focus: map.get($theme, text-field-error-focus-caret-color),
)
);
} @else {
@include _text-field-trailing-icon-color(
(
default: map.get($theme, text-field-trailing-icon-color),
hover: map.get($theme, text-field-hover-trailing-icon-color),
focus: map.get($theme, text-field-focus-trailing-icon-color),
disabled: map.get($theme, text-field-disabled-trailing-icon-color),
)
);
@include _text-field-error-trailing-icon-color(
(
default: map.get($theme, text-field-error-trailing-icon-color),
hover: map.get($theme, text-field-error-hover-trailing-icon-color),
focus: map.get($theme, text-field-error-focus-trailing-icon-color),
)
);
}
@include ink-color(
(
default: map.get($theme, text-field-input-text-color),
hover: map.get($theme, text-field-hover-input-text-color),
focus: map.get($theme, text-field-focus-input-text-color),
disabled: map.get($theme, text-field-disabled-input-text-color),
)
);
@include _error-input-text-color(
(
default: map.get($theme, text-field-error-input-text-color),
hover: map.get($theme, text-field-error-hover-input-text-color),
focus: map.get($theme, text-field-error-focus-input-text-color),
)
);
@include label-color(
(
default: map.get($theme, text-field-label-text-color),
hover: map.get($theme, text-field-hover-label-text-color),
focus: map.get($theme, text-field-focus-label-text-color),
disabled: map.get($theme, text-field-disabled-label-text-color),
)
);
@include label-floating-color(
(
default: map.get($theme, text-field-label-text-color),
hover: map.get($theme, text-field-hover-label-text-color),
focus: map.get($theme, text-field-focus-label-text-color),
disabled: map.get($theme, text-field-disabled-label-text-color),
)
);
@include _error-label-text-color(
(
default: map.get($theme, text-field-error-label-text-color),
hover: map.get($theme, text-field-error-hover-label-text-color),
focus: map.get($theme, text-field-error-focus-label-text-color),
)
);
@include _text-field-leading-icon-color(
(
default: map.get($theme, text-field-leading-icon-color),
hover: map.get($theme, text-field-hover-leading-icon-color),
focus: map.get($theme, text-field-focus-leading-icon-color),
disabled: map.get($theme, text-field-disabled-leading-icon-color),
)
);
@include _error-text-field-leading-icon-color(
(
default: map.get($theme, text-field-error-leading-icon-color),
hover: map.get($theme, text-field-error-hover-leading-icon-color),
focus: map.get($theme, text-field-error-focus-leading-icon-color),
)
);
@include select-helper-text-theme.helper-text-color(
(
default: map.get($theme, text-field-supporting-text-color),
disabled: map.get($theme, text-field-disabled-supporting-text-color),
hover: map.get($theme, text-field-hover-supporting-text-color),
focus: map.get($theme, text-field-focus-supporting-text-color),
)
);
@include select-helper-text-theme.helper-text-validation-color(
(
default: map.get($theme, text-field-error-supporting-text-color),
hover: map.get($theme, text-field-error-hover-supporting-text-color),
focus: map.get($theme, text-field-error-focus-supporting-text-color),
)
);
@include _text-field-input-text-typography(
(
font: map.get($theme, text-field-input-text-font),
line-height: map.get($theme, text-field-input-text-line-height),
size: map.get($theme, text-field-input-text-size),
tracking: map.get($theme, text-field-input-text-tracking),
weight: map.get($theme, text-field-input-text-weight),
)
);
@include _text-field-label-text-typography(
(
font: map.get($theme, text-field-label-text-font),
line-height: map.get($theme, text-field-label-text-line-height),
size: map.get($theme, text-field-label-text-size),
tracking: map.get($theme, text-field-label-text-tracking),
weight: map.get($theme, text-field-label-text-weight),
)
);
@include _text-field-label-text-populated-typography(
(
line-height: map.get($theme, text-field-label-text-populated-line-height),
size: map.get($theme, text-field-label-text-populated-size),
)
);
@include _text-field-supporting-text-typography(
(
font: map.get($theme, text-field-supporting-text-font),
line-height: map.get($theme, text-field-supporting-text-line-height),
size: map.get($theme, text-field-supporting-text-size),
tracking: map.get($theme, text-field-supporting-text-tracking),
weight: map.get($theme, text-field-supporting-text-weight),
)
);
}
@mixin _text-field-supporting-text-typography($typography-theme) {
& + .mdc-select-helper-text {
@include typography.theme-styles($typography-theme);
}
}
@mixin _text-field-input-text-typography($typography-theme) {
.mdc-select__selected-text {
@include typography.theme-styles($typography-theme);
}
}
@mixin _text-field-label-text-populated-typography($typography-theme) {
.mdc-floating-label--float-above,
// Used for CSS specificity to match with selector used in `outlined-height()`.
&.mdc-select--with-leading-icon .mdc-select__anchor .mdc-notched-outline .mdc-floating-label.mdc-floating-label--float-above {
@include typography.theme-styles($typography-theme);
}
}
@mixin _text-field-label-text-typography($typography-theme) {
.mdc-floating-label {
@include typography.theme-styles($typography-theme);
}
}
@mixin _error-outline-color($color) {
&.mdc-select--invalid {
@include outline-color($color);
}
}
@mixin _error-text-field-leading-icon-color($color) {
&.mdc-select--invalid {
@include _text-field-leading-icon-color($color);
}
}
@mixin _text-field-leading-icon-color($color) {
@include _if-enabled {
@include _set-text-field-leading-icon-color(
state.get-default-state($color)
);
&:not(.mdc-select--focused):hover {
@include _set-text-field-leading-icon-color(
state.get-hover-state($color)
);
}
@include _if-focused {
@include _set-text-field-leading-icon-color(
state.get-focus-state($color)
);
}
}
@include _if-disabled {
@include _set-text-field-leading-icon-color(
state.get-disabled-state($color)
);
}
}
@mixin _set-text-field-leading-icon-color($color) {
.mdc-select__anchor .mdc-select__icon {
@include theme.property(color, $color);
}
}
@mixin _error-label-text-color($color) {
&.mdc-select--invalid {
@include label-color($color);
}
}
@mixin _error-input-text-color($color) {
&.mdc-select--invalid {
@include ink-color($color);
}
}
@mixin _text-field-trailing-icon-color($color) {
@include dropdown-icon-color($color);
}
@mixin _text-field-error-trailing-icon-color($color) {
&.mdc-select--invalid {
@include dropdown-icon-color($color);
}
}
@mixin _text-field-error-active-indicator-color($color) {
&.mdc-select--invalid {
@include bottom-line-color($color);
}
}
@mixin _text-field-active-indicator-height($height) {
.mdc-line-ripple {
@include line-ripple-mixins.height(state.get-default-state($height));
@include line-ripple-mixins.active-height(state.get-focus-state($height));
}
}
@mixin _menu-list-item-with-leading-icon-leading-icon-color($color) {
&:not(.mdc-select--disabled) .mdc-select__option .mdc-select__icon {
@include theme.property(color, $color);
}
}
@mixin _menu-list-item-with-leading-icon-leading-icon-size($size) {
&:not(.mdc-select--disabled) .mdc-select__option .mdc-select__icon {
@include theme.property(font-size, $size);
}
}
@mixin _menu-list-item-selected-container-color($color) {
.mdc-select__option {
@include list-evolution-mixins.list-item-selected-container-color($color);
}
}
@mixin _menu-list-item-label-text-typography($typography-theme) {
.mdc-select__option {
@include list-evolution-mixins.list-primary-text-typography(
$typography-theme
);
}
}
@mixin _menu-list-item-label-text-color($color) {
.mdc-select__option {
@include list-evolution-mixins.list-primary-text-ink-color($color);
}
}
@mixin _menu-list-item-container-height($height) {
.mdc-select__option {
@include list-evolution-mixins.list-item-height($height);
}
}
@mixin _menu-list-item-state-layer($ripple-theme) {
.mdc-list-item:not(.mdc-list-item--disabled) {
@include ripple-theme.theme-styles(
$ripple-theme,
$ripple-target: list-evolution-mixins.$ripple-target
);
}
}
@mixin _menu-divider-color($color) {
.mdc-select__list {
@include list-evolution-mixins.divider-color($color);
}
}
@mixin _menu-divider-height($height) {
.mdc-select__list {
@include list-evolution-mixins.divider-height($height);
}
}
@mixin _menu-container-color($color) {
.mdc-select__menu {
@include menu-surface-mixins.fill-color($color);
}
}
@mixin _menu-container-elevation($elevation) {
@if $elevation {
.mdc-select__menu {
@include elevation-theme.shadow(map.get($elevation, shadow));
@include elevation-theme.overlay-opacity(
map.get($elevation, overlay-opacity)
);
}
}
}
@mixin _menu-container-shape($shape) {
.mdc-select__menu {
@include menu-surface-mixins.shape-radius($shape);
}
}
@mixin _menu-container-surface-tint-layer-color($color) {
.mdc-select__menu {
@include elevation-theme.overlay-container-color($color);
}
}
@mixin menu-list-item-secondary-label-text-color($color) {
.mdc-select__list {
@include list-evolution-mixins.list-secondary-text-ink-color($color);
}
}
@mixin menu-list-item-secondary-label-text-typography($typography-theme) {
.mdc-select__list {
@include list-evolution-mixins.list-secondary-text-typography(
$typography-theme
);
}
}
/// Sets the min-width of the select.
/// @param {Number} $min-width - The desired min-width.
/// @deprecated using this mixin is no longer required, and clients may set
/// the attribute directly
@mixin min-width($min-width, $query: feature-targeting.all()) {
$feat-structure: feature-targeting.create-target($query, structure);
@include feature-targeting.targets($feat-structure) {
min-width: $min-width;
}
}
/// Sets the select behavior to change width dynamically based on content.
/// @param {Number} $min-width - The min-width of the select, which should be
/// large enough to allow the label (if exists) to display in full.
@mixin variable-width($min-width, $query: feature-targeting.all()) {
$feat-structure: feature-targeting.create-target($query, structure);
.mdc-select__anchor {
@include feature-targeting.targets($feat-structure) {
width: 100%;
min-width: $min-width;
}
}
}
@mixin ink-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _ink-color(state.get-default-state($color-or-map), $query: $query);
}
@include _if-disabled {
@include _ink-color(
state.get-disabled-state($color-or-map),
$query: $query
);
}
}
@mixin container-fill-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _container-fill-color(
state.get-default-state($color-or-map),
$query: $query
);
}
@include _if-disabled {
@include _container-fill-color(
state.get-disabled-state($color-or-map),
$query: $query
);
}
}
@mixin dropdown-icon-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _dropdown-icon-color(
state.get-default-state($color-or-map),
$query: $query
);
&:not(.mdc-select--focused):hover {
@include _dropdown-icon-color(
state.get-hover-state($color-or-map),
$query: $query
);
}
@include _if-focused {
@include _dropdown-icon-color(
state.get-focus-state($color-or-map),
$query: $query
);
}
}
@include _if-disabled {
@include _dropdown-icon-color(
state.get-disabled-state($color-or-map),
$query: $query
);
}
}
@mixin label-floating-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _label-floating-color(
state.get-default-state($color-or-map),
$query: $query
);
&:not(.mdc-select--focused):hover {
@include _label-floating-color(
state.get-hover-state($color-or-map),
$query: $query
);
}
}
}
@mixin bottom-line-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _bottom-line-color(
state.get-default-state($color-or-map),
$query: $query
);
// bottom line inactive/active are on different elements, does not need
// to check for :not() focused
&:hover {
@include _bottom-line-color(
state.get-hover-state($color-or-map),
$query: $query
);
}
@include _focused-line-ripple-color(
state.get-focus-state($color-or-map),
$query: $query
);
}
@include _if-disabled {
@include _bottom-line-color(
state.get-disabled-state($color-or-map),
$query: $query
);
}
}
@mixin label-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _label-color(
state.get-default-state($color-or-map),
$query: $query
);
@include _if-focused {
@include _label-color(
state.get-focus-state($color-or-map),
$query: $query
);
}
&:not(.mdc-select--focused):hover {
@include _label-color(
state.get-hover-state($color-or-map),
$query: $query
);
}
}
@include _if-disabled {
@include _label-color(
state.get-disabled-state($color-or-map),
$query: $query
);
}
}
@mixin outline-color($color-or-map, $query: feature-targeting.all()) {
@include _if-enabled {
@include _outline-color(
state.get-default-state($color-or-map),
$query: $query
);
&:not(.mdc-select--focused) .mdc-select__anchor:hover {
@include _hover-outline-color(
state.get-hover-state($color-or-map),
$query: $query
);
}
@include _if-focused {
@include _focused-outline-color(
state.get-focus-state($color-or-map),
$query: $query
);
}
}
@include _if-disabled {
@include _outline-color(
state.get-disabled-state($color-or-map),
$query: $query
);
}
}
@mixin outline-width($width, $query: feature-targeting.all()) {
@include _if-enabled {
@include _outline-width(state.get-default-state($width), $query: $query);
&:not(.mdc-select--focused) .mdc-select__anchor:hover {
@include _outline-width(state.get-hover-state($width), $query: $query);
}
@include _if-focused {
.mdc-notched-outline {
@include _outline-width(state.get-focus-state($width), $query: $query);
}
}
}
}
@mixin _outline-width($width, $query: feature-targeting.all()) {
@if $width {
@include notched-outline-mixins.stroke-width($width, $query: $query);
}
}
///
/// Sets the dropdown icon to the specified size.
///
@mixin dropdown-icon-size($size, $query: feature-targeting.all()) {
$feat-structure: feature-targeting.create-target($query, structure);
.mdc-select__dropdown-icon {
@include feature-targeting.targets($feat-structure) {
@include theme.property(width, $size);
@include theme.property(height, $size);
}
}
}
@mixin filled-shape-radius(
$radius,
$density-scale: $density-scale,
$rtl-reflexive: false,
$query: feature-targeting.all()
) {
$height: density-functions.prop-value(
$density-config: $density-config,
$density-scale: $density-scale,
$property-name: height,
);
$masked-radius: if(
(meta.type-of($radius) == 'list') and (list.length($radius) > 2),
shape-functions.mask-radius($radius, 1 1 1 1),
shape-functions.mask-radius($radius, 1 1 0 0)
);
$fallback: if(
custom-properties.is-custom-prop($radius),
custom-properties.get-fallback($radius),
null
);
@if meta.type-of($fallback) == 'list' {
$fallback: css.unpack-value($fallback);
$first: list.nth($masked-radius, 1);
$second: list.nth($masked-radius, 2);
$third: list.nth($masked-radius, 3);
$fourth: list.nth($masked-radius, 4);
$masked-radius: (
if(
custom-properties.is-custom-prop($first),
custom-properties.set-fallback($first, list.nth($fallback, 1)),
$first
),
if(
custom-properties.is-custom-prop($second),
custom-properties.set-fallback($second, list.nth($fallback, 2)),
$second
),
if(
custom-properties.is-custom-prop($third),
custom-properties.set-fallback($third, list.nth($fallback, 3)),
$third
),
if(
custom-properties.is-custom-prop($fourth),
custom-properties.set-fallback($fourth, list.nth($fallback, 4)),
$fourth
)
);
}
.mdc-select__anchor {
@include shape-mixins.radius(
$masked-radius,
$rtl-reflexive,
$component-height: $height,
$query: $query
);
}
}
@mixin outline-shape-radius(
$radius,
$density-scale: $density-scale,
$rtl-reflexive: false,
$query: feature-targeting.all(),
$height: null
) {
$feat-structure: feature-targeting.create-target($query, structure);
@if not $height {
$height: density-functions.prop-value(
$density-config: $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);
}
@if (
$top-left-is-custom-prop or
$top-left-radius-px >
notched-outline-variables.$leading-width
) {
.mdc-select__anchor {
@include _apply-outline-shape-padding(
padding-left,
$top-left-radius,
$add-label-padding: true,
$query: $query
);
@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
);
}
}
+ .mdc-select-helper-text {
@include _apply-outline-shape-padding(
margin-left,
$top-left-radius,
$add-label-padding: true,
$query: $query
);
@include rtl.rtl {
@include feature-targeting.targets($feat-structure) {
@include rtl.ignore-next-line();
margin-left: 0;
}
@include _apply-outline-shape-padding(
margin-right,
$top-left-radius,
$add-label-padding: true,
$query: $query
);
}
}
// Unlike textfield, select does not need to re-apply leading icon padding.
// This is because select only has one potential leading class, not two
// extra classes like textfield (leading + trailing). Textfield's two extra
// classes can cause specificity conflicts, requiring everything to be
// re-applied.
}
}
///
/// Sets density scale for filled select 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 selects at which to allow floating labels.
///
@mixin filled-density(
$density-scale,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$query: feature-targeting.all()
) {
$height: density-functions.prop-value(
$density-config: $density-config,
$density-scale: $density-scale,
$property-name: height,
);
@include filled-height(
$height,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$query: $query
);
@include _list-density($density-scale, $query: $query);
}
///
/// Sets density scale for filled select variant 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`.
/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
/// filled selects at which to allow floating labels.
///
@mixin filled-with-leading-icon-density(
$density-scale,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$query: feature-targeting.all()
) {
$height: density-functions.prop-value(
$density-config: $density-config,
$density-scale: $density-scale,
$property-name: height,
);
@include filled-with-leading-icon-height(
$height,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$query: $query
);
@include _list-density($density-scale, $query: $query);
}
///
/// Sets density scale for outlined select (Excluding outlined select 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: $density-config,
$density-scale: $density-scale,
$property-name: height,
);
@include outlined-height($height, $query: $query);
@include _list-density($density-scale, $query: $query);
}
///
/// Sets density scale for outlined select 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: $density-config,
$density-scale: $density-scale,
$property-name: height,
);
@include outlined-with-leading-icon-height($height, $query: $query);
@include _list-density($density-scale, $query: $query);
}
@mixin _list-density($density-scale, $query) {
@include list-mixins.deprecated-single-line-density(
$density-scale,
$query: $query
);
.mdc-select__one-line-option {
@include list-evolution-mixins.one-line-item-density(
$density-scale,
$exclude-variants: true,
$query: $query
);
}
.mdc-select__two-line-option {
@include list-evolution-mixins.two-line-item-density(
$density-scale,
$query: $query
);
}
}
///
/// Sets height of default select variant.
///
/// @param {Number} $new-height
/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
/// filled selects at which to allow floating labels.
/// @param {Number} $filled-baseline-top The baseline from the top of the anchor
/// that the input should be aligned to for a filled variant with a label
/// @access public
///
@mixin filled-height(
$new-height,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$filled-baseline-top: $filled-baseline-top,
$query: feature-targeting.all()
) {
$feat-structure: feature-targeting.create-target($query, structure);
.mdc-select__anchor {
@include feature-targeting.targets($feat-structure) {
@include theme.property(height, $new-height);
}
// Filled variant is aligned to baseline...
@include typography-mixins.baseline(
$top: $filled-baseline-top,
$display: flex,
$query: $query
);
// ...unless it is too small to display a label
// TODO(b/283457421): Account for dynamic height
@if _is-less-than($new-height, $minimum-height-for-filled-label) {
@include center-aligned($query: $query);
@include feature-targeting.targets($feat-structure) {
.mdc-floating-label {
display: none;
}
}
}
}
// No-label variants are always centered
&.mdc-select--no-label .mdc-select__anchor {
@include center-aligned($query: $query);
}
// TODO(b/283457421): Account for dynamic height
@if _is-less-than($new-height, $height) {
@include dropdown-icon-size(
select-icon-theme.$dense-icon-size,
$query: $query
);
&.mdc-select--filled {
@include truncate-floating-label-max-width(
$leading-icon-size: 0,
$dropdown-icon-size: select-icon-theme.$dense-icon-size,
$query: $query
);
}
}
}
///
/// Sets height of filled select variant with leading icon.
///
/// @param {Number} $height
/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
/// filled selects at which to allow floating labels.
/// @param {Number} $filled-baseline-top The baseline from the top of the anchor
/// that the input should be aligned to for a filled variant with a label
/// @access public
///
@mixin filled-with-leading-icon-height(
$new-height,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$filled-baseline-top: $filled-baseline-top,
$query: feature-targeting.all()
) {
$feat-structure: feature-targeting.create-target($query, structure);
@include filled-height(
$new-height,
$minimum-height-for-filled-label: $minimum-height-for-filled-label,
$filled-baseline-top: $filled-baseline-top,
$query: $query
);
// TODO(b/283457421): Account for dynamic height
@if _is-less-than($new-height, $height) {
@include select-icon-theme.size(
select-icon-theme.$dense-icon-size,
$query: $query
);
&.mdc-select--filled {
@include truncate-floating-label-max-width(
$leading-icon-size: select-icon-theme.$dense-icon-size,
$dropdown-icon-size: select-icon-theme.$dense-icon-size,
$query: $query
);
}
.mdc-deprecated-list-item__graphic {
width: select-icon-theme.$dense-icon-size;
height: select-icon-theme.$dense-icon-size;
}
@include list-evolution-mixins.item-start-size(
$width: select-icon-theme.$dense-icon-size + 12px,
$height: select-icon-theme.$dense-icon-size,
$query: $query
);
.mdc-select__anchor {
@include leading-icon-floating-label-position(
select-icon-theme.$dense-icon-size,
$query: $query
);
}
}
}
///
/// Sets height of outlined select variant (Excluding outlined select with leading icon).
///
/// @param {Number} $new-height
/// @param {String} $keyframe-suffix - Optional suffix to use for generated
/// floating label keyframes
///
@mixin outlined-height(
$new-height,
$keyframe-suffix: null,
$query: feature-targeting.all()
) {
$feat-structure: feature-targeting.create-target($query, structure);
$positionY: get-outlined-label-position-y($new-height);
@if $keyframe-suffix == null {
$modifier: $new-height;
@if custom-properties.is-custom-prop($modifier) {
$modifier: custom-properties.get-fallback($modifier);
}
$keyframe-suffix: select-outlined-#{$modifier};
}
.mdc-select__anchor {
// 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) {
@include theme.property(height, $new-height);
}
}
// TODO(b/283457421): Account for dynamic height
@if _is-less-than($new-height, $height) {
@include dropdown-icon-size(
select-icon-theme.$dense-icon-size,
$query: $query
);
&.mdc-select--outlined {
@include truncate-notched-outline-max-width(
$leading-icon-size: 0,
$dropdown-icon-size: select-icon-theme.$dense-icon-size,
$query: $query
);
}
}
}
///
/// Sets height of outlined select with leading icon variant.
///
/// @param {Number} $new-height
/// @param {String} $keyframe-suffix - Optional suffix to use for generated
/// floating label keyframes
///
@mixin outlined-with-leading-icon-height(
$new-height,
$keyframe-suffix: null,
$query: feature-targeting.all()
) {
$feat-structure: feature-targeting.create-target($query, structure);
.mdc-select__anchor {
// TODO(b/283457421): Account for dynamic height
@if _is-less-than($new-height, $height) {
@include dropdown-icon-size(
select-icon-theme.$dense-icon-size,
$query: $query
);
@include outlined-with-leading-icon-floating-label-position-animation(
$new-height,
select-icon-theme.$dense-icon-size,
$keyframe-suffix,
$query: $query
);
} @else {
@include outlined-with-leading-icon-floating-label-position-animation(
$new-height,
select-icon-theme.$icon-size,
$keyframe-suffix,
$query: $query
);
}
@include feature-targeting.targets($feat-structure) {
@include theme.property(height, $new-height);
}
}
// TODO(b/283457421): Account for dynamic height
@if _is-less-than($new-height, $height) {
.mdc-deprecated-list-item__graphic {
width: select-icon-theme.$dense-icon-size;
height: select-icon-theme.$dense-icon-size;
}
@include list-evolution-mixins.item-start-size(
$width: select-icon-theme.$dense-icon-size + 12px,
$height: select-icon-theme.$dense-icon-size,
$query: $query
);
@include select-icon-theme.size(
select-icon-theme.$dense-icon-size,
$query: $query
);
&.mdc-select--outlined {
@include truncate-notched-outline-max-width(
$leading-icon-size: select-icon-theme.$dense-icon-size,
$dropdown-icon-size: select-icon-theme.$dense-icon-size,
$query: $query
);
}
}
}
// $add-label-padding is copied from textfield's mixin, even though select
// always sets it to true. This is to try and keep things aligned between select
// and textfield for when these styles are refactored into shared styles.
@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 > notched-outline-variables.$leading-width) {
// 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;
@include gss.annotate(
(
alternate: $padding-is-custom-prop,
)
);
}
@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(#{$anchor-padding-left}, #{$value});
}
}
}
}
// Removes filled baseline alignment
@mixin center-aligned($query: feature-targeting.all()) {
$feat-structure: feature-targeting.create-target($query, structure);
.mdc-select__selected-text {
@include typography-mixins.zero-width-prefix($query: $query);
}
@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.
.mdc-select__selected-text-container {
height: 100%;
display: inline-flex;
align-items: center;
}
&::before {
display: none;
}
}
}
///
/// Sets the position of the floating label for a select with leading icon.
/// @param {number} $icon-size - The size of the leading icon.
///
@mixin leading-icon-floating-label-position(
$icon-size: select-icon-theme.$icon-size,
$query: feature-targeting.all()
) {
$feat-structure: feature-targeting.create-target($query, structure);
$icon-total-width: $icon-size + 2 * select-icon-theme.$icon-horizontal-margin;
.mdc-floating-label {
@include feature-targeting.targets($feat-structure) {
@include rtl.reflexive-position(left, $icon-total-width);
}
}
}
///
/// Sets the floating label position and animations for a given height for an
/// outlined select with leaing icon.
/// @param {number} $icon-size - The size of the leading icon.
/// @param {string} $keyframe-suffix - The suffix for the newly generated keyframes.
///
@mixin outlined-with-leading-icon-floating-label-position-animation(
$height,
$icon-size,
$keyframe-suffix: select-outlined-leading-icon-#{$height},
$query: feature-targeting.all()
) {
$feat-structure: feature-targeting.create-target($query, structure);
$icon-total-width: $icon-size + 2 * select-icon-theme.$icon-horizontal-margin;
$resting-position-x: $icon-total-width -
select-icon-theme.$icon-horizontal-margin;
$float-position-y: get-outlined-label-position-y($height);
$float-position-x: $icon-size + select-icon-theme.$icon-horizontal-margin -
notched-outline-variables.$notch-gutter-size;
// Resting label position
.mdc-floating-label {
@include feature-targeting.targets($feat-structure) {
@include rtl.reflexive-position(left, $resting-position-x);
}
}
// Floating label position
@include notched-outline-mixins.floating-label-float-position-absolute(
$float-position-y,
$float-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,
$float-position-y,
$float-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,
$float-position-y,
-($float-position-x),
$query: $query
);
}
}
///
/// Truncates the max-width of the floating label according to sizes of the
/// leading icon and dropdown icon.
///
/// @param {Number} $leading-icon-size - Size of leading icon.
/// @param {Number} $dropdown-icon-size - Size of dropdown icon.
///
@mixin truncate-floating-label-max-width(
$leading-icon-size,
$dropdown-icon-size,
$query: feature-targeting.all()
) {
$truncation: select-icon-theme.$icon-horizontal-margin * 2 +
$dropdown-icon-size;
@if $leading-icon-size > 0 {
$truncation: $truncation +
select-icon-theme.$icon-horizontal-margin *
2 +
$leading-icon-size;
} @else {
$truncation: $truncation + $outline-label-offset;
}
.mdc-floating-label {
@include floating-label-mixins.max-width(
calc(100% - #{$truncation}),
$query: $query
);
}
.mdc-floating-label--float-above {
$scale: floating-label-variables.$float-scale;
@include floating-label-mixins.max-width(
calc(100% / #{$scale} - #{$truncation} / #{$scale}),
$query: $query
);
}
}
///
/// Truncates the max-width of the notched outline according to the sizes of
/// the leading icon and dropdown icon.
///
/// @param {Number} $leading-icon-size - Size of leading icon.
/// @param {Number} $dropdown-icon-size - Size of dropdown icon.
///
@mixin truncate-notched-outline-max-width(
$leading-icon-size,
$dropdown-icon-size,
$query: feature-targeting.all()
) {
$truncation: select-icon-theme.$icon-horizontal-margin * 2 +
$dropdown-icon-size + notched-outline-variables.$leading-width;
@if $leading-icon-size > 0 {
$truncation: $truncation +
select-icon-theme.$icon-horizontal-margin +
$leading-icon-size;
}
.mdc-select__anchor {
@include notched-outline-mixins.notch-max-width(
calc(100% - #{$truncation}),
$query: $query
);
}
}
/// Selector for focused state
/// @access private
@mixin _if-focused {
&.mdc-select--focused {
@content;
}
}
/// Selector for enabled state
/// @access private
@mixin _if-enabled {
&:not(.mdc-select--disabled) {
@content;
}
}
/// Selector for disabled state
/// @access private
@mixin _if-disabled {
&.mdc-select--disabled {
@content;
}
}
@mixin _ink-color($color, $query: feature-targeting.all()) {
$feat-color: feature-targeting.create-target($query, color);
@if $color {
.mdc-select__selected-text {
@include feature-targeting.targets($feat-color) {
@include theme.property(color, $color);
}
}
}
}
@mixin _container-fill-color($color, $query: feature-targeting.all()) {
$feat-color: feature-targeting.create-target($query, color);
@if $color {
.mdc-select__anchor {
@include feature-targeting.targets($feat-color) {
@include theme.property(background-color, $color);
}
}
}
}
@mixin _bottom-line-color($color, $query: feature-targeting.all()) {
@if $color {
.mdc-line-ripple {
@include line-ripple-mixins.inactive-color($color, $query: $query);
}
}
}
@mixin _focused-line-ripple-color($color, $query: feature-targeting.all()) {
@if $color {
.mdc-line-ripple {
@include line-ripple-mixins.active-color($color, $query: $query);
}
}
}
@mixin _outline-color($color, $query: feature-targeting.all()) {
@if $color {
@include notched-outline-mixins.color($color, $query: $query);
}
}
@mixin _hover-outline-color($color, $query: feature-targeting.all()) {
@if $color {
.mdc-notched-outline {
@include notched-outline-mixins.color($color, $query: $query);
}
}
}
@mixin _focused-outline-color($color, $query: feature-targeting.all()) {
@if $color {
.mdc-notched-outline {
@include notched-outline-mixins.color($color, $query: $query);
}
}
}
@mixin _label-color($color, $query: feature-targeting.all()) {
@if $color {
.mdc-floating-label {
@include floating-label-mixins.ink-color($color, $query: $query);
}
}
}
@mixin _label-floating-color($color, $query: feature-targeting.all()) {
@if $color {
.mdc-floating-label--float-above {
@include floating-label-mixins.ink-color($color, $query: $query);
}
}
}
///
/// Sets the dropdown icon to the specified color.
/// @access private
///
@mixin _dropdown-icon-color($color, $query: feature-targeting.all()) {
$feat-color: feature-targeting.create-target($query, color);
@if $color {
@include feature-targeting.targets($feat-color) {
.mdc-select__dropdown-icon {
@include theme.property(fill, $color);
}
}
}
}
///
/// Compare the two inputs even if they're custom-prop objects.
/// @access private
///
@function _is-less-than($subject, $object) {
$fallback-subject: if(
custom-properties.is-custom-prop($subject),
custom-properties.get-fallback($subject),
$subject
);
$fallback-object: if(
custom-properties.is-custom-prop($object),
custom-properties.get-fallback($object),
$object
);
@return $fallback-subject < $fallback-object;
}