| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- //
- // Copyright 2017 Google Inc.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- // stylelint-disable selector-class-pattern --
- // Selector '.mdc-*' should only be used in this project.
- @use 'sass:math';
- @use '@material/elevation/mixins' as elevation-mixins;
- @use '@material/feature-targeting/feature-targeting';
- @use '@material/ripple/ripple';
- @use '@material/ripple/ripple-theme';
- @use '@material/rtl/rtl';
- @use '@material/shape/mixins' as shape-mixins;
- @use '@material/theme/theme';
- @use './variables';
- @use '@material/theme/theme-color';
- @use '@material/dom/mixins' as dom-mixins;
- //
- // Public
- //
- $ripple-target: '.mdc-card__ripple';
- @mixin core-styles($query: feature-targeting.all()) {
- @include without-ripple($query);
- @include ripple($query);
- }
- @mixin static-styles($query: feature-targeting.all()) {
- $feat-structure: feature-targeting.create-target($query, structure);
- $feat-color: feature-targeting.create-target($query, color);
- .mdc-card {
- @include feature-targeting.targets($feat-structure) {
- @include container-layout_;
- }
- // Transparent card border for high-contrast mode.
- &::after {
- @include dom-mixins.transparent-border($query: $query);
- @include feature-targeting.targets($feat-structure) {
- pointer-events: none;
- }
- }
- }
- .mdc-card--outlined {
- // Outlined card already displays border in high-contrast mode.
- // Overwriting styles set above to remove a duplicate border.
- &::after {
- @include feature-targeting.targets($feat-structure) {
- border: none;
- }
- }
- }
- .mdc-card__content {
- @include feature-targeting.targets($feat-structure) {
- border-radius: inherit;
- height: 100%;
- }
- }
- //
- // Media
- //
- .mdc-card__media {
- @include feature-targeting.targets($feat-structure) {
- position: relative; // Child element `__media-content` has `position: absolute`
- box-sizing: border-box;
- background-repeat: no-repeat;
- background-position: center;
- background-size: cover;
- }
- &::before {
- @include feature-targeting.targets($feat-structure) {
- display: block;
- content: '';
- }
- }
- }
- .mdc-card__media:first-child {
- @include feature-targeting.targets($feat-structure) {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- }
- }
- .mdc-card__media:last-child {
- @include feature-targeting.targets($feat-structure) {
- border-bottom-left-radius: inherit;
- border-bottom-right-radius: inherit;
- }
- }
- .mdc-card__media--square {
- @include media-aspect-ratio(1, 1, $query);
- }
- .mdc-card__media--16-9 {
- @include media-aspect-ratio(16, 9, $query);
- }
- .mdc-card__media-content {
- @include feature-targeting.targets($feat-structure) {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- box-sizing: border-box;
- }
- }
- //
- // Primary action
- //
- .mdc-card__primary-action {
- @include feature-targeting.targets($feat-structure) {
- @include container-layout_;
- position: relative; // Needed to prevent the ripple wash from overflowing the container in IE and Edge
- outline: none;
- color: inherit;
- text-decoration: none;
- cursor: pointer;
- overflow: hidden;
- }
- }
- .mdc-card__primary-action:first-child {
- @include feature-targeting.targets($feat-structure) {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- }
- }
- .mdc-card__primary-action:last-child {
- @include feature-targeting.targets($feat-structure) {
- border-bottom-left-radius: inherit;
- border-bottom-right-radius: inherit;
- }
- }
- //
- // Action row
- //
- .mdc-card__actions {
- @include feature-targeting.targets($feat-structure) {
- @include actions-layout_;
- min-height: 52px;
- padding: 8px;
- }
- }
- .mdc-card__actions--full-bleed {
- @include feature-targeting.targets($feat-structure) {
- padding: 0;
- }
- }
- .mdc-card__action-buttons,
- .mdc-card__action-icons {
- @include feature-targeting.targets($feat-structure) {
- @include actions-layout_;
- }
- }
- .mdc-card__action-icons {
- @include feature-targeting.targets($feat-color) {
- @include theme.property(color, variables.$action-icon-color);
- }
- @include feature-targeting.targets($feat-structure) {
- flex-grow: 1;
- justify-content: flex-end;
- }
- }
- .mdc-card__action-buttons + .mdc-card__action-icons {
- @include feature-targeting.targets($feat-structure) {
- @include rtl.reflexive-box(margin, left, 16px);
- }
- }
- //
- // Action items
- //
- .mdc-card__action {
- @include feature-targeting.targets($feat-structure) {
- @include actions-layout_(inline-flex);
- justify-content: center;
- cursor: pointer;
- user-select: none;
- }
- &:focus {
- @include feature-targeting.targets($feat-structure) {
- outline: none;
- }
- }
- }
- //
- // Action buttons
- //
- .mdc-card__action--button {
- @include feature-targeting.targets($feat-structure) {
- @include rtl.reflexive-box(margin, right, 8px);
- padding: 0 8px;
- }
- &:last-child {
- @include feature-targeting.targets($feat-structure) {
- @include rtl.reflexive-box(margin, right, 0);
- }
- }
- }
- .mdc-card__actions--full-bleed .mdc-card__action--button {
- @include feature-targeting.targets($feat-structure) {
- justify-content: space-between;
- width: 100%;
- height: auto;
- max-height: none;
- margin: 0;
- padding: 8px 16px;
- @include rtl.ignore-next-line();
- text-align: left;
- }
- @include rtl.rtl {
- @include feature-targeting.targets($feat-structure) {
- @include rtl.ignore-next-line();
- text-align: right;
- }
- }
- }
- //
- // Action icons
- //
- .mdc-card__action--icon {
- @include feature-targeting.targets($feat-structure) {
- // Icon buttons are taller than buttons, so we need to adjust their margins to prevent the action row from
- // expanding.
- margin: -6px 0;
- // Same padding as mdc-icon-button.
- padding: 12px;
- }
- }
- .mdc-card__action--icon:not(:disabled) {
- @include feature-targeting.targets($feat-color) {
- @include theme.property(color, variables.$action-icon-color);
- }
- }
- }
- // This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
- // card styles. It is recommended that most users use `mdc-card-core-styles` instead.
- @mixin without-ripple($query: feature-targeting.all()) {
- // postcss-bem-linter: define card
- $feat-color: feature-targeting.create-target($query, color);
- $feat-structure: feature-targeting.create-target($query, structure);
- // prettier-ignore
- @include elevation-mixins.overlay-common($query); // COPYBARA_COMMENT_THIS_LINE
- .mdc-card {
- @include shape-radius(variables.$shape-radius, $query: $query);
- @include fill-color(surface, $query);
- @include elevation-mixins.overlay-surface-position($query: $query);
- @include elevation-mixins.overlay-dimensions(100%, $query: $query);
- @include elevation-mixins.elevation(1, $query: $query);
- // Transparent card border for high-contrast mode.
- &::after {
- @include shape-radius(variables.$shape-radius, $query: $query);
- }
- }
- .mdc-card--outlined {
- @include elevation-mixins.elevation(0, $query: $query);
- @include outline(variables.$outline-color, $query: $query);
- }
- @include static-styles($query: $query);
- // postcss-bem-linter: end
- }
- // This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
- // card styles. It is recommended that most users use `mdc-card-core-styles` instead.
- @mixin ripple($query: feature-targeting.all()) {
- @include ripple.common($query); // COPYBARA_COMMENT_THIS_LINE
- $feat-structure: feature-targeting.create-target($query, structure);
- .mdc-card__primary-action {
- @include ripple.surface($query, $ripple-target: $ripple-target);
- @include ripple.radius-bounded(
- $query: $query,
- $ripple-target: $ripple-target
- );
- @include ripple-theme.states(
- $query: $query,
- $ripple-target: $ripple-target
- );
- #{$ripple-target} {
- @include feature-targeting.targets($feat-structure) {
- box-sizing: content-box;
- height: 100%;
- overflow: hidden;
- left: 0;
- pointer-events: none;
- position: absolute;
- top: 0;
- width: 100%;
- }
- }
- @include ripple-theme.focus {
- &::after {
- @include dom-mixins.transparent-border(
- $border-width: 5px,
- $border-style: double,
- $query: $query
- );
- }
- }
- }
- }
- @mixin fill-color($color, $query: feature-targeting.all()) {
- $feat-color: feature-targeting.create-target($query, color);
- @include feature-targeting.targets($feat-color) {
- @include theme.property(background-color, $color);
- }
- }
- @mixin outline(
- $color,
- $thickness: variables.$outline-width,
- $query: feature-targeting.all()
- ) {
- $feat-color: feature-targeting.create-target($query, color);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include feature-targeting.targets($feat-structure) {
- @include theme.property(border-width, $thickness);
- border-style: solid;
- }
- @include feature-targeting.targets($feat-color) {
- @include theme.property(border-color, $color);
- }
- }
- @mixin shape-radius(
- $radius,
- $rtl-reflexive: false,
- $query: feature-targeting.all()
- ) {
- @include shape-mixins.radius($radius, $rtl-reflexive, $query: $query);
- }
- @mixin media-aspect-ratio($x, $y, $query: feature-targeting.all()) {
- $feat-structure: feature-targeting.create-target($query, structure);
- &::before {
- @include feature-targeting.targets($feat-structure) {
- // This clever trick brought to you by: http://www.mademyday.de/css-height-equals-width-with-pure-css.html
- margin-top: math.percentage(math.div($y, $x));
- }
- }
- }
- //
- // Private
- //
- @mixin container-layout_ {
- display: flex;
- flex-direction: column;
- box-sizing: border-box;
- }
- @mixin actions-layout_($display: flex) {
- display: $display;
- flex-direction: row;
- align-items: center;
- box-sizing: border-box;
- }
|