/
githubmirror
/
ionic-framework
Обзор
Документация
Войти
/
githubmirror
/
ionic-framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
core/src/components/select/select.scss
640 строк
17 KB
Maria Hutt
fix(select): update icon color and use correct focused class (#30342)
16 апр 2025, 20:16
Не верифицирован
16 апр 2025, 20:16
cad1c61
Код
Авторство
О чём код?
@import "./select.vars"; // Select // -------------------------------------------------- :host { /** * @prop --background: Background of the select * @prop --padding-top: Top padding of the select * @prop --padding-end: Right padding if direction is left-to-right, and left padding if direction is right-to-left of the select * @prop --padding-bottom: Bottom padding of the select * @prop --padding-start: Left padding if direction is left-to-right, and right padding if direction is right-to-left of the select * * @prop --placeholder-color: Color of the select placeholder text * @prop --placeholder-opacity: Opacity of the select placeholder text * * @prop --highlight-height: The height of the highlight on the select. Only applies to md mode. * @prop --highlight-color-focused: The color of the highlight on the select when focused * @prop --highlight-color-invalid: The color of the highlight on the select when invalid * @prop --highlight-color-valid: The color of the highlight on the select when valid * * @prop --border-color: Color of the select border * @prop --border-radius: Radius of the select border. A large radius may display unevenly when using fill="outline"; if needed, use shape="round" instead or increase --padding-start. * @prop --border-style: Style of the select border * @prop --border-width: Width of the select border * * @prop --ripple-color: The color of the ripple effect on MD mode. */ --padding-top: 0px; --padding-end: 0px; --padding-bottom: 0px; --padding-start: 0px; --placeholder-color: currentColor; --placeholder-opacity: #{$placeholder-opacity}; --background: transparent; --border-style: solid; --highlight-color-focused: #{ion-color(primary, base)}; --highlight-color-valid: #{ion-color(success, base)}; --highlight-color-invalid: #{ion-color(danger, base)}; /** * This is a private API that is used to switch * out the highlight color based on the state * of the component without having to write * different selectors for different fill variants. */ --highlight-color: var(--highlight-color-focused); display: block; position: relative; width: 100%; min-height: 44px; font-family: $font-family-base; white-space: nowrap; cursor: pointer; z-index: $z-index-item-input; } /** * Since the label sits on top of the element, * the component needs to be taller otherwise the * label will appear too close to the select text. */ :host(.select-label-placement-floating), :host(.select-label-placement-stacked) { min-height: 56px; } :host(.ion-color) { --highlight-color-focused: #{current-color(base)}; } // Select Used in ion-item // -------------------------------------------------- // The flex property is required here in order to allow // the select to shrink inside of an item otherwise it // always wraps to the next line even when it can shrink :host(.in-item) { flex: 1 1 0; } :host(.select-disabled) { pointer-events: none; } :host(.has-focus) button { border: 2px solid #5e9ed6; } /** * Select can be slotted * in components such as item and * toolbar which is why we do not * limit the below behavior to just ion-item. */ :host([slot="start"]), :host([slot="end"]) { // Reset the flex property when the select // is slotted to avoid growing the element larger // than its content. flex: initial; width: auto; } .select-placeholder { color: var(--placeholder-color); opacity: var(--placeholder-opacity); } button { @include visually-hidden(); } // Select Icon // -------------------------------------------------- .select-icon { @include margin(0, 0, 0, $select-icon-margin-start); position: relative; /** * Prevent the icon from shrinking when the label and/or * selected item text is long enough to fill the rest of * the container. */ flex-shrink: 0; } /** * Ensure that the select icon has * the correct color contrast when * used inside of an item. */ :host(.in-item-color) .select-icon { color: inherit; } /** * The select icon should be centered with * the entire container not just the control * with floating/stacked labels. */ :host(.select-label-placement-stacked) .select-icon, :host(.select-label-placement-floating) .select-icon { position: absolute; height: 100%; } /** * This positions the icon at the correct * edge of the component with LTR and RTL * text directions. The position mixin cannot be * used here because the icon is in the Shadow DOM. */ :host(.select-ltr.select-label-placement-stacked) .select-icon, :host(.select-ltr.select-label-placement-floating) .select-icon { // stylelint-disable-next-line property-disallowed-list right: var(--padding-end, 0); } :host(.select-rtl.select-label-placement-stacked) .select-icon, :host(.select-rtl.select-label-placement-floating) .select-icon { // stylelint-disable-next-line property-disallowed-list left: var(--padding-start, 0); } // Select Text // -------------------------------------------------- .select-text { flex: 1; min-width: 16px; font-size: inherit; text-overflow: ellipsis; white-space: inherit; overflow: hidden; } // Select Wrapper // -------------------------------------------------- .select-wrapper { @include padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start)); @include border-radius(var(--border-radius)); display: flex; position: relative; flex-grow: 1; align-items: center; justify-content: space-between; height: inherit; /** * This allows developers to set the height * on the host of the element but still have * the label take up the full height * of the parent. */ min-height: inherit; transition: background-color 15ms linear; background: var(--background); line-height: normal; cursor: inherit; box-sizing: border-box; } .select-wrapper .select-placeholder { /** * When the floating label appears on top of the * select, we need to fade the text out so that the * label does not overlap with the placeholder. */ transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1); } .select-wrapper-inner { display: flex; align-items: center; overflow: hidden; } :host(.select-label-placement-stacked) .select-wrapper-inner, :host(.select-label-placement-floating) .select-wrapper-inner { /** * When using a stacked/floating label, the inner wrapper is * stacked vertically under the label container. This line * ensures that the inner wrapper fills all the remaining height * of the component. */ flex-grow: 1; } // Select Highlight // ---------------------------------------------------------------- :host(.ion-touched.ion-invalid) { --highlight-color: var(--highlight-color-invalid); } /** * The component highlight is only shown * on focus, so we can safely set the valid * color state when touched/valid. If we * set it when .has-focus is present then * the highlight color would change * from the valid color to the component's * color during the transition after the * component loses focus. */ :host(.ion-valid) { --highlight-color: var(--highlight-color-valid); } // Select Bottom Content // ---------------------------------------------------------------- .select-bottom { /** * The bottom content should take on the start and end * padding so it is always aligned with either the label * or the start of the text select. */ @include padding(5px, var(--padding-end), 0, var(--padding-start)); display: flex; justify-content: space-between; border-top: var(--border-width) var(--border-style) var(--border-color); font-size: dynamic-font(12px); white-space: normal; } /** * If the select has a validity state, the * border and label should reflect that as a color. * The invalid state should show if the select is * invalid and has already been touched. * The valid state should show if the select * is valid, has already been touched, and * is currently focused. Do not show the valid * highlight when the select is blurred. */ :host(.has-focus.ion-valid), :host(.select-expanded.ion-valid), :host(.ion-touched.ion-invalid), :host(.select-expanded.ion-touched.ion-invalid) { --border-color: var(--highlight-color); } // Select Hint Text // ---------------------------------------------------------------- /** * Error text should only be shown when .ion-invalid is * present on the select. Otherwise the helper text should * be shown. */ .select-bottom .error-text { display: none; color: var(--highlight-color-invalid); } .select-bottom .helper-text { display: block; color: $text-color-step-300; } :host(.ion-touched.ion-invalid) .select-bottom .error-text { display: block; } :host(.ion-touched.ion-invalid) .select-bottom .helper-text { display: none; } // Select Label // ---------------------------------------------------------------- .label-text-wrapper { /** * This causes the label to take up * the entire height of its container * while still keeping the text centered. */ display: flex; align-items: center; /** * Label text should not extend * beyond the bounds of the select. * However, we do not set the max * width to 100% because then * only the label would show and users * would not be able to see what they are typing. */ max-width: 200px; transition: color 150ms cubic-bezier(.4, 0, .2, 1), transform 150ms cubic-bezier(.4, 0, .2, 1); /** * This ensures that double tapping this text * clicks the <label> and focuses the input * when a screen reader is enabled. */ pointer-events: none; } /** * We need to use two elements instead of * one. The .label-text-wrapper is responsible * for centering the label text vertically regardless * of the input height using flexbox. * * The .label-text element is responsible for controlling * overflow when label-placement="fixed". * We want the ellipses to show up when the * fixed label overflows, but text-overflow: ellipsis only * works on block-level elements. A flex item is * considered blockified (https://www.w3.org/TR/css-display-3/#blockify). */ .label-text, ::slotted([slot="label"]) { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } /** * If no label text is placed into the slot * then the element should be hidden otherwise * there will be additional margins added. */ .label-text-wrapper-hidden, .select-outline-notch-hidden { display: none; } // Select Native Wrapper // ---------------------------------------------------------------- .native-wrapper { display: flex; align-items: center; /** * When the floating label appears on top of the * input, we need to fade the input out so that the * label does not overlap with the placeholder. */ transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1); /** * This ensures that the .select-text gets * truncated with ellipses when the text is * too long for the screen. */ overflow: hidden; } // Select Justify // -------------------------------------------------- :host(.select-justify-space-between) .select-wrapper { justify-content: space-between; } :host(.select-justify-start) .select-wrapper { justify-content: start; } :host(.select-justify-end) .select-wrapper { justify-content: end; } // Select Label Placement - Start // ---------------------------------------------------------------- /** * Label is on the left of the input in LTR and * on the right in RTL. */ :host(.select-label-placement-start) .select-wrapper { flex-direction: row; } :host(.select-label-placement-start) .label-text-wrapper { /** * The margin between the label and * the select should be on the end * when the label sits at the start. */ @include margin(0, $form-control-label-margin, 0, 0); } // Select Label Placement - End // ---------------------------------------------------------------- /** * Label is on the right of the select in LTR and * on the left in RTL. */ :host(.select-label-placement-end) .select-wrapper { flex-direction: row-reverse; } /** * The margin between the label and * the select should be on the start * when the label sits at the end. */ :host(.select-label-placement-end) .label-text-wrapper { @include margin(0, 0, 0, $form-control-label-margin); } // Select Label Placement - Fixed // ---------------------------------------------------------------- :host(.select-label-placement-fixed) .label-text-wrapper { /** * The margin between the label and * the select should be on the end * when the label sits at the start. */ @include margin(0, $form-control-label-margin, 0, 0); } /** * Label is on the left of the select in LTR and * on the right in RTL. Label also has a fixed width. */ :host(.select-label-placement-fixed) .label-text-wrapper { flex: 0 0 100px; width: 100px; min-width: 100px; max-width: 200px; } // Select Label Placement - Stacked and Floating // ---------------------------------------------------------------- /** * Stacked: Label sits above the select and is scaled down. * Floating: Label sits over the select when the select has no * value and is blurred. Label sits above the input and is scaled * down when the select is focused or has a value. * */ :host(.select-label-placement-stacked) .select-wrapper, :host(.select-label-placement-floating) .select-wrapper { flex-direction: column; align-items: start; } /** * Ensures that the label animates * up and to the left in LTR or * up and to the right in RTL. */ :host(.select-label-placement-stacked) .label-text-wrapper, :host(.select-label-placement-floating) .label-text-wrapper { max-width: 100%; } :host(.select-ltr.select-label-placement-stacked) .label-text-wrapper, :host(.select-ltr.select-label-placement-floating) .label-text-wrapper { // stylelint-disable-next-line property-disallowed-list transform-origin: left top; } :host(.select-rtl.select-label-placement-stacked) .label-text-wrapper, :host(.select-rtl.select-label-placement-floating) .label-text-wrapper { // stylelint-disable-next-line property-disallowed-list transform-origin: right top; } /** * Ensures the select does not * overlap the label. * Also ensure that the native wrapper * takes up the remaining available height and width. */ :host(.select-label-placement-stacked) .native-wrapper, :host(.select-label-placement-floating) .native-wrapper { @include margin(1px, 0, 0, 0); flex-grow: 1; width: 100%; } /** * This makes the label sit over the select * when the select is blurred and has no value. * The label should not sit over the select if the * select has a placeholder. * Note: This is different from what ion-input does * because the activating the select causes an overlay * to appear. This makes it hard to read the placeholder. * With ion-input, the input just focuses and the placeholder * is still easy to read. */ :host(.select-label-placement-floating) .label-text-wrapper { @include transform(translateY(100%), scale(1)); } /** * The placeholder should be hidden when the label * is on top of the select. This prevents the label * from overlapping any placeholder value. * * TODO(FW-5592): Remove :not(.label-floating) piece */ :host(.select-label-placement-floating:not(.label-floating)) .native-wrapper .select-placeholder { opacity: 0; } /** * We don't use .label-floating here because that would * also include the case where the label is floating due * to content in the start/end slot. We want the opacity * to remain at the default in this case, since the select * isn't being actively interacted with. * * TODO(FW-5592): Change entire selector to: * :host(.label-floating.select-label-placement-floating) .native-wrapper .select-placeholder */ :host(.select-expanded.select-label-placement-floating) .native-wrapper .select-placeholder, :host(.has-focus.select-label-placement-floating) .native-wrapper .select-placeholder, :host(.has-value.select-label-placement-floating) .native-wrapper .select-placeholder { opacity: 1; } /** * This makes the label sit above the input. */ :host(.label-floating) .label-text-wrapper { @include transform(translateY(50%), scale(#{$form-control-label-stacked-scale})); /** * Label text should not extend * beyond the bounds of the input. */ max-width: calc(100% / #{$form-control-label-stacked-scale}); } // Start/End Slots // ---------------------------------------------------------------- ::slotted([slot="start"]), ::slotted([slot="end"]) { /** * Prevent the slots from shrinking when the label and/or * selected item text is long enough to fill the rest of * the container. */ flex-shrink: 0; } ::slotted([slot="start"]:last-of-type) { margin-inline-end: $form-control-label-margin; margin-inline-start: 0; } ::slotted([slot="end"]:first-of-type) { margin-inline-start: $form-control-label-margin; margin-inline-end: 0; }