diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts
index 5bd6436a6b4..82a097d7ccc 100644
--- a/angular/src/directives/proxies.ts
+++ b/angular/src/directives/proxies.ts
@@ -652,13 +652,14 @@ export class ReorderGroup {
}
export declare interface RippleEffect extends StencilComponents<'IonRippleEffect'> {}
-@Component({ selector: 'ion-ripple-effect', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '' })
+@Component({ selector: 'ion-ripple-effect', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: '', inputs: ['type'] })
export class RippleEffect {
constructor(c: ChangeDetectorRef, r: ElementRef) {
c.detach();
const el = r.nativeElement;
proxyMethods(this, el, ['addRipple']);
+ proxyInputs(this, el, ['type']);
}
}
diff --git a/core/api.txt b/core/api.txt
index 0e483beb3b9..81f5454fc24 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -740,6 +740,7 @@ ion-reorder-group,method,complete,complete(listOrReorder?: boolean | any[] | und
ion-reorder-group,event,ionItemReorder,ItemReorderDetail,true
+ion-ripple-effect,prop,type,"bounded" | "unbounded",'bounded',false
ion-ripple-effect,method,addRipple,addRipple(pageX: number, pageY: number) => Promise<() => void>
ion-route-redirect,prop,from,string,undefined,false
@@ -943,6 +944,7 @@ ion-tab-button,style,--padding-bottom
ion-tab-button,style,--padding-end
ion-tab-button,style,--padding-start
ion-tab-button,style,--padding-top
+ion-tab-button,style,--ripple-color
ion-tab,prop,component,Function | HTMLElement | null | string | undefined,undefined,false
ion-tab,prop,tab,string,undefined,false
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 7055fab623a..93a59c144f8 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -3543,8 +3543,17 @@ export namespace Components {
* Adds the ripple effect to the parent element
*/
'addRipple': (pageX: number, pageY: number) => Promise<() => void>;
+ /**
+ * Sets the type of ripple-effect: - `bounded`: the ripple effect expands from the user's click position - `unbounded`: the ripple effect expands from the center of the button and overflows the container. NOTE: Surfaces for bounded ripples should have the overflow property set to hidden, while surfaces for unbounded ripples should have it set to visible.
+ */
+ 'type': 'bounded' | 'unbounded';
+ }
+ interface IonRippleEffectAttributes extends StencilHTMLAttributes {
+ /**
+ * Sets the type of ripple-effect: - `bounded`: the ripple effect expands from the user's click position - `unbounded`: the ripple effect expands from the center of the button and overflows the container. NOTE: Surfaces for bounded ripples should have the overflow property set to hidden, while surfaces for unbounded ripples should have it set to visible.
+ */
+ 'type'?: 'bounded' | 'unbounded';
}
- interface IonRippleEffectAttributes extends StencilHTMLAttributes {}
interface IonRouteRedirect {
/**
diff --git a/core/src/components/button/button.scss b/core/src/components/button/button.scss
index 9cfdc69ab57..c2905b84ee2 100644
--- a/core/src/components/button/button.scss
+++ b/core/src/components/button/button.scss
@@ -218,7 +218,7 @@
line-height: 1;
box-shadow: var(--box-shadow);
- contain: content;
+ contain: layout style;
cursor: pointer;
opacity: var(--opacity);
overflow: var(--overflow);
diff --git a/core/src/components/button/button.tsx b/core/src/components/button/button.tsx
index e4ffffce42e..69ffd098558 100644
--- a/core/src/components/button/button.tsx
+++ b/core/src/components/button/button.tsx
@@ -13,6 +13,9 @@ import { createColorClasses, openURL } from '../../utils/theme';
shadow: true,
})
export class Button implements ComponentInterface {
+
+ private inToolbar = false;
+
@Element() el!: HTMLElement;
@Prop({ context: 'window' }) win!: Window;
@@ -97,9 +100,7 @@ export class Button implements ComponentInterface {
@Event() ionBlur!: EventEmitter;
componentWillLoad() {
- if (this.fill === undefined) {
- this.fill = this.el.closest('ion-buttons') ? 'clear' : 'solid';
- }
+ this.inToolbar = !!this.el.closest('ion-buttons');
}
private onFocus = () => {
@@ -139,8 +140,11 @@ export class Button implements ComponentInterface {
}
hostData() {
- const { buttonType, keyFocus, disabled, color, expand, fill, shape, size, strong } = this;
-
+ const { buttonType, keyFocus, disabled, color, expand, shape, size, strong } = this;
+ let fill = this.fill;
+ if (fill === undefined) {
+ fill = this.inToolbar ? 'clear' : 'solid';
+ }
return {
'ion-activatable': true,
'aria-disabled': this.disabled ? 'true' : null,
@@ -181,7 +185,7 @@ export class Button implements ComponentInterface {
- {this.mode === 'md' && }
+ {this.mode === 'md' && }
);
}
diff --git a/core/src/components/buttons/buttons.scss b/core/src/components/buttons/buttons.scss
index 74e21c21432..53dad899dfe 100644
--- a/core/src/components/buttons/buttons.scss
+++ b/core/src/components/buttons/buttons.scss
@@ -23,6 +23,7 @@
--padding-start: 0;
--padding-end: 0;
--box-shadow: none;
+ --overflow: visible;
@include margin-horizontal(2px, 2px);
}
diff --git a/core/src/components/ripple-effect/readme.md b/core/src/components/ripple-effect/readme.md
index 7c66c666d6d..5f734b56e1b 100644
--- a/core/src/components/ripple-effect/readme.md
+++ b/core/src/components/ripple-effect/readme.md
@@ -6,6 +6,13 @@ The ripple effect component adds the [Material Design ink ripple interaction eff
+## Properties
+
+| Property | Attribute | Description | Type | Default |
+| -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ----------- |
+| `type` | `type` | Sets the type of ripple-effect: - `bounded`: the ripple effect expands from the user's click position - `unbounded`: the ripple effect expands from the center of the button and overflows the container. NOTE: Surfaces for bounded ripples should have the overflow property set to hidden, while surfaces for unbounded ripples should have it set to visible. | `"bounded" \| "unbounded"` | `'bounded'` |
+
+
## Methods
### `addRipple(pageX: number, pageY: number) => Promise<() => void>`
diff --git a/core/src/components/ripple-effect/ripple-effect.scss b/core/src/components/ripple-effect/ripple-effect.scss
index cfd26c9e894..36bf6a1a7a2 100644
--- a/core/src/components/ripple-effect/ripple-effect.scss
+++ b/core/src/components/ripple-effect/ripple-effect.scss
@@ -17,6 +17,10 @@ $opacity-duration: $fade-in-duration + $fade-out-duration;
contain: strict;
}
+:host(.unbounded) {
+ contain: layout size style;
+}
+
.ripple-effect {
@include border-radius(50%);
diff --git a/core/src/components/ripple-effect/ripple-effect.tsx b/core/src/components/ripple-effect/ripple-effect.tsx
index 89792769b99..98ae9d683f0 100644
--- a/core/src/components/ripple-effect/ripple-effect.tsx
+++ b/core/src/components/ripple-effect/ripple-effect.tsx
@@ -12,6 +12,17 @@ export class RippleEffect implements ComponentInterface {
@Prop({ context: 'queue' }) queue!: QueueApi;
@Prop({ context: 'window' }) win!: Window;
+ /**
+ * Sets the type of ripple-effect:
+ *
+ * - `bounded`: the ripple effect expands from the user's click position
+ * - `unbounded`: the ripple effect expands from the center of the button and overflows the container.
+ *
+ * NOTE: Surfaces for bounded ripples should have the overflow property set to hidden,
+ * while surfaces for unbounded ripples should have it set to visible.
+ */
+ @Prop() type: 'bounded' | 'unbounded' = 'bounded';
+
/**
* Adds the ripple effect to the parent element
*/
@@ -23,13 +34,17 @@ export class RippleEffect implements ComponentInterface {
const width = rect.width;
const height = rect.height;
const hypotenuse = Math.sqrt(width * width + height * height);
- const maxRadius = hypotenuse + PADDING;
const maxDim = Math.max(height, width);
- const posX = pageX - rect.left;
- const posY = pageY - rect.top;
-
+ const maxRadius = this.unbounded ? maxDim : hypotenuse + PADDING;
const initialSize = Math.floor(maxDim * INITIAL_ORIGIN_SCALE);
const finalScale = maxRadius / initialSize;
+ let posX = pageX - rect.left;
+ let posY = pageY - rect.top;
+ if (this.type) {
+ posX = width * 0.5;
+ posY = height * 0.5;
+ }
+
const x = posX - initialSize * 0.5;
const y = posY - initialSize * 0.5;
const moveX = width * 0.5 - posX;
@@ -57,9 +72,16 @@ export class RippleEffect implements ComponentInterface {
});
}
+ private get unbounded() {
+ return this.type === 'unbounded';
+ }
+
hostData() {
return {
- role: 'presentation'
+ role: 'presentation',
+ class: {
+ 'unbounded': this.unbounded
+ }
};
}
}
diff --git a/core/src/components/tab-button/readme.md b/core/src/components/tab-button/readme.md
index 8fb9ad3261b..0d7e526c058 100644
--- a/core/src/components/tab-button/readme.md
+++ b/core/src/components/tab-button/readme.md
@@ -32,6 +32,7 @@ See the [Tabs API Docs](../Tabs/) for more details on configuring Tabs.
| `--padding-end` | End padding of the tab button |
| `--padding-start` | Start padding of the tab button |
| `--padding-top` | Top padding of the tab button |
+| `--ripple-color` | Color of the button ripple effect |
----------------------------------------------
diff --git a/core/src/components/tab-button/tab-button.scss b/core/src/components/tab-button/tab-button.scss
index aa9cccb50af..b32b5e2a3aa 100644
--- a/core/src/components/tab-button/tab-button.scss
+++ b/core/src/components/tab-button/tab-button.scss
@@ -10,8 +10,10 @@
* @prop --padding-end: End padding of the tab button
* @prop --padding-bottom: Bottom padding of the tab button
* @prop --padding-start: Start padding of the tab button
+ * @prop --ripple-color: Color of the button ripple effect
*/
--badge-end: 4%;
+ --ripple-color: var(--color-selected);
flex: 1;
@@ -177,3 +179,7 @@ a:focus-visible {
:host(.tab-has-label-only) {
--badge-end: #{calc(50% - 50px)};
}
+
+ion-ripple-effect {
+ color: var(--ripple-color);
+}
diff --git a/core/src/components/tab-button/tab-button.tsx b/core/src/components/tab-button/tab-button.tsx
index c620642aaf7..68dcc49aede 100644
--- a/core/src/components/tab-button/tab-button.tsx
+++ b/core/src/components/tab-button/tab-button.tsx
@@ -122,7 +122,7 @@ export class TabButton implements ComponentInterface {
return (
- {mode === 'md' && }
+ {mode === 'md' && }
);
}