/* * Rows a person can go into (`data-list-row`, resources/js/list-rows.js), and M3 Expressive lists. * * A row answers a pointer with M3's state layer — hover 8%, press and focus 10% — but not while the * pointer is on one of its own controls, which light only themselves. Hover only under * `(hover: hover)`, because a touch screen keeps the last hover after a tap. The opener draws no * focus ring inside a row; the row draws it, inset, so keyboard focus shows which row Enter opens. * `data-selected` is M3's selected list item, in secondary-container. * * Unlayered where a component paints its fill as a utility (``): anything in a @layer loses * to a utility whatever its specificity. * * Every selector that paints a row is `:where()`, so they all weigh nothing and the later rule * wins: the segmented list's own fill is declared first and a row's state layer, further down, * paints over it. Written any other way — outside the layer, or with its real specificity — the * fill would beat the state layer and a segmented row would answer nothing. */ @layer components { /* * M3 Expressive's segmented list gives each item its own container. ListTokens.kt:201 — * `ItemSegmentedContainerColor get() = ColorSchemeKeyTokens.Surface`. */ :where([data-list='segmented'] > [data-list-item]) { background-color: var(--md-sys-color-surface); } /* * ListTokens.kt:30,36 — `DividerLeadingSpace` and `DividerTrailingSpace` are 16dp, so a * list's dividers are inset from both ends rather than full-bleed (``). */ :where([data-list][data-dividers] > [data-list-item]:not(:last-child))::after { content: ''; position: absolute; inset-inline: 16px; bottom: 0; height: 1px; background-color: var(--md-sys-color-outline-variant); pointer-events: none; } :where([data-list-row]) { cursor: pointer; transition: background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast), border-radius var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast); } @media (hover: hover) { :where([data-list-row]:not([data-card]):hover:not(:has(:is(a, button, input, select, textarea, label, summary):not([data-list-open]):hover))) { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 8%, transparent); } } :where([data-list-row]:not([data-card]):has([data-list-open]:focus-visible)) { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent); outline: 3px solid var(--md-sys-color-secondary); outline-offset: -3px; } :where([data-list-row]:not([data-card]):active:not(:has(:is(a, button, input, select, textarea, label, summary):not([data-list-open]):active))) { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent); } } [data-list-row] [data-list-open]:focus-visible { outline: none; } :is([data-list-row], [data-list-item])[data-selected]:not([data-card]) { background-color: var(--md-sys-color-secondary-container); color: var(--md-sys-color-on-secondary-container); } /* A card that opens answers with its container one tone up and its corner opening a step. */ [data-card][data-list-row] { transition-property: border-radius, background-color, box-shadow; transition-duration: var(--md-sys-motion-spatial-default-duration); transition-timing-function: var(--md-sys-motion-spatial-default); } @media (hover: hover) { [data-card][data-list-row]:hover:not(:has(:is(a, button, input, select, textarea, label, summary):not([data-list-open]):hover)) { border-radius: var(--md-sys-shape-corner-lg); box-shadow: inset 0 0 0 100vmax color-mix(in srgb, var(--md-sys-color-on-surface) 8%, transparent); } } [data-card][data-list-row]:active:not(:has(:is(a, button, input, select, textarea, label, summary):not([data-list-open]):active)) { box-shadow: inset 0 0 0 100vmax color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent); } [data-card][data-list-row]:has([data-list-open]:focus-visible) { outline: 3px solid var(--md-sys-color-secondary); outline-offset: 2px; } /* * M3 Expressive's segmented list (``): each item its own surface, 2px apart, * extra-small corners that open to medium while hovered and to large at the ends and while * focused, pressed or selected — the specs page's interaction-state expressive shapes, and * ListTokens' `ItemPressedContainerExpressiveShape` / `ItemDraggedContainerExpressiveShape` * (androidx Compose Material 3, Apache-2.0). */ [data-list='segmented'] > [data-list-item] { border-radius: var(--md-sys-shape-corner-xs); } [data-list='segmented'] > [data-list-item]:first-child { border-start-start-radius: var(--md-sys-shape-corner-lg); border-start-end-radius: var(--md-sys-shape-corner-lg); } [data-list='segmented'] > [data-list-item]:last-child { border-end-start-radius: var(--md-sys-shape-corner-lg); border-end-end-radius: var(--md-sys-shape-corner-lg); } @media (hover: hover) { [data-list='segmented'] > [data-list-item][data-list-row]:hover { border-radius: var(--md-sys-shape-corner-md); } } [data-list='segmented'] > [data-list-item]:is([data-selected], [data-list-row]:active, [data-list-row]:has([data-list-open]:focus-visible)) { border-radius: var(--md-sys-shape-corner-lg); }