/
githubmirror
/
components
Обзор
Документация
Войти
/
githubmirror
/
components
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/material/list/list.scss
185 строк
7 KB
Andrew Seguin
fix(multiple): use focus-visible for focus indicator (#32514)
10 дек 2025, 23:59
Не верифицирован
10 дек 2025, 23:59
d4e104a
Код
Авторство
О чём код?
@use '../core/style/layout-common'; @use './m3-list'; @use '../core/tokens/token-utils'; @use './list-item-hcm-indicator'; @use './list-inherited-structure'; $fallbacks: m3-list.get-tokens(); @include list-inherited-structure.private-list-inherited-structural-styles; // Add additional slots for the MDC list tokens, needed in Angular Material. // MDC allows focus and hover colors to take precedence over disabled color. We add the disabled // color here with higher specificity so that the disabled color takes precedence. // TODO(mmalerba): Dicuss with MDC whether to change this in their code. .mdc-list-item.mdc-list-item--disabled .mdc-list-item__primary-text { color: token-utils.slot(list-list-item-disabled-label-text-color, $fallbacks); } // We don't use MDC's state layer since it's tied in with their ripple. Instead we emit slots // for our own state layer. // TODO(mmalerba): Consider using MDC's ripple & state layer. .mdc-list-item:hover::before { background-color: token-utils.slot(list-list-item-hover-state-layer-color, $fallbacks); opacity: token-utils.slot(list-list-item-hover-state-layer-opacity, $fallbacks); } .mdc-list-item.mdc-list-item--disabled::before { background-color: token-utils.slot(list-list-item-disabled-state-layer-color, $fallbacks); opacity: token-utils.slot(list-list-item-disabled-state-layer-opacity, $fallbacks); } .mdc-list-item:focus::before { background-color: token-utils.slot(list-list-item-focus-state-layer-color, $fallbacks); opacity: token-utils.slot(list-list-item-focus-state-layer-opacity, $fallbacks); } // Apply the disabled opacity to the checkbox/radio indicators. // TODO(mmalerba): We should probably stop doing this and allow the checkbox/radio to decide // what their disabled state looks like. This is done for now to avoid screenshot diffs. .mdc-list-item--disabled { .mdc-radio, .mdc-checkbox { opacity: token-utils.slot(list-list-item-disabled-label-text-opacity, $fallbacks); } } // In Angular Material we put the avatar class directly on the .mdc-list-item__start element, // rather than nested inside it, so we need to emit avatar slots ourselves. // TODO(mmalerba): We should try to change MDC's recommended DOM or change ours to match their // recommendation. .mdc-list-item--with-leading-avatar .mat-mdc-list-item-avatar { border-radius: token-utils.slot(list-list-item-leading-avatar-shape, $fallbacks); background-color: token-utils.slot(list-list-item-leading-avatar-color, $fallbacks); } // Set font-size of leading icon to same value as its width and height. Ensure icon scales to // "list-item-leading-icon-size" token. In Angular Material, the icon is on the same element as // ".mdc-list-item__start", rather than a child of ".mdc-list-item__start". .mat-mdc-list-item-icon { font-size: token-utils.slot(list-list-item-leading-icon-size, $fallbacks); } a.mdc-list-item--activated { // Improve accessibility for Window High Contrast Mode (HCM) by adding an idicator on active // links. @include list-item-hcm-indicator.private-high-contrast-list-item-indicator(); } // MDC expects the list element to be a `<ul>`, since we use `<mat-list>` instead we need to // explicitly set `display: block` .mat-mdc-list-base { display: block; // MDC sets `pointer-events: none` on these elements, // even though we allowed interactive content in them. .mdc-list-item__start, .mdc-list-item__end, .mdc-list-item__content { pointer-events: auto; } } .mat-mdc-list-item, .mat-mdc-list-option { // MDC expects that the list items are always `<li>`, since we actually use `<button>` in some // cases, we need to make sure it expands to fill the available width. width: 100%; box-sizing: border-box; -webkit-tap-highlight-color: transparent; &:not(.mat-mdc-list-item-interactive) { cursor: default; } // MDC doesn't have list dividers, so we use mat-divider and style appropriately. // TODO(devversion): check if we can use the MDC dividers. .mat-divider-inset { position: absolute; left: 0; right: 0; bottom: 0; } .mat-mdc-list-item-avatar ~ .mat-divider-inset { margin-left: 72px; [dir='rtl'] & { margin-right: 72px; } } } // MDC's hover and focus state styles are included with their ripple which we don't use. // Instead we add the focus, hover and selected styles ourselves using this pseudo-element .mat-mdc-list-item-interactive::before { @include layout-common.fill(); content: ''; opacity: 0; pointer-events: none; // This comes up in some internal implementations. border-radius: inherit; } // The MDC-based list items already use the `::before` pseudo element for the standard // focus/selected/hover state. Hence, we need to have a separate list-item spanning // element that can be used for strong focus indicators. .mat-mdc-list-item { > .mat-focus-indicator { @include layout-common.fill(); pointer-events: none; } // For list items, render the focus indicator when the parent // listem item is focused. &:focus-visible > .mat-focus-indicator::before { content: ''; } } .mat-mdc-list-item.mdc-list-item--with-three-lines { .mat-mdc-list-item-line.mdc-list-item__secondary-text { white-space: nowrap; line-height: normal; } // Unscoped content can wrap if the list item has acquired three lines. MDC implements // this functionality for secondary text but there is no proper text ellipsis when // text overflows the third line. These styles ensure the overflow is handled properly. // TODO: Move this to the MDC list once it drops IE11 support. .mat-mdc-list-item-unscoped-content.mdc-list-item__secondary-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; } } // MDC doesn't account for button being used as a list item. We override some of // the default button styles here so that they look right when used as a list // item. mat-action-list button { background: none; color: inherit; border: none; font: inherit; outline: inherit; -webkit-tap-highlight-color: transparent; text-align: start; &::-moz-focus-inner { border: 0; } } .mdc-list-item--with-leading-icon .mdc-list-item__start { margin-inline-start: token-utils.slot(list-list-item-leading-icon-start-space, $fallbacks); margin-inline-end: token-utils.slot(list-list-item-leading-icon-end-space, $fallbacks); } .mat-mdc-nav-list .mat-mdc-list-item { border-radius: token-utils.slot(list-active-indicator-shape, $fallbacks); --mat-focus-indicator-border-radius: #{token-utils.slot(list-active-indicator-shape, $fallbacks)}; &.mdc-list-item--activated { background-color: token-utils.slot(list-active-indicator-color, $fallbacks); } }