/
githubmirror
/
ionic-framework
Обзор
Документация
Войти
/
githubmirror
/
ionic-framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
core/src/components/item/item.scss
431 строка
11 KB
Shane
fix(checkbox,radio,toggle): add missing keyboard focus indicators (#31295)
01 авг 2026, 00:57
Не верифицирован
01 авг 2026, 00:57
2f9c0b7
Код
Авторство
О чём код?
@import "./item.vars"; // Item // -------------------------------------------------- :host { /** * @prop --background: Background of the item * @prop --background-activated: Background of the item when pressed. Note: setting this will interfere with the Material Design ripple. * @prop --background-activated-opacity: Opacity of the item background when pressed * @prop --background-focused: Background of the item when focused with the tab key * @prop --background-focused-opacity: Opacity of the item background when focused with the tab key * @prop --background-hover: Background of the item on hover * @prop --background-hover-opacity: Opacity of the background of the item on hover * * @prop --border-color: Color of the item border * @prop --border-radius: Radius of the item border * @prop --border-style: Style of the item border * @prop --border-width: Width of the item border * * @prop --color: Color of the item * @prop --color-activated: Color of the item when pressed * @prop --color-focused: Color of the item when focused with the tab key * @prop --color-hover: Color of the item on hover * * @prop --detail-icon-color: Color of the item detail icon * @prop --detail-icon-opacity: Opacity of the item detail icon * @prop --detail-icon-font-size: Font size of the item detail icon * * @prop --inner-border-width: Width of the item inner border * @prop --inner-box-shadow: Box shadow of the item inner * @prop --inner-padding-top: Top padding of the item inner * @prop --inner-padding-end: Right padding if direction is left-to-right, and left padding if direction is right-to-left of the item inner * @prop --inner-padding-bottom: Bottom padding of the item inner * @prop --inner-padding-start: Left padding if direction is left-to-right, and right padding if direction is right-to-left of the item inner * * @prop --min-height: Minimum height of the item * * @prop --padding-bottom: Bottom padding of the item * @prop --padding-end: Right padding if direction is left-to-right, and left padding if direction is right-to-left of the item * @prop --padding-start: Left padding if direction is left-to-right, and right padding if direction is right-to-left of the item * @prop --padding-top: Top padding of the item * * @prop --transition: Transition of the item * * @prop --ripple-color: Color of the item ripple effect * */ --border-radius: 0px; --border-width: 0px; --border-style: solid; --padding-top: 0px; --padding-bottom: 0px; --padding-end: 0px; --padding-start: 0px; --inner-border-width: 0px; --inner-padding-top: 0px; --inner-padding-bottom: 0px; --inner-padding-start: 0px; --inner-padding-end: 0px; --inner-box-shadow: none; --detail-icon-color: initial; --detail-icon-font-size: 1.25em; --detail-icon-opacity: 0.25; --color-activated: var(--color); --color-focused: var(--color); --color-hover: var(--color); --ripple-color: currentColor; @include font-smoothing(); display: block; position: relative; align-items: center; justify-content: space-between; outline: none; color: var(--color); font-family: $font-family-base; text-align: initial; text-decoration: none; overflow: hidden; box-sizing: border-box; } // Item: Color // -------------------------------------------------- :host(.ion-color) .item-native { background: current-color(base); color: current-color(contrast); } :host(.ion-color) .item-native, :host(.ion-color) .item-inner { border-color: current-color(shade); } // Item: Activated // -------------------------------------------------- :host(.ion-activated) .item-native { color: var(--color-activated); &::after { background: var(--background-activated); opacity: var(--background-activated-opacity); } } :host(.ion-color.ion-activated) .item-native { color: current-color(contrast); } // Item: Focused // -------------------------------------------------- :host(.ion-focused) .item-native { color: var(--color-focused); &::after { background: var(--background-focused); opacity: var(--background-focused-opacity); } } :host(.ion-color.ion-focused) .item-native { color: current-color(contrast); &::after { background: current-color(contrast); } } // Item: Hover // -------------------------------------------------- @media (any-hover: hover) { :host(.ion-activatable:not(.ion-focused):hover) .item-native { color: var(--color-hover); &::after { background: var(--background-hover); opacity: var(--background-hover-opacity); } } :host(.ion-color.ion-activatable:not(.ion-focused):hover) .item-native { color: #{current-color(contrast)}; &::after { background: #{current-color(contrast)}; } } } // Item: Interactive // -------------------------------------------------- // Inputs and textareas do not need the cursor, but other components like checkbox or toggle do. :host(.item-control-needs-pointer-cursor) { cursor: pointer; } // Item: Disabled // -------------------------------------------------- :host(.item-interactive-disabled:not(.item-multiple-inputs)) { cursor: default; pointer-events: none; } :host(.item-disabled) { cursor: default; opacity: 0.3; pointer-events: none; } // Native Item // -------------------------------------------------- .item-native { @include border-radius(var(--border-radius)); @include margin(0); @include padding(var(--padding-top), null, var(--padding-bottom)); @include text-inherit(); /* stylelint-disable */ @include ltr() { padding-right: var(--padding-end); padding-left: calc(var(--padding-start) + var(--ion-safe-area-left, 0px)); } @include rtl() { padding-right: calc(var(--padding-start) + var(--ion-safe-area-right, 0px)); padding-left: var(--padding-end); } /* stylelint-enable */ display: flex; position: relative; align-items: inherit; justify-content: inherit; width: 100%; min-height: var(--min-height); transition: var(--transition); border-width: var(--border-width); border-style: var(--border-style); border-color: var(--border-color); outline: none; background: var(--background); overflow: inherit; z-index: 1; box-sizing: border-box; } .item-native::-moz-focus-inner { border: 0; } .item-native::after { @include button-state(); transition: var(--transition); z-index: -1; } button, a { cursor: pointer; user-select: none; -webkit-user-drag: none; } // Inner Item // -------------------------------------------------- .item-inner { @include margin(0); @include padding(var(--inner-padding-top), null, var(--inner-padding-bottom)); /* stylelint-disable */ @include ltr() { padding-right: calc(var(--ion-safe-area-right, 0px) + var(--inner-padding-end)); padding-left: var(--inner-padding-start); } @include rtl() { padding-right: var(--inner-padding-start); padding-left: calc(var(--ion-safe-area-left, 0px) + var(--inner-padding-end)); } /* stylelint-enable */ display: flex; // This is required to work with an inset highlight position: relative; flex: 1; flex-direction: inherit; align-items: inherit; align-self: stretch; min-height: inherit; border-width: var(--inner-border-width); border-style: var(--border-style); border-color: var(--border-color); box-shadow: var(--inner-box-shadow); overflow: inherit; box-sizing: border-box; } // Item Detail Icon // -------------------------------------------------- .item-detail-icon { /** * IonItem applies its own end padding. However, * all IonIcons have the same bounding box meaning * there may be white space for narrow icons. As * a result, the white space gives the appearance * that there is too much end margin. We move the default * chevron icon over to account for this extra whitespace. */ @include margin(null, -6px, null, calc(var(--inner-padding-end) / 2)); color: var(--detail-icon-color); font-size: var(--detail-icon-font-size); opacity: var(--detail-icon-opacity); } // Item Slots // -------------------------------------------------- ::slotted(ion-icon) { font-size: 1.6em; } ::slotted(ion-button) { --margin-top: 0; --margin-bottom: 0; --margin-start: 0; --margin-end: 0; z-index: 1; } ::slotted(ion-label:not([slot="end"])) { flex: 1; // Setting width to min-content allows the label to // shrink and wrap its text instead of moving to its // own row if there are slotted elements next to it width: min-content; /** * We allow labels in the default * slot to grow. However, we do not * want them to grow indefinitely. */ max-width: 100%; } // Item Input // -------------------------------------------------- :host(.item-input) { align-items: center; } .input-wrapper { display: flex; // This flex property is required in order to keep // the label from shrinking when there are wide // elements next to it flex: 1; flex-direction: inherit; align-items: inherit; align-self: stretch; text-overflow: ellipsis; // Makes the wrapper a scroll container, which zeroes its automatic minimum // size and lets long labels ellipsize overflow: inherit; box-sizing: border-box; } :host(.item-label-stacked), :host(.item-label-floating) { align-items: start; } :host(.item-label-stacked) .input-wrapper, :host(.item-label-floating) .input-wrapper { flex: 1; flex-direction: column; } // Item Focus Indicator Room // -------------------------------------------------- // Widens the clip boundary so a focus indicator on a control in the default // slot isn't cut off. Scoped because the wider painted box overlaps end slot // content on items with nothing overhanging :host(.item-focus-indicator-room) .input-wrapper { @include margin-horizontal(-$item-input-focus-indicator-room); @include padding-horizontal($item-input-focus-indicator-room); } // Item w/ Multiple Inputs // -------------------------------------------------- // Multiple inputs in an item should have the input // cover relative to themselves instead of the item :host(.item-multiple-inputs) ::slotted(ion-checkbox), :host(.item-multiple-inputs) ::slotted(ion-datetime), :host(.item-multiple-inputs) ::slotted(ion-radio) { position: relative; } // Item Textarea // -------------------------------------------------- :host(.item-textarea) { align-items: stretch; } // Item Reorder // -------------------------------------------------- ::slotted(ion-reorder[slot]) { @include margin(0, null); } // Item Button Ripple effect // -------------------------------------------------- ion-ripple-effect { color: var(--ripple-color); }