mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00
fix(ripple): using ripple effect in all button components
This commit is contained in:
61
packages/core/src/components.d.ts
vendored
61
packages/core/src/components.d.ts
vendored
@ -330,36 +330,6 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
import {
|
|
||||||
ButtonEffect as IonButtonEffect
|
|
||||||
} from './components/button-effect/button-effect';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLIonButtonEffectElement extends IonButtonEffect, HTMLElement {
|
|
||||||
}
|
|
||||||
var HTMLIonButtonEffectElement: {
|
|
||||||
prototype: HTMLIonButtonEffectElement;
|
|
||||||
new (): HTMLIonButtonEffectElement;
|
|
||||||
};
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ion-button-effect": HTMLIonButtonEffectElement;
|
|
||||||
}
|
|
||||||
interface ElementTagNameMap {
|
|
||||||
"ion-button-effect": HTMLIonButtonEffectElement;
|
|
||||||
}
|
|
||||||
namespace JSX {
|
|
||||||
interface IntrinsicElements {
|
|
||||||
"ion-button-effect": JSXElements.IonButtonEffectAttributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
namespace JSXElements {
|
|
||||||
export interface IonButtonEffectAttributes extends HTMLAttributes {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button as IonButton
|
Button as IonButton
|
||||||
} from './components/button/button';
|
} from './components/button/button';
|
||||||
@ -2301,6 +2271,36 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
import {
|
||||||
|
RippleEffect as IonRippleEffect
|
||||||
|
} from './components/ripple-effect/ripple-effect';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLIonRippleEffectElement extends IonRippleEffect, HTMLElement {
|
||||||
|
}
|
||||||
|
var HTMLIonRippleEffectElement: {
|
||||||
|
prototype: HTMLIonRippleEffectElement;
|
||||||
|
new (): HTMLIonRippleEffectElement;
|
||||||
|
};
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ion-ripple-effect": HTMLIonRippleEffectElement;
|
||||||
|
}
|
||||||
|
interface ElementTagNameMap {
|
||||||
|
"ion-ripple-effect": HTMLIonRippleEffectElement;
|
||||||
|
}
|
||||||
|
namespace JSX {
|
||||||
|
interface IntrinsicElements {
|
||||||
|
"ion-ripple-effect": JSXElements.IonRippleEffectAttributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace JSXElements {
|
||||||
|
export interface IonRippleEffectAttributes extends HTMLAttributes {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RouteLink as IonRouteLink
|
RouteLink as IonRouteLink
|
||||||
} from './components/route-link/route-link';
|
} from './components/route-link/route-link';
|
||||||
@ -2851,6 +2851,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
namespace JSXElements {
|
namespace JSXElements {
|
||||||
export interface IonTabButtonAttributes extends HTMLAttributes {
|
export interface IonTabButtonAttributes extends HTMLAttributes {
|
||||||
|
mode?: 'ios' | 'md';
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
tab?: HTMLIonTabElement;
|
tab?: HTMLIonTabElement;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
background-color: $button-md-background-color-focused;
|
background-color: $button-md-background-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-md .button-effect {
|
.button-md .ripple-effect {
|
||||||
background-color: $button-md-text-color;
|
background-color: $button-md-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@
|
|||||||
background-color: $bg-color-focused;
|
background-color: $bg-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-md-#{$color-name} .button-effect {
|
.button-md-#{$color-name} .ripple-effect {
|
||||||
background-color: $fg-color;
|
background-color: $fg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@
|
|||||||
background-color: $button-md-outline-background-color-focused;
|
background-color: $button-md-outline-background-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-outline-md .button-effect {
|
.button-outline-md .ripple-effect {
|
||||||
background-color: $button-md-outline-ripple-background-color;
|
background-color: $button-md-outline-ripple-background-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@
|
|||||||
background-color: $bg-color-focused;
|
background-color: $bg-color-focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-outline-md-#{$color-name} .button-effect {
|
.button-outline-md-#{$color-name} .ripple-effect {
|
||||||
background-color: $fg-color;
|
background-color: $fg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@
|
|||||||
background-color: $button-md-clear-background-color-hover;
|
background-color: $button-md-clear-background-color-hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-clear-md .button-effect {
|
.button-clear-md .ripple-effect {
|
||||||
background-color: $button-md-clear-ripple-background-color;
|
background-color: $button-md-clear-ripple-background-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ export class Button {
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
<slot name='end'></slot>
|
<slot name='end'></slot>
|
||||||
</span>
|
</span>
|
||||||
<ion-button-effect />
|
{ this.mode === 'md' && <ion-ripple-effect /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ export class ChipButton {
|
|||||||
<span class='button-inner'>
|
<span class='button-inner'>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</span>
|
</span>
|
||||||
<div class='button-effect'></div>
|
{ this.mode === 'md' && <ion-ripple-effect /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
// Material Design FAB Ripple
|
// Material Design FAB Ripple
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
.fab-button-md .button-effect {
|
.fab-button-md .ripple-effect {
|
||||||
background-color: color-contrast($colors-md, $fab-md-background-color);
|
background-color: color-contrast($colors-md, $fab-md-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@
|
|||||||
background-color: $bg-color-activated;
|
background-color: $bg-color-activated;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fab-button-md-#{$color-name} .button-effect {
|
.fab-button-md-#{$color-name} .ripple-effect {
|
||||||
background-color: $fg-color;
|
background-color: $fg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ export class FabButton {
|
|||||||
<span class='button-inner'>
|
<span class='button-inner'>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</span>
|
</span>
|
||||||
<div class='button-effect'></div>
|
{ this.mode === 'md' && <ion-ripple-effect /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ export class Item {
|
|||||||
</div>
|
</div>
|
||||||
<slot name='end'></slot>
|
<slot name='end'></slot>
|
||||||
</div>
|
</div>
|
||||||
<div class='button-effect'></div>
|
{ this.href && this.mode === 'md' && <ion-ripple-effect /> }
|
||||||
</TagType>
|
</TagType>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,7 @@
|
|||||||
// Only Material uses the button effect, so by default
|
// Only Material uses the button effect, so by default
|
||||||
// it's display none, and .md sets to display block.
|
// it's display none, and .md sets to display block.
|
||||||
|
|
||||||
/// @prop - Background color of the ripple on the button
|
ion-ripple-effect {
|
||||||
$button-effect-ripple-background-color: #000 !default;
|
|
||||||
|
|
||||||
ion-button-effect {
|
|
||||||
@include position(0, 0, 0, 0);
|
@include position(0, 0, 0, 0);
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -16,11 +13,11 @@ ion-button-effect {
|
|||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-effect {
|
.ripple-effect {
|
||||||
@include border-radius(50%);
|
@include border-radius(50%);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
background: $button-effect-ripple-background-color;
|
background: #000;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
will-change: transform, opacity;
|
will-change: transform, opacity;
|
@ -1,18 +1,16 @@
|
|||||||
import { Component, Element, Listen, Prop, State } from '@stencil/core';
|
import { Component, Element, Listen, Prop } from '@stencil/core';
|
||||||
import { now } from '../../utils/helpers';
|
import { now } from '../../utils/helpers';
|
||||||
import { DomController } from '../../global/dom-controller';
|
import { DomController } from '../../global/dom-controller';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
tag: 'ion-button-effect',
|
tag: 'ion-ripple-effect',
|
||||||
styleUrl: 'button-effect.scss'
|
styleUrl: 'ripple-effect.scss'
|
||||||
})
|
})
|
||||||
export class ButtonEffect {
|
export class RippleEffect {
|
||||||
|
|
||||||
private lastClick = -10000;
|
private lastClick = -10000;
|
||||||
@Element() el: HTMLElement;
|
@Element() el: HTMLElement;
|
||||||
|
|
||||||
@State() state = 0;
|
|
||||||
|
|
||||||
@Prop({context: 'dom'}) dom: DomController;
|
@Prop({context: 'dom'}) dom: DomController;
|
||||||
|
|
||||||
@Listen('touchstart')
|
@Listen('touchstart')
|
||||||
@ -37,13 +35,13 @@ export class ButtonEffect {
|
|||||||
const rect = this.el.getBoundingClientRect();
|
const rect = this.el.getBoundingClientRect();
|
||||||
const width = rect.width;
|
const width = rect.width;
|
||||||
const height = rect.height;
|
const height = rect.height;
|
||||||
size = Math.sqrt(width * width + height * height) * 2;
|
size = Math.min(Math.sqrt(width * width + height * height) * 2, 600);
|
||||||
x = pageX - rect.left - (size / 2);
|
x = pageX - rect.left - (size / 2);
|
||||||
y = pageY - rect.top - (size / 2);
|
y = pageY - rect.top - (size / 2);
|
||||||
});
|
});
|
||||||
this.dom.write(() => {
|
this.dom.write(() => {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.classList.add('button-effect');
|
div.classList.add('ripple-effect');
|
||||||
const style = div.style;
|
const style = div.style;
|
||||||
const duration = Math.max(800 * Math.sqrt(size / 350) + 0.5, 260);
|
const duration = Math.max(800 * Math.sqrt(size / 350) + 0.5, 260);
|
||||||
style.top = y + 'px';
|
style.top = y + 'px';
|
@ -40,19 +40,19 @@
|
|||||||
<ion-button size="large" fill="clear">Large</ion-button>
|
<ion-button size="large" fill="clear">Large</ion-button>
|
||||||
</p>
|
</p>
|
||||||
<div class="my-block">
|
<div class="my-block">
|
||||||
<ion-button-effect></ion-button-effect>
|
<ion-ripple-effect></ion-ripple-effect>
|
||||||
This is just a div + effect behind
|
This is just a div + effect behind
|
||||||
<ion-button onclick="buttonClicked()">Nested button</ion-button>
|
<ion-button onclick="buttonClicked()">Nested button</ion-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-block">
|
<div class="my-block">
|
||||||
This is just a div + effect on top
|
This is just a div + effect on top
|
||||||
<ion-button onclick="buttonClicked()">Nested button</ion-button>
|
<ion-button onclick="buttonClicked()">Nested button</ion-button>
|
||||||
<ion-button-effect></ion-button-effect>
|
<ion-ripple-effect></ion-ripple-effect>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="my-block">
|
<div class="my-block">
|
||||||
This is just a div + effect
|
This is just a div + effect
|
||||||
<ion-button-effect></ion-button-effect>
|
<ion-ripple-effect></ion-ripple-effect>
|
||||||
</div>
|
</div>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</ion-page>
|
</ion-page>
|
@ -7,6 +7,11 @@
|
|||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
|
#### mode
|
||||||
|
|
||||||
|
any
|
||||||
|
|
||||||
|
|
||||||
#### selected
|
#### selected
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
@ -19,6 +24,11 @@ any
|
|||||||
|
|
||||||
## Attributes
|
## Attributes
|
||||||
|
|
||||||
|
#### mode
|
||||||
|
|
||||||
|
any
|
||||||
|
|
||||||
|
|
||||||
#### selected
|
#### selected
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
|
@ -8,6 +8,13 @@ export class TabButton {
|
|||||||
|
|
||||||
@Element() el: HTMLElement;
|
@Element() el: HTMLElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {string} The mode determines which platform styles to use.
|
||||||
|
* Possible values are: `"ios"` or `"md"`.
|
||||||
|
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||||
|
*/
|
||||||
|
@Prop() mode: 'ios' | 'md';
|
||||||
|
|
||||||
@Prop() selected = false;
|
@Prop() selected = false;
|
||||||
@Prop() tab: HTMLIonTabElement;
|
@Prop() tab: HTMLIonTabElement;
|
||||||
|
|
||||||
@ -67,8 +74,9 @@ export class TabButton {
|
|||||||
if (tab.badge) {
|
if (tab.badge) {
|
||||||
items.push(<ion-badge class='tab-badge' color={tab.badgeStyle}>{tab.badge}</ion-badge>);
|
items.push(<ion-badge class='tab-badge' color={tab.badgeStyle}>{tab.badge}</ion-badge>);
|
||||||
}
|
}
|
||||||
items.push(<div class='button-effect'></div>);
|
if (this.mode === 'md') {
|
||||||
|
items.push(<ion-ripple-effect />);
|
||||||
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
.bar-button-clear-md,
|
.bar-button-clear-md,
|
||||||
.bar-button-default-md,
|
.bar-button-default-md,
|
||||||
.bar-button-outline-md {
|
.bar-button-outline-md {
|
||||||
.button-effect {
|
.ripple-effect {
|
||||||
background-color: $color-contrast;
|
background-color: $color-contrast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-effect {
|
.ripple-effect {
|
||||||
background-color: $toolbar-md-button-color;
|
background-color: $toolbar-md-button-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,7 +219,7 @@
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-effect {
|
.ripple-effect {
|
||||||
background-color: $fg-color;
|
background-color: $fg-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const _engine = (window as any).TapticEngine;
|
const engine = (window as any).TapticEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the Haptic Plugin is available
|
* Check to see if the Haptic Plugin is available
|
||||||
@ -6,7 +6,7 @@ const _engine = (window as any).TapticEngine;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export function hapticAvailable() {
|
export function hapticAvailable() {
|
||||||
return !!_engine;
|
return !!engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,21 +14,21 @@ export function hapticAvailable() {
|
|||||||
* (not for gestures)
|
* (not for gestures)
|
||||||
*/
|
*/
|
||||||
export function hapticSelection() {
|
export function hapticSelection() {
|
||||||
_engine && _engine.selection();
|
engine && engine.selection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the haptic engine that a gesture for a selection change is starting.
|
* Tell the haptic engine that a gesture for a selection change is starting.
|
||||||
*/
|
*/
|
||||||
export function hapticSelectionStart() {
|
export function hapticSelectionStart() {
|
||||||
_engine && _engine.gestureSelectionStart();
|
engine && engine.gestureSelectionStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the haptic engine that a selection changed during a gesture.
|
* Tell the haptic engine that a selection changed during a gesture.
|
||||||
*/
|
*/
|
||||||
export function hapticSelectionChanged() {
|
export function hapticSelectionChanged() {
|
||||||
_engine && _engine.gestureSelectionChanged();
|
engine && engine.gestureSelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,7 +36,7 @@ export function hapticSelectionChanged() {
|
|||||||
* called lest resources are not properly recycled.
|
* called lest resources are not properly recycled.
|
||||||
*/
|
*/
|
||||||
export function hapticSelectionEnd() {
|
export function hapticSelectionEnd() {
|
||||||
_engine && _engine.gestureSelectionEnd();
|
engine && engine.gestureSelectionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,7 +44,7 @@ export function hapticSelectionEnd() {
|
|||||||
* options should be of the type `{ type: 'success' }` (or `warning`/`error`)
|
* options should be of the type `{ type: 'success' }` (or `warning`/`error`)
|
||||||
*/
|
*/
|
||||||
export function hapticNotification(options: { type: string }) {
|
export function hapticNotification(options: { type: string }) {
|
||||||
_engine && _engine.notification(options);
|
engine && engine.notification(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,5 +52,5 @@ export function hapticNotification(options: { type: string }) {
|
|||||||
* options should be of the type `{ style: 'light' }` (or `medium`/`heavy`)
|
* options should be of the type `{ style: 'light' }` (or `medium`/`heavy`)
|
||||||
*/
|
*/
|
||||||
export function hapticImpact(options: { style: string }) {
|
export function hapticImpact(options: { style: string }) {
|
||||||
_engine && _engine.impact(options);
|
engine && engine.impact(options);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user