Skip to content

Commit fa02947

Browse files
asynclizcopybara-github
authored andcommitted
chore(labs): fix ripple keypress minimum activation
PiperOrigin-RevId: 900897661
1 parent 3400f36 commit fa02947

1 file changed

Lines changed: 42 additions & 24 deletions

File tree

labs/gb/components/ripple/ripple.ts

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,39 +87,45 @@ export function setupRipple(
8787
}
8888

8989
let minimumPressTimeoutId: number | undefined;
90+
const activateRipple = () => {
91+
// If the ripple is already active, restart the current press animation.
92+
if (ripple.classList.contains(RIPPLE_CLASSES.active)) {
93+
const pressAnimation = ripple
94+
.getAnimations()
95+
.find(
96+
(animation) =>
97+
(animation as Partial<CSSAnimation>).animationName ===
98+
'ripple-press',
99+
);
100+
pressAnimation?.cancel();
101+
pressAnimation?.play();
102+
}
103+
104+
// Emulate the `:active` class for a minimum press duration to show the
105+
// ripple effect on short clicks.
106+
ripple.classList.add(RIPPLE_CLASSES.active);
107+
clearTimeout(minimumPressTimeoutId);
108+
minimumPressTimeoutId = setTimeout(() => {
109+
ripple.classList.remove(RIPPLE_CLASSES.active);
110+
}, MINIMUM_PRESS_MS);
111+
};
112+
113+
// Return true if the ripple is disabled, or if the ripple class has been
114+
// removed. This allows components to disable and re-enable ripple behavior.
115+
const isRippleDisabled = () =>
116+
isDisabled(ripple) || !ripple.matches(`.${RIPPLE_CLASSES.ripple}`);
117+
90118
ripple.addEventListener(
91119
'pointerdown',
92120
(event: PointerEvent): void => {
93-
if (isDisabled(ripple)) return;
94-
121+
if (isRippleDisabled()) return;
95122
// Set ripple position to the pointer position.
96123
const rect = ripple.getBoundingClientRect();
97124
const x = (event.clientX - rect.x) / rect.width;
98125
const y = (event.clientY - rect.y) / rect.height;
99126
ripple.style.setProperty('--ripple-x', `${x * 100}%`);
100127
ripple.style.setProperty('--ripple-y', `${y * 100}%`);
101-
102-
// If another pointerdown is received while the ripple is active, restart
103-
// the active press animation.
104-
if (ripple.classList.contains(RIPPLE_CLASSES.active)) {
105-
const pressAnimation = ripple
106-
.getAnimations()
107-
.find(
108-
(animation) =>
109-
(animation as Partial<CSSAnimation>).animationName ===
110-
'ripple-press',
111-
);
112-
pressAnimation?.cancel();
113-
pressAnimation?.play();
114-
}
115-
116-
// Emulate the `:active` class for a minimum press duration to show the
117-
// ripple effect on short clicks.
118-
ripple.classList.add(RIPPLE_CLASSES.active);
119-
clearTimeout(minimumPressTimeoutId);
120-
minimumPressTimeoutId = setTimeout(() => {
121-
ripple.classList.remove(RIPPLE_CLASSES.active);
122-
}, MINIMUM_PRESS_MS);
128+
activateRipple();
123129
},
124130
opts,
125131
);
@@ -133,6 +139,18 @@ export function setupRipple(
133139
},
134140
opts,
135141
);
142+
143+
ripple.addEventListener(
144+
'click',
145+
(event) => {
146+
// A UIEvent.detail click count of 0 indicates the click was not triggered
147+
// by a pointer. Show the ripple press effect for these clicks as well.
148+
if (event.detail === 0 && !isRippleDisabled()) {
149+
activateRipple();
150+
}
151+
},
152+
opts,
153+
);
136154
}
137155

138156
/**

0 commit comments

Comments
 (0)