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

Commit a983c01

Browse files
authored
feat(ripple): Add new simpler mixins and remove unused CSS vars (#1452)
1 parent b4c4d7b commit a983c01

8 files changed

+225
-146
lines changed

packages/mdc-ripple/README.md

+54-77
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,31 @@ path: /catalog/ripples/
99

1010
# Ripples
1111

12-
- [MDC Ripple](#mdc-ripple)
13-
- [An aside regarding browser support](#an-aside-regarding-browser-support)
14-
- [Installation](#installation)
15-
- [Usage](#usage)
16-
- [Adding the ripple Sass](#adding-the-ripple-sass)
17-
- [The full Sass API](#the-full-sass-api)
18-
- [Adding the ripple JS](#adding-the-ripple-js)
19-
- [ES2015](#es2015)
20-
- [CommonJS](#commonjs)
21-
- [AMD](#amd)
22-
- [Global](#global)
23-
- [Unbounded Ripples](#unbounded-ripples)
24-
- [Using JS](#using-js)
25-
- [Using DOM (Component Only)](#using-dom-component-only)
26-
- [The mdc-ripple-surface class](#the-mdc-ripple-surface-class)
27-
- [Using the foundation](#using-the-foundation)
28-
- [Using the vanilla DOM adapter](#using-the-vanilla-DOM-adapter)
29-
- [Tips/Tricks](#tipstricks)
30-
- [Integrating ripples into MDC-Web components](#integrating-ripples-into-mdc-web-components)
31-
- [Using a sentinel element for a ripple](#using-a-sentinel-element-for-a-ripple)
32-
- [Keyboard interaction for custom UI components](#keyboard-interaction-for-custom-ui-components)
33-
- [Specifying known element dimensions](#specifying-known-element-dimensions)
34-
- [Caveat: Edge](#caveat-edge)
35-
- [Caveat: Safari](#caveat-safari)
36-
- [Caveat: Theme Custom Variables](#caveat-theme-custom-variables)
37-
- [The util API](#the-util-api)
38-
39-
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.
40-
41-
MDC Ripple also works without javascript, where it gracefully degrades to a simpler CSS-Only implementation.
12+
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.
13+
14+
MDC Ripple also works without JavaScript, where it gracefully degrades to a simpler CSS-Only implementation.
15+
16+
## Table of Contents
17+
18+
- [An aside regarding browser support](#an-aside-regarding-browser-support)
19+
- [Installation](#installation)
20+
- [Usage](#usage)
21+
- [Adding Ripple styles](#adding-ripple-styles)
22+
- [Adding Ripple JS](#adding-ripple-js)
23+
- [Ripple JS API](#ripple-js-api)
24+
- [Unbounded Ripples](#unbounded-ripples)
25+
- [The mdc-ripple-surface class](#the-mdc-ripple-surface-class)
26+
- [Using the foundation](#using-the-foundation)
27+
- [Using the vanilla DOM adapter](#using-the-vanilla-dom-adapter)
28+
- [Tips/Tricks](#tipstricks)
29+
- [Integrating ripples into MDC-Web components](#integrating-ripples-into-mdc-web-components)
30+
- [Using a sentinel element for a ripple](#using-a-sentinel-element-for-a-ripple)
31+
- [Keyboard interaction for custom UI components](#keyboard-interaction-for-custom-ui-components)
32+
- [Specifying known element dimensions](#specifying-known-element-dimensions)
33+
- [Caveat: Edge](#caveat-edge)
34+
- [Caveat: Safari](#caveat-safari)
35+
- [Caveat: Theme Custom Variables](#caveat-theme-custom-variables)
36+
- [The util API](#the-util-api)
4237

4338
### An aside regarding browser support
4439

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

5752
## Usage
5853

59-
For many components, providing a ripple interaction is straightforward.
54+
### Adding Ripple styles
6055

61-
Let's say we have a `surface` element that represents a basic surface.
56+
General notes:
6257

63-
```html
64-
<div class="surface" tabindex="0">
65-
<p>A surface</p>
66-
</div>
67-
```
58+
* 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.
59+
* Surfaces for bounded ripples should have `overflow` set to `hidden`, while surfaces for unbounded ripples should have it set to `visible`
60+
* 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`.
6861

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

72-
```scss
73-
@import "@material/elevation/mixins";
64+
These APIs implicitly use pseudo-elements for the ripple effect: `::before` for the background, and `::after` for the foreground.
65+
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.
7466

75-
.surface {
76-
@include mdc-elevation(2);
77-
78-
position: relative;
79-
border-radius: 2px;
80-
text-align: center;
81-
/* Indicate to user element is interactive. */
82-
cursor: pointer;
83-
```
67+
Mixin | Description
68+
--- | ---
69+
`mdc-ripple-surface` | Adds base styles for a ripple surface
70+
`mdc-ripple-color($color, $opacity)` | Adds styles for the color and opacity of the ripple effect
71+
`mdc-ripple-radius($radius)` | Adds styles for the radius of the ripple effect,<br>for both bounded and unbounded ripples
8472

85-
#### Adding the ripple Sass
73+
#### Legacy Sass API
8674

87-
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.
88-
89-
```scss
90-
@import "@material/elevation/mixins";
91-
@import "@material/ripple/mixins";
92-
93-
.surface {
94-
@include mdc-ripple-base;
95-
@include mdc-ripple-bg((pseudo: "::before"));
96-
@include mdc-ripple-fg((pseudo: "::after"));
97-
// ...
98-
99-
/* "Bound" the ripple, preventing the pseudo-elements from bleeding out of the box. */
100-
overflow: hidden;
101-
}
102-
```
75+
> 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.
10376
104-
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.
77+
All three of the following mixins are mandatory in order to fully style the ripple effect.
10578

106-
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`.
79+
Mixin | Description
80+
--- | ---
81+
`mdc-ripple-base` | Adds base styles for a ripple surface
82+
`mdc-ripple-bg($config)` | Adds styles for the ripple's background (i.e. fade effects)
83+
`mdc-ripple-fg($config)` | Adds styles for the ripple's foreground (i.e. the ink wash)
10784

108-
##### The full Sass API
85+
##### Ripple Configuration Map
10986

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

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

121-
#### Adding the ripple JS
98+
### Adding Ripple JS
12299

123-
First import the ripple JS
100+
First import the ripple JS.
124101

125-
##### ES2015
102+
#### ES2015
126103

127104
```javascript
128105
import {MDCRipple, MDCRippleFoundation, util} from '@material/ripple';
@@ -134,7 +111,7 @@ import {MDCRipple, MDCRippleFoundation, util} from '@material/ripple';
134111
const {MDCRipple, MDCRippleFoundation, util} = require('@material/ripple');
135112
```
136113

137-
##### AMD
114+
#### AMD
138115

139116
```javascript
140117
require('path/to/@material/ripple', function(mdcRipple) {
@@ -144,7 +121,7 @@ require('path/to/@material/ripple', function(mdcRipple) {
144121
});
145122
```
146123

147-
##### Global
124+
#### Global
148125

149126
```javascript
150127
const MDCRipple = mdc.ripple.MDCRipple;
@@ -166,7 +143,7 @@ ripple.
166143
MDCRipple.attachTo(document.querySelector('.surface'));
167144
```
168145

169-
### Ripple API
146+
### Ripple JS API
170147

171148
The component allows for programmatic activation / deactivation of the ripple, for interdependent interaction between
172149
components. This is used for making form field labels trigger the ripples in their corresponding input elements, for

packages/mdc-ripple/_mixins.scss

+143-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
@import "@material/theme/variables";
1919
@import "./keyframes";
2020

21+
//
22+
// Legacy mixin APIs, to be removed after converting all components to use new APIs
23+
//
24+
2125
@function mdc-ripple-default-config_() {
2226
@return (
2327
pseudo: null,
@@ -29,8 +33,6 @@
2933
}
3034

3135
@mixin mdc-ripple-base() {
32-
--mdc-ripple-surface-width: 0;
33-
--mdc-ripple-surface-height: 0;
3436
--mdc-ripple-fg-size: 0;
3537
--mdc-ripple-left: 0;
3638
--mdc-ripple-top: 0;
@@ -51,7 +53,7 @@
5153
}
5254
}
5355

54-
@mixin mdc-ripple-color_($config) {
56+
@mixin mdc-ripple-color-legacy_($config) {
5557
$base-color: map-get($config, base-color);
5658
$opacity: map-get($config, opacity);
5759
$theme-style: map-get($config, theme-style);
@@ -82,7 +84,7 @@
8284
@mixin mdc-ripple-bg-base_($config) {
8385
$radius: map-get($config, radius);
8486

85-
@include mdc-ripple-color_($config);
87+
@include mdc-ripple-color-legacy_($config);
8688

8789
position: absolute;
8890
top: calc(50% - #{$radius});
@@ -158,7 +160,7 @@
158160
@mixin mdc-ripple-fg-base_($config) {
159161
$radius: map-get($config, radius);
160162

161-
@include mdc-ripple-color_($config);
163+
@include mdc-ripple-color-legacy_($config);
162164

163165
position: absolute;
164166
top: calc(50% - #{$radius});
@@ -241,6 +243,142 @@
241243
}
242244
}
243245

246+
//
247+
// New mixin APIs
248+
//
249+
250+
@mixin mdc-ripple-surface() {
251+
--mdc-ripple-fg-size: 0;
252+
--mdc-ripple-left: 0;
253+
--mdc-ripple-top: 0;
254+
--mdc-ripple-fg-scale: 1;
255+
--mdc-ripple-fg-translate-end: 0;
256+
--mdc-ripple-fg-translate-start: 0;
257+
258+
will-change: transform, opacity;
259+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
260+
261+
&::before,
262+
&::after {
263+
position: absolute;
264+
transition: opacity 250ms linear;
265+
border-radius: 50%;
266+
pointer-events: none;
267+
content: "";
268+
}
269+
}
270+
271+
@mixin mdc-ripple-color_($color, $opacity) {
272+
// stylelint-disable at-rule-empty-line-before, block-closing-brace-newline-after
273+
@if type-of($color) == "color" {
274+
background-color: rgba($color, $opacity);
275+
} @else {
276+
// Assume $color is a theme property name
277+
$theme-value: map-get($mdc-theme-property-values, $color);
278+
$css-var: var(--mdc-theme-#{$color}, $theme-value);
279+
280+
background-color: rgba($theme-value, $opacity);
281+
282+
// See: https://drafts.csswg.org/css-color/#modifying-colors
283+
// While this is currently unsupported as of now, it will begin to work by default as browsers
284+
// begin to implement the CSS 4 color spec.
285+
@supports (background-color: color(green a(10%))) {
286+
background-color: color(#{$css-var} a(#{percentage($opacity)}));
287+
}
288+
}
289+
// stylelint-enable at-rule-empty-line-before, block-closing-brace-newline-after
290+
}
291+
292+
@mixin mdc-ripple-color($color: black, $opacity: .06) {
293+
// Opacity styles are here (rather than in mdc-ripple-surface) to ensure that opacity is re-initialized for
294+
// cases where this mixin is used to override another inherited use of itself,
295+
// without needing to re-include mdc-ripple-surface.
296+
&::before,
297+
&::after {
298+
@include mdc-ripple-color_($color, $opacity);
299+
300+
opacity: 0;
301+
}
302+
303+
// Note: when :active is applied, :focus is already applied, which will effectively double the effect.
304+
&:not(.mdc-ripple-upgraded) {
305+
&:hover::before,
306+
&:focus::before,
307+
&:active::after {
308+
transition-duration: 85ms;
309+
opacity: .6;
310+
}
311+
}
312+
313+
&.mdc-ripple-upgraded--background-focused::before {
314+
opacity: .99999;
315+
}
316+
317+
&.mdc-ripple-upgraded--background-active-fill::before {
318+
transition-duration: 120ms;
319+
opacity: 1;
320+
}
321+
322+
// Foreground ripple styles
323+
324+
&.mdc-ripple-upgraded::after {
325+
opacity: 0;
326+
}
327+
328+
&.mdc-ripple-upgraded--foreground-activation::after {
329+
animation: 300ms mdc-ripple-fg-radius-in forwards, 83ms mdc-ripple-fg-opacity-in forwards;
330+
}
331+
332+
&.mdc-ripple-upgraded--foreground-deactivation::after {
333+
animation: 83ms mdc-ripple-fg-opacity-out;
334+
// Retain transform from mdc-ripple-fg-radius-in activation
335+
transform: translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1));
336+
}
337+
}
338+
339+
@mixin mdc-ripple-radius($radius: 100%) {
340+
&::before,
341+
&::after {
342+
top: calc(50% - #{$radius});
343+
left: calc(50% - #{$radius});
344+
width: $radius * 2;
345+
height: $radius * 2;
346+
}
347+
348+
// Background ripple styles
349+
350+
&.mdc-ripple-upgraded::before {
351+
top: calc(50% - #{$radius});
352+
left: calc(50% - #{$radius});
353+
width: $radius * 2;
354+
height: $radius * 2;
355+
transform: scale(var(--mdc-ripple-fg-scale, 0));
356+
}
357+
358+
&.mdc-ripple-upgraded--unbounded::before {
359+
top: var(--mdc-ripple-top, calc(50% - #{$radius / 2}));
360+
left: var(--mdc-ripple-left, calc(50% - #{$radius / 2}));
361+
width: var(--mdc-ripple-fg-size, $radius);
362+
height: var(--mdc-ripple-fg-size, $radius);
363+
transform: scale(var(--mdc-ripple-fg-scale, 0));
364+
}
365+
366+
// Foreground ripple styles
367+
&.mdc-ripple-upgraded::after {
368+
top: 0;
369+
left: 0;
370+
width: var(--mdc-ripple-fg-size, $radius);
371+
height: var(--mdc-ripple-fg-size, $radius);
372+
transform: scale(0);
373+
transform-origin: center center;
374+
}
375+
376+
&.mdc-ripple-upgraded--unbounded::after {
377+
top: var(--mdc-ripple-top, 0);
378+
left: var(--mdc-ripple-left, 0);
379+
}
380+
}
381+
244382
// Styles used to detect buggy behavior of CSS custom properties in Edge.
245383
// See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11495448/
246384
// This is included in _mixins.scss rather than mdc-ripple.scss so that it will be

packages/mdc-ripple/_variables.scss

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// Copyright 2016 Google Inc. All Rights Reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
$mdc-ripple-pressed-dark-ink-opacity: .16;
18+
$mdc-ripple-pressed-light-ink-opacity: .32;

0 commit comments

Comments
 (0)