Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
feat(ripple): Add new simpler mixins and remove unused CSS vars (#1452)
Browse files Browse the repository at this point in the history
  • Loading branch information
kfranqueiro authored Oct 23, 2017
1 parent b4c4d7b commit a983c01
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 146 deletions.
131 changes: 54 additions & 77 deletions packages/mdc-ripple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,31 @@ path: /catalog/ripples/

# Ripples

- [MDC Ripple](#mdc-ripple)
- [An aside regarding browser support](#an-aside-regarding-browser-support)
- [Installation](#installation)
- [Usage](#usage)
- [Adding the ripple Sass](#adding-the-ripple-sass)
- [The full Sass API](#the-full-sass-api)
- [Adding the ripple JS](#adding-the-ripple-js)
- [ES2015](#es2015)
- [CommonJS](#commonjs)
- [AMD](#amd)
- [Global](#global)
- [Unbounded Ripples](#unbounded-ripples)
- [Using JS](#using-js)
- [Using DOM (Component Only)](#using-dom-component-only)
- [The mdc-ripple-surface class](#the-mdc-ripple-surface-class)
- [Using the foundation](#using-the-foundation)
- [Using the vanilla DOM adapter](#using-the-vanilla-DOM-adapter)
- [Tips/Tricks](#tipstricks)
- [Integrating ripples into MDC-Web components](#integrating-ripples-into-mdc-web-components)
- [Using a sentinel element for a ripple](#using-a-sentinel-element-for-a-ripple)
- [Keyboard interaction for custom UI components](#keyboard-interaction-for-custom-ui-components)
- [Specifying known element dimensions](#specifying-known-element-dimensions)
- [Caveat: Edge](#caveat-edge)
- [Caveat: Safari](#caveat-safari)
- [Caveat: Theme Custom Variables](#caveat-theme-custom-variables)
- [The util API](#the-util-api)

MDC Ripple provides the Javascript and CSS required to provide components (or any element at all) with a material "ink ripple" interaction effect. It is designed to be efficient, uninvasive, and usable without adding any extra DOM to your elements.

MDC Ripple also works without javascript, where it gracefully degrades to a simpler CSS-Only implementation.
MDC Ripple provides the JavaScript and CSS required to provide components (or any element at all) with a material "ink ripple" interaction effect. It is designed to be efficient, uninvasive, and usable without adding any extra DOM to your elements.

MDC Ripple also works without JavaScript, where it gracefully degrades to a simpler CSS-Only implementation.

## Table of Contents

- [An aside regarding browser support](#an-aside-regarding-browser-support)
- [Installation](#installation)
- [Usage](#usage)
- [Adding Ripple styles](#adding-ripple-styles)
- [Adding Ripple JS](#adding-ripple-js)
- [Ripple JS API](#ripple-js-api)
- [Unbounded Ripples](#unbounded-ripples)
- [The mdc-ripple-surface class](#the-mdc-ripple-surface-class)
- [Using the foundation](#using-the-foundation)
- [Using the vanilla DOM adapter](#using-the-vanilla-dom-adapter)
- [Tips/Tricks](#tipstricks)
- [Integrating ripples into MDC-Web components](#integrating-ripples-into-mdc-web-components)
- [Using a sentinel element for a ripple](#using-a-sentinel-element-for-a-ripple)
- [Keyboard interaction for custom UI components](#keyboard-interaction-for-custom-ui-components)
- [Specifying known element dimensions](#specifying-known-element-dimensions)
- [Caveat: Edge](#caveat-edge)
- [Caveat: Safari](#caveat-safari)
- [Caveat: Theme Custom Variables](#caveat-theme-custom-variables)
- [The util API](#the-util-api)

### An aside regarding browser support

Expand All @@ -56,58 +51,40 @@ npm install --save @material/ripple

## Usage

For many components, providing a ripple interaction is straightforward.
### Adding Ripple styles

Let's say we have a `surface` element that represents a basic surface.
General notes:

```html
<div class="surface" tabindex="0">
<p>A surface</p>
</div>
```
* Ripple mixins can be applied to a variety of elements representing interactive surfaces. These mixins are also used by other MDC Web components such as Button, FAB, Checkbox, Radio, etc.
* Surfaces for bounded ripples should have `overflow` set to `hidden`, while surfaces for unbounded ripples should have it set to `visible`
* When a ripple is successfully initialized on an element using JS, it dynamically adds a `mdc-ripple-upgraded` class to that element. If ripple JS is not initialized but Sass mixins are included on the surface, the ripple will still work, but it uses a simpler, CSS-only implementation which relies on `:hover`, `:focus`, and `:active`.

We also have some basic styles for our surface that
use [mdc-elevation](../mdc-elevation) to raise it up off of its background.
#### Sass API

```scss
@import "@material/elevation/mixins";
These APIs implicitly use pseudo-elements for the ripple effect: `::before` for the background, and `::after` for the foreground.
All three of the following mixins are mandatory in order to fully style the ripple effect; from that point, it is feasible to further override only the parts necessary (e.g. `mdc-ripple-color` specifically) for variants of a component.

.surface {
@include mdc-elevation(2);

position: relative;
border-radius: 2px;
text-align: center;
/* Indicate to user element is interactive. */
cursor: pointer;
```
Mixin | Description
--- | ---
`mdc-ripple-surface` | Adds base styles for a ripple surface
`mdc-ripple-color($color, $opacity)` | Adds styles for the color and opacity of the ripple effect
`mdc-ripple-radius($radius)` | Adds styles for the radius of the ripple effect,<br>for both bounded and unbounded ripples

#### Adding the ripple Sass
#### Legacy Sass API

To add a ripple to our surface, first we include the proper Sass mixins within our surface's styles. We also add a few additional properties that ensure the ripple's UX is correct.

```scss
@import "@material/elevation/mixins";
@import "@material/ripple/mixins";

.surface {
@include mdc-ripple-base;
@include mdc-ripple-bg((pseudo: "::before"));
@include mdc-ripple-fg((pseudo: "::after"));
// ...

/* "Bound" the ripple, preventing the pseudo-elements from bleeding out of the box. */
overflow: hidden;
}
```
> Note: This API is deprecated and will be removed soon. Please use the APIs above instead, which establish the same styles with a simpler API.
This code sets up `.surface` with the correct css variables as well as `will-change` properties to support the ripple. It then dynamically generates the correct selectors such that the surface's `::before` element functions as a background ripple, and the surface's `::after` element functions as a foreground ripple.
All three of the following mixins are mandatory in order to fully style the ripple effect.

When a ripple is successfully initialized on an element, it dynamically adds a `mdc-ripple-upgraded` class to that element. If ripple is not initialized but Sass mixins are included within our surface, the ripple will still work, but it would use a simpler, CSS-Only implementation which relies on `:hover`, `:active`, and `:focus`.
Mixin | Description
--- | ---
`mdc-ripple-base` | Adds base styles for a ripple surface
`mdc-ripple-bg($config)` | Adds styles for the ripple's background (i.e. fade effects)
`mdc-ripple-fg($config)` | Adds styles for the ripple's foreground (i.e. the ink wash)

##### The full Sass API
##### Ripple Configuration Map

Both `mdc-ripple-bg` and `mdc-ripple-fg` take an `$config` map as an optional
Both `mdc-ripple-bg` and `mdc-ripple-fg` take a `$config` map as an optional
argument, with which you can specify the following parameters:

| Parameter | Description | Default |
Expand All @@ -118,11 +95,11 @@ argument, with which you can specify the following parameters:
| `base-color` | The RGB color (_without_ an alpha component) of the ripple. This will only be used if `theme-style` isn't specified. | `black` |
| `opacity` | A unitless number from `0-1` specifying the opacity that either the `base-color` or the `theme-style` color will take on. | `.06` |

#### Adding the ripple JS
### Adding Ripple JS

First import the ripple JS
First import the ripple JS.

##### ES2015
#### ES2015

```javascript
import {MDCRipple, MDCRippleFoundation, util} from '@material/ripple';
Expand All @@ -134,7 +111,7 @@ import {MDCRipple, MDCRippleFoundation, util} from '@material/ripple';
const {MDCRipple, MDCRippleFoundation, util} = require('@material/ripple');
```

##### AMD
#### AMD

```javascript
require('path/to/@material/ripple', function(mdcRipple) {
Expand All @@ -144,7 +121,7 @@ require('path/to/@material/ripple', function(mdcRipple) {
});
```

##### Global
#### Global

```javascript
const MDCRipple = mdc.ripple.MDCRipple;
Expand All @@ -166,7 +143,7 @@ ripple.
MDCRipple.attachTo(document.querySelector('.surface'));
```

### Ripple API
### Ripple JS API

The component allows for programmatic activation / deactivation of the ripple, for interdependent interaction between
components. This is used for making form field labels trigger the ripples in their corresponding input elements, for
Expand Down
148 changes: 143 additions & 5 deletions packages/mdc-ripple/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
@import "@material/theme/variables";
@import "./keyframes";

//
// Legacy mixin APIs, to be removed after converting all components to use new APIs
//

@function mdc-ripple-default-config_() {
@return (
pseudo: null,
Expand All @@ -29,8 +33,6 @@
}

@mixin mdc-ripple-base() {
--mdc-ripple-surface-width: 0;
--mdc-ripple-surface-height: 0;
--mdc-ripple-fg-size: 0;
--mdc-ripple-left: 0;
--mdc-ripple-top: 0;
Expand All @@ -51,7 +53,7 @@
}
}

@mixin mdc-ripple-color_($config) {
@mixin mdc-ripple-color-legacy_($config) {
$base-color: map-get($config, base-color);
$opacity: map-get($config, opacity);
$theme-style: map-get($config, theme-style);
Expand Down Expand Up @@ -82,7 +84,7 @@
@mixin mdc-ripple-bg-base_($config) {
$radius: map-get($config, radius);

@include mdc-ripple-color_($config);
@include mdc-ripple-color-legacy_($config);

position: absolute;
top: calc(50% - #{$radius});
Expand Down Expand Up @@ -158,7 +160,7 @@
@mixin mdc-ripple-fg-base_($config) {
$radius: map-get($config, radius);

@include mdc-ripple-color_($config);
@include mdc-ripple-color-legacy_($config);

position: absolute;
top: calc(50% - #{$radius});
Expand Down Expand Up @@ -241,6 +243,142 @@
}
}

//
// New mixin APIs
//

@mixin mdc-ripple-surface() {
--mdc-ripple-fg-size: 0;
--mdc-ripple-left: 0;
--mdc-ripple-top: 0;
--mdc-ripple-fg-scale: 1;
--mdc-ripple-fg-translate-end: 0;
--mdc-ripple-fg-translate-start: 0;

will-change: transform, opacity;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);

&::before,
&::after {
position: absolute;
transition: opacity 250ms linear;
border-radius: 50%;
pointer-events: none;
content: "";
}
}

@mixin mdc-ripple-color_($color, $opacity) {
// stylelint-disable at-rule-empty-line-before, block-closing-brace-newline-after
@if type-of($color) == "color" {
background-color: rgba($color, $opacity);
} @else {
// Assume $color is a theme property name
$theme-value: map-get($mdc-theme-property-values, $color);
$css-var: var(--mdc-theme-#{$color}, $theme-value);

background-color: rgba($theme-value, $opacity);

// See: https://drafts.csswg.org/css-color/#modifying-colors
// While this is currently unsupported as of now, it will begin to work by default as browsers
// begin to implement the CSS 4 color spec.
@supports (background-color: color(green a(10%))) {
background-color: color(#{$css-var} a(#{percentage($opacity)}));
}
}
// stylelint-enable at-rule-empty-line-before, block-closing-brace-newline-after
}

@mixin mdc-ripple-color($color: black, $opacity: .06) {
// Opacity styles are here (rather than in mdc-ripple-surface) to ensure that opacity is re-initialized for
// cases where this mixin is used to override another inherited use of itself,
// without needing to re-include mdc-ripple-surface.
&::before,
&::after {
@include mdc-ripple-color_($color, $opacity);

opacity: 0;
}

// Note: when :active is applied, :focus is already applied, which will effectively double the effect.
&:not(.mdc-ripple-upgraded) {
&:hover::before,
&:focus::before,
&:active::after {
transition-duration: 85ms;
opacity: .6;
}
}

&.mdc-ripple-upgraded--background-focused::before {
opacity: .99999;
}

&.mdc-ripple-upgraded--background-active-fill::before {
transition-duration: 120ms;
opacity: 1;
}

// Foreground ripple styles

&.mdc-ripple-upgraded::after {
opacity: 0;
}

&.mdc-ripple-upgraded--foreground-activation::after {
animation: 300ms mdc-ripple-fg-radius-in forwards, 83ms mdc-ripple-fg-opacity-in forwards;
}

&.mdc-ripple-upgraded--foreground-deactivation::after {
animation: 83ms mdc-ripple-fg-opacity-out;
// Retain transform from mdc-ripple-fg-radius-in activation
transform: translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1));
}
}

@mixin mdc-ripple-radius($radius: 100%) {
&::before,
&::after {
top: calc(50% - #{$radius});
left: calc(50% - #{$radius});
width: $radius * 2;
height: $radius * 2;
}

// Background ripple styles

&.mdc-ripple-upgraded::before {
top: calc(50% - #{$radius});
left: calc(50% - #{$radius});
width: $radius * 2;
height: $radius * 2;
transform: scale(var(--mdc-ripple-fg-scale, 0));
}

&.mdc-ripple-upgraded--unbounded::before {
top: var(--mdc-ripple-top, calc(50% - #{$radius / 2}));
left: var(--mdc-ripple-left, calc(50% - #{$radius / 2}));
width: var(--mdc-ripple-fg-size, $radius);
height: var(--mdc-ripple-fg-size, $radius);
transform: scale(var(--mdc-ripple-fg-scale, 0));
}

// Foreground ripple styles
&.mdc-ripple-upgraded::after {
top: 0;
left: 0;
width: var(--mdc-ripple-fg-size, $radius);
height: var(--mdc-ripple-fg-size, $radius);
transform: scale(0);
transform-origin: center center;
}

&.mdc-ripple-upgraded--unbounded::after {
top: var(--mdc-ripple-top, 0);
left: var(--mdc-ripple-left, 0);
}
}

// Styles used to detect buggy behavior of CSS custom properties in Edge.
// See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11495448/
// This is included in _mixins.scss rather than mdc-ripple.scss so that it will be
Expand Down
18 changes: 18 additions & 0 deletions packages/mdc-ripple/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

$mdc-ripple-pressed-dark-ink-opacity: .16;
$mdc-ripple-pressed-light-ink-opacity: .32;
Loading

0 comments on commit a983c01

Please sign in to comment.