refactor(button): add ripple effect to ionic theme (#29754)
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
23
core/api.txt
@ -398,50 +398,73 @@ ion-button,prop,theme,"ios" | "md" | "ionic",undefined,false,false
|
|||||||
ion-button,prop,type,"button" | "reset" | "submit",'button',false,false
|
ion-button,prop,type,"button" | "reset" | "submit",'button',false,false
|
||||||
ion-button,event,ionBlur,void,true
|
ion-button,event,ionBlur,void,true
|
||||||
ion-button,event,ionFocus,void,true
|
ion-button,event,ionFocus,void,true
|
||||||
|
ion-button,css-prop,--background,ionic
|
||||||
ion-button,css-prop,--background,ios
|
ion-button,css-prop,--background,ios
|
||||||
ion-button,css-prop,--background,md
|
ion-button,css-prop,--background,md
|
||||||
|
ion-button,css-prop,--background-activated,ionic
|
||||||
ion-button,css-prop,--background-activated,ios
|
ion-button,css-prop,--background-activated,ios
|
||||||
ion-button,css-prop,--background-activated,md
|
ion-button,css-prop,--background-activated,md
|
||||||
|
ion-button,css-prop,--background-activated-opacity,ionic
|
||||||
ion-button,css-prop,--background-activated-opacity,ios
|
ion-button,css-prop,--background-activated-opacity,ios
|
||||||
ion-button,css-prop,--background-activated-opacity,md
|
ion-button,css-prop,--background-activated-opacity,md
|
||||||
|
ion-button,css-prop,--background-focused,ionic
|
||||||
ion-button,css-prop,--background-focused,ios
|
ion-button,css-prop,--background-focused,ios
|
||||||
ion-button,css-prop,--background-focused,md
|
ion-button,css-prop,--background-focused,md
|
||||||
|
ion-button,css-prop,--background-focused-opacity,ionic
|
||||||
ion-button,css-prop,--background-focused-opacity,ios
|
ion-button,css-prop,--background-focused-opacity,ios
|
||||||
ion-button,css-prop,--background-focused-opacity,md
|
ion-button,css-prop,--background-focused-opacity,md
|
||||||
|
ion-button,css-prop,--background-hover,ionic
|
||||||
ion-button,css-prop,--background-hover,ios
|
ion-button,css-prop,--background-hover,ios
|
||||||
ion-button,css-prop,--background-hover,md
|
ion-button,css-prop,--background-hover,md
|
||||||
|
ion-button,css-prop,--background-hover-opacity,ionic
|
||||||
ion-button,css-prop,--background-hover-opacity,ios
|
ion-button,css-prop,--background-hover-opacity,ios
|
||||||
ion-button,css-prop,--background-hover-opacity,md
|
ion-button,css-prop,--background-hover-opacity,md
|
||||||
|
ion-button,css-prop,--border-color,ionic
|
||||||
ion-button,css-prop,--border-color,ios
|
ion-button,css-prop,--border-color,ios
|
||||||
ion-button,css-prop,--border-color,md
|
ion-button,css-prop,--border-color,md
|
||||||
|
ion-button,css-prop,--border-radius,ionic
|
||||||
ion-button,css-prop,--border-radius,ios
|
ion-button,css-prop,--border-radius,ios
|
||||||
ion-button,css-prop,--border-radius,md
|
ion-button,css-prop,--border-radius,md
|
||||||
|
ion-button,css-prop,--border-style,ionic
|
||||||
ion-button,css-prop,--border-style,ios
|
ion-button,css-prop,--border-style,ios
|
||||||
ion-button,css-prop,--border-style,md
|
ion-button,css-prop,--border-style,md
|
||||||
|
ion-button,css-prop,--border-width,ionic
|
||||||
ion-button,css-prop,--border-width,ios
|
ion-button,css-prop,--border-width,ios
|
||||||
ion-button,css-prop,--border-width,md
|
ion-button,css-prop,--border-width,md
|
||||||
|
ion-button,css-prop,--box-shadow,ionic
|
||||||
ion-button,css-prop,--box-shadow,ios
|
ion-button,css-prop,--box-shadow,ios
|
||||||
ion-button,css-prop,--box-shadow,md
|
ion-button,css-prop,--box-shadow,md
|
||||||
|
ion-button,css-prop,--color,ionic
|
||||||
ion-button,css-prop,--color,ios
|
ion-button,css-prop,--color,ios
|
||||||
ion-button,css-prop,--color,md
|
ion-button,css-prop,--color,md
|
||||||
|
ion-button,css-prop,--color-activated,ionic
|
||||||
ion-button,css-prop,--color-activated,ios
|
ion-button,css-prop,--color-activated,ios
|
||||||
ion-button,css-prop,--color-activated,md
|
ion-button,css-prop,--color-activated,md
|
||||||
|
ion-button,css-prop,--color-focused,ionic
|
||||||
ion-button,css-prop,--color-focused,ios
|
ion-button,css-prop,--color-focused,ios
|
||||||
ion-button,css-prop,--color-focused,md
|
ion-button,css-prop,--color-focused,md
|
||||||
|
ion-button,css-prop,--color-hover,ionic
|
||||||
ion-button,css-prop,--color-hover,ios
|
ion-button,css-prop,--color-hover,ios
|
||||||
ion-button,css-prop,--color-hover,md
|
ion-button,css-prop,--color-hover,md
|
||||||
|
ion-button,css-prop,--opacity,ionic
|
||||||
ion-button,css-prop,--opacity,ios
|
ion-button,css-prop,--opacity,ios
|
||||||
ion-button,css-prop,--opacity,md
|
ion-button,css-prop,--opacity,md
|
||||||
|
ion-button,css-prop,--padding-bottom,ionic
|
||||||
ion-button,css-prop,--padding-bottom,ios
|
ion-button,css-prop,--padding-bottom,ios
|
||||||
ion-button,css-prop,--padding-bottom,md
|
ion-button,css-prop,--padding-bottom,md
|
||||||
|
ion-button,css-prop,--padding-end,ionic
|
||||||
ion-button,css-prop,--padding-end,ios
|
ion-button,css-prop,--padding-end,ios
|
||||||
ion-button,css-prop,--padding-end,md
|
ion-button,css-prop,--padding-end,md
|
||||||
|
ion-button,css-prop,--padding-start,ionic
|
||||||
ion-button,css-prop,--padding-start,ios
|
ion-button,css-prop,--padding-start,ios
|
||||||
ion-button,css-prop,--padding-start,md
|
ion-button,css-prop,--padding-start,md
|
||||||
|
ion-button,css-prop,--padding-top,ionic
|
||||||
ion-button,css-prop,--padding-top,ios
|
ion-button,css-prop,--padding-top,ios
|
||||||
ion-button,css-prop,--padding-top,md
|
ion-button,css-prop,--padding-top,md
|
||||||
|
ion-button,css-prop,--ripple-color,ionic
|
||||||
ion-button,css-prop,--ripple-color,ios
|
ion-button,css-prop,--ripple-color,ios
|
||||||
ion-button,css-prop,--ripple-color,md
|
ion-button,css-prop,--ripple-color,md
|
||||||
|
ion-button,css-prop,--transition,ionic
|
||||||
ion-button,css-prop,--transition,ios
|
ion-button,css-prop,--transition,ios
|
||||||
ion-button,css-prop,--transition,md
|
ion-button,css-prop,--transition,md
|
||||||
ion-button,part,native
|
ion-button,part,native
|
||||||
|
@ -51,8 +51,6 @@
|
|||||||
|
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
|
|
||||||
font-family: $font-family-base;
|
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
@ -217,18 +215,9 @@
|
|||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
::slotted(ion-icon) {
|
::slotted(ion-icon) {
|
||||||
font-size: 1.35em;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
::slotted(ion-icon[slot="start"]) {
|
|
||||||
@include margin(0, 0.3em, 0, -0.3em);
|
|
||||||
}
|
|
||||||
|
|
||||||
::slotted(ion-icon[slot="end"]) {
|
|
||||||
@include margin(0, -0.2em, 0, 0.3em);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Button Ripple effect
|
// Button Ripple effect
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
@ -1,48 +1,23 @@
|
|||||||
@use "../../themes/ionic/ionic.globals.scss" as globals;
|
@use "../../themes/ionic/ionic.globals.scss" as globals;
|
||||||
|
@use "./button.common";
|
||||||
|
|
||||||
// Ionic Button
|
// Ionic Button
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
:host {
|
:host {
|
||||||
--overflow: hidden;
|
|
||||||
--border-width: initial;
|
|
||||||
--border-color: initial;
|
|
||||||
--border-style: initial;
|
|
||||||
--color-activated: var(--color);
|
|
||||||
--color-focused: var(--color);
|
|
||||||
--color-hover: var(--color);
|
|
||||||
--box-shadow: none;
|
|
||||||
--padding-bottom: var(--padding-top);
|
--padding-bottom: var(--padding-top);
|
||||||
--padding-end: #{globals.$ionic-space-400};
|
--padding-end: #{globals.$ionic-space-500};
|
||||||
--padding-start: var(--padding-end);
|
--padding-start: var(--padding-end);
|
||||||
--padding-top: #{globals.$ionic-space-300};
|
--padding-top: #{globals.$ionic-space-0};
|
||||||
--focus-ring-color: #{globals.$ionic-state-focus-1};
|
--focus-ring-color: #{globals.$ionic-state-focus-1};
|
||||||
--focus-ring-width: #{globals.$ionic-border-size-050};
|
--focus-ring-width: #{globals.$ionic-border-size-050};
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
min-height: globals.$ionic-scale-1000;
|
min-height: globals.$ionic-scale-1000;
|
||||||
|
|
||||||
color: var(--color);
|
|
||||||
|
|
||||||
font-family: globals.$ionic-font-family;
|
font-family: globals.$ionic-font-family;
|
||||||
|
|
||||||
font-size: globals.$ionic-font-size-350;
|
font-size: globals.$ionic-font-size-350;
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
white-space: normal;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
vertical-align: top; // the better option for most scenarios
|
|
||||||
vertical-align: -webkit-baseline-middle; // the best for those that support it
|
|
||||||
|
|
||||||
font-kerning: none;
|
|
||||||
|
|
||||||
// Target area
|
// Target area
|
||||||
&::after {
|
&::after {
|
||||||
@include globals.position(50%, 0, null, 0);
|
@include globals.position(50%, 0, null, 0);
|
||||||
@ -59,37 +34,60 @@
|
|||||||
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
::slotted(ion-icon[slot="start"]) {
|
|
||||||
@include globals.margin-horizontal(null, globals.$ionic-space-200);
|
|
||||||
}
|
|
||||||
|
|
||||||
::slotted(ion-icon[slot="end"]) {
|
|
||||||
@include globals.margin-horizontal(globals.$ionic-space-200, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Colors
|
// Button Fills
|
||||||
|
// -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Solid Button
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
// Solid Button with Color
|
:host(.button-solid) {
|
||||||
:host(.button-solid.ion-color) .button-native {
|
--background-activated: #{globals.ion-color(primary, shade)};
|
||||||
background: globals.current-color(base);
|
--background-hover: #{globals.ion-color(primary, contrast)};
|
||||||
color: globals.current-color(contrast);
|
--background-focused: #{globals.ion-color(primary, contrast)};
|
||||||
|
--background-focused-opacity: 0.24;
|
||||||
|
--background-hover-opacity: 0.08;
|
||||||
|
--ripple-opacity: var(--background-activated-opacity, 1);
|
||||||
|
--ripple-color: var(--background-activated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outline Button with Color
|
// Outline Button
|
||||||
:host(.button-outline.ion-color) .button-native {
|
// --------------------------------------------------
|
||||||
border-color: globals.current-color(base);
|
|
||||||
|
|
||||||
background: transparent;
|
:host(.button-outline) {
|
||||||
color: globals.current-color(base);
|
--border-width: #{globals.$ionic-border-size-025};
|
||||||
|
--border-style: #{globals.$ionic-border-style-solid};
|
||||||
|
--background-activated: #{globals.$ionic-color-neutral-200};
|
||||||
|
--background-focused: transparent;
|
||||||
|
--background-hover: #{globals.ion-color(primary, base)};
|
||||||
|
--background-hover-opacity: 0.04;
|
||||||
|
--ripple-opacity: var(--background-activated-opacity, 1);
|
||||||
|
--ripple-color: var(--background-activated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear Button with Color
|
// Clear Button
|
||||||
:host(.button-clear.ion-color) .button-native {
|
// --------------------------------------------------
|
||||||
background: transparent;
|
|
||||||
color: globals.current-color(base);
|
:host(.button-clear) {
|
||||||
|
--background-activated: #{globals.$ionic-color-neutral-200};
|
||||||
|
--background-focused: transparent;
|
||||||
|
--background-hover: #{globals.ion-color(primary, base)};
|
||||||
|
--background-hover-opacity: 0.04;
|
||||||
|
--ripple-opacity: var(--background-activated-opacity, 1);
|
||||||
|
--ripple-color: var(--background-activated);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ripple Effect
|
||||||
|
// -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
:host(.button-solid.ion-color) ion-ripple-effect {
|
||||||
|
color: globals.current-color(shade);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.button-outline.ion-color) ion-ripple-effect,
|
||||||
|
:host(.button-clear.ion-color) ion-ripple-effect {
|
||||||
|
color: globals.$ionic-color-neutral-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Sizes
|
// Button Sizes
|
||||||
@ -177,6 +175,9 @@
|
|||||||
// Button Shapes
|
// Button Shapes
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Soft Button
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.button-soft) {
|
:host(.button-soft) {
|
||||||
--border-radius: #{globals.$ionic-border-radius-200};
|
--border-radius: #{globals.$ionic-border-radius-200};
|
||||||
}
|
}
|
||||||
@ -186,15 +187,21 @@
|
|||||||
--border-radius: #{globals.$ionic-border-radius-100};
|
--border-radius: #{globals.$ionic-border-radius-100};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Round Button
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.button-round) {
|
:host(.button-round) {
|
||||||
--border-radius: #{globals.$ionic-border-radius-full};
|
--border-radius: #{globals.$ionic-border-radius-full};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rectangular Button
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.button-rectangular) {
|
:host(.button-rectangular) {
|
||||||
--border-radius: #{globals.$ionic-border-radius-0};
|
--border-radius: #{globals.$ionic-border-radius-0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Focused
|
// Button: Focus
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Only show the focus ring when the button is focused
|
// Only show the focus ring when the button is focused
|
||||||
@ -203,57 +210,6 @@
|
|||||||
outline-offset: globals.$ionic-border-size-050;
|
outline-offset: globals.$ionic-border-size-050;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill Solid Button
|
|
||||||
// -------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
:host(.button-solid) {
|
|
||||||
--background-activated: #{globals.$ionic-color-primary-base};
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-solid.ion-activated) .button-native::after {
|
|
||||||
background: #{globals.$ionic-color-primary-900};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill Outline Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
:host(.button-outline) {
|
|
||||||
--border-width: #{globals.$ionic-border-size-025};
|
|
||||||
--border-style: #{globals.$ionic-border-style-solid};
|
|
||||||
--background-activated: #{globals.$ionic-color-neutral-200};
|
|
||||||
--background-activated-opacity: 1;
|
|
||||||
--background-focused: transparent;
|
|
||||||
--background-hover: transparent;
|
|
||||||
--background-focused-opacity: 0.1;
|
|
||||||
--color-activated: #{globals.$ionic-color-primary-base};
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-outline.ion-focused) {
|
|
||||||
--border-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill Clear Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
:host(.button-clear) {
|
|
||||||
--background-activated: #{globals.$ionic-color-neutral-200};
|
|
||||||
--background-activated-opacity: 1;
|
|
||||||
--background-focused: transparent;
|
|
||||||
--background-hover: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Button Hover
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
:host(.button-solid) {
|
|
||||||
--background-hover: #{globals.$ionic-color-primary-800};
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-outline),
|
|
||||||
:host(.button-clear) {
|
|
||||||
--background-hover: #{globals.$ionic-color-neutral-100};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only allow overriding of opacity here
|
* Only allow overriding of opacity here
|
||||||
* as developers should not be overriding
|
* as developers should not be overriding
|
||||||
@ -261,177 +217,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
:host(.button-solid.ion-color.ion-focused) .button-native::after {
|
:host(.button-solid.ion-color.ion-focused) .button-native::after {
|
||||||
background: #{current-color(contrast)};
|
background: globals.current-color(contrast);
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.button-clear.ion-color.ion-focused) .button-native::after,
|
// Button: Activated
|
||||||
:host(.button-outline.ion-color.ion-focused) .button-native::after {
|
// --------------------------------------------------
|
||||||
background: #{current-color(base)};
|
|
||||||
|
:host(.button-solid.ion-color.ion-activated) .button-native::after {
|
||||||
|
background: globals.current-color(shade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (any-hover: hover) {
|
:host(.ion-activated) .button-native:has(ion-ripple-effect)::after,
|
||||||
:host(.button-solid.ion-color:hover) .button-native::after {
|
:host(.button-solid.ion-color.ion-activated) .button-native:has(ion-ripple-effect)::after {
|
||||||
background: #{current-color(contrast)};
|
background: transparent;
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-clear.ion-color:hover) .button-native::after,
|
|
||||||
:host(.button-outline.ion-color:hover) .button-native::after {
|
|
||||||
background: #{current-color(base)};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button: Disabled
|
// Button: Disabled
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
:host(.button-disabled) {
|
:host(.button-disabled) {
|
||||||
--background: #{globals.$ionic-state-disabled};
|
opacity: 0.6;
|
||||||
--border-color: var(--color);
|
|
||||||
|
|
||||||
cursor: default;
|
|
||||||
opacity: 0.5;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Solid Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Default Solid Color
|
|
||||||
:host(.button-solid) {
|
|
||||||
--background: #{globals.$ionic-color-primary-base};
|
|
||||||
--color: #{globals.$ionic-color-base-white};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outline Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Default Outline Color
|
|
||||||
:host(.button-outline) {
|
|
||||||
--border-color: #{globals.ion-color(primary, base)};
|
|
||||||
--background: #{globals.$ionic-color-base-white};
|
|
||||||
--color: #{globals.ion-color(primary, base)};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Default Clear Color
|
|
||||||
:host(.button-clear) {
|
|
||||||
--border-width: #{globals.$ionic-border-size-0};
|
|
||||||
--background: transparent;
|
|
||||||
--color: #{globals.$ionic-color-primary-base};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
:host(.button-block) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-block) .button-native {
|
|
||||||
@include globals.margin-horizontal(0);
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
clear: both;
|
|
||||||
|
|
||||||
contain: content;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-block) .button-native::after {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Full Button
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
:host(.button-full) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-full) .button-native {
|
|
||||||
@include globals.margin-horizontal(0);
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
contain: content;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.button-full:not(.button-round)) .button-native {
|
|
||||||
@include globals.border-radius(0);
|
|
||||||
|
|
||||||
border-right-width: 0;
|
|
||||||
border-left-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-native {
|
|
||||||
@include globals.border-radius(var(--border-radius));
|
|
||||||
@include globals.font-smoothing();
|
|
||||||
@include globals.margin(0);
|
|
||||||
@include globals.padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start));
|
|
||||||
@include globals.text-inherit();
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
min-height: inherit;
|
|
||||||
|
|
||||||
transition: var(--transition);
|
|
||||||
|
|
||||||
border-width: var(--border-width);
|
|
||||||
border-style: var(--border-style);
|
|
||||||
border-color: var(--border-color);
|
|
||||||
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
background: var(--background);
|
|
||||||
|
|
||||||
line-height: 1;
|
|
||||||
|
|
||||||
box-shadow: var(--box-shadow);
|
|
||||||
|
|
||||||
contain: layout style;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
opacity: var(--opacity);
|
|
||||||
overflow: var(--overflow);
|
|
||||||
|
|
||||||
z-index: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-native::-moz-focus-inner {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-inner {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
flex-flow: row nowrap;
|
|
||||||
flex-shrink: 0;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Button Slots
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
::slotted([slot="start"]),
|
|
||||||
::slotted([slot="end"]) {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Icons
|
// Button Icons
|
||||||
@ -439,47 +244,28 @@
|
|||||||
|
|
||||||
::slotted(ion-icon) {
|
::slotted(ion-icon) {
|
||||||
font-size: globals.$ionic-font-size-500;
|
font-size: globals.$ionic-font-size-500;
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button: States
|
:host(.button-small) ::slotted(ion-icon[slot="start"]) {
|
||||||
// --------------------------------------------------
|
@include globals.margin-horizontal(null, globals.$ionic-space-200);
|
||||||
|
|
||||||
.button-native::after {
|
|
||||||
@include globals.button-state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Focused
|
::slotted(ion-icon[slot="start"]) {
|
||||||
:host(.ion-focused) {
|
@include globals.margin-horizontal(null, globals.$ionic-space-250);
|
||||||
color: var(--color-focused);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.ion-focused) .button-native::after {
|
:host(.button-large) ::slotted(ion-icon[slot="start"]) {
|
||||||
background: var(--background-focused);
|
@include globals.margin-horizontal(null, globals.$ionic-space-300);
|
||||||
|
|
||||||
opacity: var(--background-focused-opacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Hover
|
:host(.button-small) ::slotted(ion-icon[slot="end"]) {
|
||||||
@media (any-hover: hover) {
|
@include globals.margin-horizontal(globals.$ionic-space-200, null);
|
||||||
:host(:hover) {
|
|
||||||
color: var(--color-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(:hover) .button-native::after {
|
|
||||||
background: var(--background-hover);
|
|
||||||
|
|
||||||
opacity: var(--background-hover-opacity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button Activated
|
::slotted(ion-icon[slot="end"]) {
|
||||||
:host(.ion-activated) {
|
@include globals.margin-horizontal(globals.$ionic-space-250, null);
|
||||||
color: var(--color-activated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.ion-activated) .button-native::after {
|
:host(.button-large) ::slotted(ion-icon[slot="end"]) {
|
||||||
background: var(--background-activated);
|
@include globals.margin-horizontal(globals.$ionic-space-300, null);
|
||||||
|
|
||||||
opacity: var(--background-activated-opacity);
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "./button";
|
@import "./button.native";
|
||||||
@import "./button.ios.vars";
|
@import "./button.ios.vars";
|
||||||
@import "../toolbar/toolbar.ios.vars";
|
@import "../toolbar/toolbar.ios.vars";
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "./button";
|
@import "./button.native";
|
||||||
@import "./button.md.vars";
|
@import "./button.md.vars";
|
||||||
|
|
||||||
// Material Design Button
|
// Material Design Button
|
||||||
|
24
core/src/components/button/button.native.scss
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@use "../../themes/native/native.globals.md" as globals;
|
||||||
|
@use "./button.common";
|
||||||
|
|
||||||
|
// Button - iOS and Material Design
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
:host {
|
||||||
|
font-family: globals.$font-family-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button Icons
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
::slotted(ion-icon) {
|
||||||
|
font-size: 1.35em;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(ion-icon[slot="start"]) {
|
||||||
|
@include globals.margin(0, 0.3em, 0, -0.3em);
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(ion-icon[slot="end"]) {
|
||||||
|
@include globals.margin(0, -0.2em, 0, 0.3em);
|
||||||
|
}
|
@ -6,7 +6,7 @@ import { inheritAriaAttributes, hasShadowDom } from '@utils/helpers';
|
|||||||
import { printIonWarning } from '@utils/logging';
|
import { printIonWarning } from '@utils/logging';
|
||||||
import { createColorClasses, hostContext, openURL } from '@utils/theme';
|
import { createColorClasses, hostContext, openURL } from '@utils/theme';
|
||||||
|
|
||||||
import { getIonTheme } from '../../global/ionic-global';
|
import { getIonTheme, getIonMode } from '../../global/ionic-global';
|
||||||
import type { AnimationBuilder, Color } from '../../interface';
|
import type { AnimationBuilder, Color } from '../../interface';
|
||||||
import type { RouterDirection } from '../router/utils/interface';
|
import type { RouterDirection } from '../router/utils/interface';
|
||||||
|
|
||||||
@ -353,6 +353,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
|||||||
this;
|
this;
|
||||||
|
|
||||||
const theme = getIonTheme(this);
|
const theme = getIonTheme(this);
|
||||||
|
const mode = getIonMode(this);
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const shape = this.getShape();
|
const shape = this.getShape();
|
||||||
const TagType = href === undefined ? 'button' : ('a' as any);
|
const TagType = href === undefined ? 'button' : ('a' as any);
|
||||||
@ -421,7 +422,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
<slot name="end"></slot>
|
<slot name="end"></slot>
|
||||||
</span>
|
</span>
|
||||||
{theme === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
|
{mode === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
|
||||||
</TagType>
|
</TagType>
|
||||||
</Host>
|
</Host>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
import { configs, test } from '@utils/test/playwright';
|
import { configs, test } from '@utils/test/playwright';
|
||||||
|
|
||||||
configs().forEach(({ config, screenshot, title }) => {
|
configs({ modes: ['ios', 'md', 'ionic-md', 'ionic-ios'] }).forEach(({ config, screenshot, title }) => {
|
||||||
test.describe(title('button: basic'), () => {
|
test.describe(title('button: basic'), () => {
|
||||||
test('should not have visual regressions', async ({ page }) => {
|
test('should not have visual regressions', async ({ page }) => {
|
||||||
await page.goto(`/src/components/button/test/basic`, config);
|
await page.goto(`/src/components/button/test/basic`, config);
|
||||||
@ -39,9 +39,9 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ config, title }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ripple effect is only available in MD mode.
|
* Ripple effect is only available in MD and Ionic mode.
|
||||||
*/
|
*/
|
||||||
configs({ modes: ['md'] }).forEach(({ config, screenshot, title }) => {
|
configs({ modes: ['md', 'ionic-md'] }).forEach(({ config, screenshot, title }) => {
|
||||||
test.describe(title('button: ripple effect'), () => {
|
test.describe(title('button: ripple effect'), () => {
|
||||||
test('should not have visual regressions', async ({ page }) => {
|
test('should not have visual regressions', async ({ page }) => {
|
||||||
await page.goto(`/src/components/button/test/basic?ionic:_testing=false`, config);
|
await page.goto(`/src/components/button/test/basic?ionic:_testing=false`, config);
|
||||||
|
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.7 KiB |
@ -4,14 +4,16 @@ import { configs, test } from '@utils/test/playwright';
|
|||||||
/**
|
/**
|
||||||
* Fill="clear" does not render differently based on the direction.
|
* Fill="clear" does not render differently based on the direction.
|
||||||
*/
|
*/
|
||||||
configs({ directions: ['ltr'], modes: ['ios', 'md', 'ionic-md'] }).forEach(({ title, config, screenshot }) => {
|
configs({ directions: ['ltr'], modes: ['ios', 'md', 'ionic-md', 'ionic-ios'] }).forEach(
|
||||||
test.describe(title('button: fill: clear'), () => {
|
({ title, config, screenshot }) => {
|
||||||
test('should not have visual regressions', async ({ page }) => {
|
test.describe(title('button: fill: clear'), () => {
|
||||||
await page.goto(`/src/components/button/test/clear`, config);
|
test('should not have visual regressions', async ({ page }) => {
|
||||||
|
await page.goto(`/src/components/button/test/clear`, config);
|
||||||
|
|
||||||
await page.setIonViewport();
|
await page.setIonViewport();
|
||||||
|
|
||||||
await expect(page).toHaveScreenshot(screenshot(`button-fill-clear`));
|
await expect(page).toHaveScreenshot(screenshot(`button-fill-clear`));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
});
|
);
|
||||||
|
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 67 KiB |
@ -1,7 +1,7 @@
|
|||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
import { configs, test } from '@utils/test/playwright';
|
import { configs, test } from '@utils/test/playwright';
|
||||||
|
|
||||||
configs({ modes: ['ios', 'md', 'ionic-md'] }).forEach(({ title, screenshot, config }) => {
|
configs({ modes: ['ios', 'md', 'ionic-md', 'ionic-ios'] }).forEach(({ title, screenshot, config }) => {
|
||||||
test.describe(title('button: outline'), () => {
|
test.describe(title('button: outline'), () => {
|
||||||
test('should not have visual regressions', async ({ page }) => {
|
test('should not have visual regressions', async ({ page }) => {
|
||||||
await page.goto(`/src/components/button/test/outline`, config);
|
await page.goto(`/src/components/button/test/outline`, config);
|
||||||
|
After Width: | Height: | Size: 130 KiB |
After Width: | Height: | Size: 159 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 159 KiB |
After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 136 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 870 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 871 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 866 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 878 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |