// // Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 // // stylelint-disable selector-class-pattern -- // Selector '.md3-*' should only be used in this project. // go/keep-sorted start @use 'sass:map'; // go/keep-sorted end // go/keep-sorted start @use '../../motion/animation'; @use '../../ripple/ripple'; @use '../../sass/color'; @use '../../sass/touch-target'; // go/keep-sorted end @mixin styles() { @keyframes md3-segmented-button-checkmark-selection-draw-in { from { stroke-dashoffset: 29.7833385; } to { stroke-dashoffset: 0; } } @keyframes md3-segmented-button-simple-fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes md3-segmented-button-simple-fade-in { from { opacity: 0; } to { opacity: 1; } } :host { display: inline-flex; outline: none; } .md3-segmented-button { align-items: center; background: transparent; border: none; border-radius: inherit; display: flex; flex: 1; justify-content: center; outline: none; position: relative; vertical-align: middle; padding-inline-start: var(--_spacing-leading); padding-inline-end: var(--_spacing-trailing); .md3-segmented-button__outline { border-color: var(--_outline-color); } &:disabled .md3-segmented-button__outline { border-color: var(--_disabled-outline-color); } .md3-segmented-button__graphic, .md3-segmented-button__checkmark, .md3-segmented-button__icon, .md3-segmented-button__icon ::slotted([slot='icon']) { height: var(--_with-icon-icon-size); width: var(--_with-icon-icon-size); font-size: var(--_with-icon-icon-size); } // Under the following conditions, we need to account for extra space between // the graphic and the text label/icon content: // // 1. A button with an icon and a label. // 2. A selected button with a label and checkmark. // 3. A selected button with an icon and checkmark but no label. // // We calculate a larger width here instead of using padding or margin for // two main reasons: // // 1. We may need to transition between a zero width and an explicit width. // 2. Both margin and padding take up space when a node has child content // even when a zero width is set and overflow is set to hidden. // // Because of those reasons, we calculate a new width with the given values. &.md3-segmented-button--with-icon.md3-segmented-button--with-label, &.md3-segmented-button--selected.md3-segmented-button--with-label.md3-segmented-button--with-checkmark, &.md3-segmented-button--selected.md3-segmented-button--without-label.md3-segmented-button--with-checkmark { .md3-segmented-button__graphic { // TODO(b/198759625): Use padding token instead of hardcoded 8px value. width: calc(var(--_with-icon-icon-size) + 8px); } } .md3-segmented-button__label-text { font: var(--_label-text-type); } &.md3-segmented-button--selected:enabled { .md3-segmented-button__label-text { color: var(--_selected-label-text-color); } &:hover { .md3-segmented-button__label-text { color: var(--_selected-hover-label-text-color); } } &:focus { .md3-segmented-button__label-text { color: var(--_selected-focus-label-text-color); } } &:active { .md3-segmented-button__label-text { color: var(--_selected-pressed-label-text-color); } } } &.md3-segmented-button--unselected:enabled { .md3-segmented-button__label-text { color: var(--_unselected-label-text-color); } &:hover { .md3-segmented-button__label-text { color: var(--_unselected-hover-label-text-color); } } &:focus { .md3-segmented-button__label-text { color: var(--_unselected-focus-label-text-color); } } &:active { .md3-segmented-button__label-text { color: var(--_unselected-pressed-label-text-color); } } } &:disabled { .md3-segmented-button__label-text { color: var(--_disabled-label-text-color); } } } .md3-segmented-button--unselected { .md3-segmented-button__icon { color: var(--_unselected-with-icon-icon-color); } &:hover { .md3-segmented-button__icon { color: var(--_unselected-hover-icon-color); } } &:focus { .md3-segmented-button__icon { color: var(--_unselected-focus-icon-color); } } &:active { .md3-segmented-button__icon { color: var(--_unselected-pressed-icon-color); } } &:disabled { .md3-segmented-button__icon { color: var(--_disabled-icon-color); } } @include ripple.theme( ( hover-color: var(--_unselected-hover-state-layer-color), hover-opacity: var(--_hover-state-layer-opacity), focus-color: var(--_unselected-focus-state-layer-color), focus-opacity: var(--_focus-state-layer-opacity), pressed-color: var(--_unselected-pressed-state-layer-color), pressed-opacity: var(--_pressed-state-layer-opacity), ) ); } .md3-segmented-button--selected { background-color: var(--_selected-container-color); .md3-segmented-button__icon { color: var(--_selected-with-icon-icon-color); } .md3-segmented-button__checkmark-path { stroke: var(--_selected-with-icon-icon-color); } &:hover { .md3-segmented-button__checkmark-path { stroke: var(--_selected-hover-icon-color); } } &:focus { .md3-segmented-button__checkmark-path { stroke: var(--_selected-focus-icon-color); } } &:active { .md3-segmented-button__checkmark-path { stroke: var(--_selected-pressed-icon-color); } } &:disabled { .md3-segmented-button__checkmark-path { stroke: var(--_disabled-icon-color); } } @include ripple.theme( ( hover-color: var(--_selected-hover-state-layer-color), hover-opacity: var(--_hover-state-layer-opacity), focus-color: var(--_selected-focus-state-layer-color), focus-opacity: var(--_focus-state-layer-opacity), pressed-color: var(--_selected-pressed-state-layer-color), pressed-opacity: var(--_pressed-state-layer-opacity), ) ); } .md3-segmented-button:enabled { cursor: pointer; } .md3-segmented-button__focus-ring { z-index: 1; } .md3-segmented-button__ripple { border-radius: inherit; z-index: 0; } .md3-segmented-button__touch { @include touch-target.touch-target($width: 100%); } .md3-segmented-button__leading, .md3-segmented-button__graphic { display: inline-flex; justify-content: flex-start; align-items: center; } .md3-segmented-button__graphic { position: relative; overflow: hidden; } .md3-segmented-button__graphic { transition: animation.standard(width, 150ms); } .md3-segmented-button--unselected.md3-segmented-button--with-label, .md3-segmented-button--unselected.md3-segmented-button--without-label, .md3-segmented-button--selected.md3-segmented-button--without-checkmark { .md3-segmented-button__graphic { width: 0; } } .md3-segmented-button--unselected .md3-segmented-button__checkmark { opacity: 0; } .md3-segmented-button--selected.md3-segmented-button--with-label { .md3-segmented-button__icon { opacity: 0; } } .md3-segmented-button--with-label .md3-segmented-button__checkmark { display: inline-flex; position: absolute; } .md3-segmented-button__checkmark-path { stroke-width: 2px; stroke-dasharray: 29.7833385; } .md3-segmented-button--selecting { .md3-segmented-button__checkmark-path { // We immediately render the checkmark in the animation start treatment // because we're using an animation delay. If we didn't have the delay, // the checkmark would render in the base fully-drawn state during the // brief animation-delay period which would look wrong. stroke-dashoffset: 29.7833385; animation: md3-segmented-button-checkmark-selection-draw-in; animation-duration: 150ms; animation-delay: 50ms; animation-fill-mode: forwards; animation-timing-function: animation.$standard-easing; } &.md3-segmented-button--with-label .md3-segmented-button__icon { animation: md3-segmented-button-simple-fade-out; animation-duration: 75ms; animation-timing-function: linear; animation-fill-mode: forwards; } } .md3-segmented-button--deselecting { .md3-segmented-button__checkmark { animation: md3-segmented-button-simple-fade-out; animation-duration: 50ms; animation-timing-function: linear; animation-fill-mode: forwards; } &.md3-segmented-button--with-label .md3-segmented-button__icon { // We immediately render the icon in the animation start treatment // because we're using an animation delay. If we didn't have the delay, // the icon would render with full opacity during the brief // animation-delay period which would look wrong. opacity: 0; animation: md3-segmented-button-simple-fade-in; animation-delay: 50ms; animation-duration: 150ms; animation-timing-function: linear; animation-fill-mode: forwards; } } } @function resolve-tokens($tokens) { $tokens: _flatten-disabled-colors($tokens); @return $tokens; } @function _flatten-disabled-colors($tokens) { @return color.join-color-and-opacity-pairs( $tokens, ( ( color-key: 'disabled-container-color', opacity-key: 'disabled-container-opacity' ), ( color-key: 'disabled-label-text-color', opacity-key: 'disabled-label-text-opacity' ), (color-key: 'disabled-icon-color', opacity-key: 'disabled-icon-opacity'), ( color-key: 'disabled-outline-color', opacity-key: 'disabled-outline-opacity' ) ) ); }