diff --git a/core/api.txt b/core/api.txt
index 3b7214ae15f..5de889aff49 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -234,8 +234,8 @@ ion-button,prop,mode,"ios" | "md",undefined,false,false
ion-button,prop,rel,string | undefined,undefined,false,false
ion-button,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-button,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
-ion-button,prop,shape,"round" | undefined,undefined,false,true
-ion-button,prop,size,"default" | "large" | "small" | undefined,undefined,false,true
+ion-button,prop,shape,"rectangular" | "round" | undefined,undefined,false,true
+ion-button,prop,size,"default" | "large" | "small" | "xlarge" | "xsmall" | undefined,undefined,false,true
ion-button,prop,strong,boolean,false,false,false
ion-button,prop,target,string | undefined,undefined,false,false
ion-button,prop,theme,"ios" | "md" | "ionic",undefined,false,false
@@ -265,6 +265,7 @@ ion-button,css-prop,--padding-start
ion-button,css-prop,--padding-top
ion-button,css-prop,--ripple-color
ion-button,css-prop,--transition
+ion-button,part,focus-ring
ion-button,part,native
ion-buttons,scoped
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 91503120f1d..bed08f01ce9 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -545,11 +545,11 @@ export namespace Components {
/**
* Set to `"round"` for a button with more rounded corners.
*/
- "shape"?: 'round';
+ "shape"?: 'round' | 'rectangular';
/**
* Set to `"small"` for a button with less height and padding, to `"default"` for a button with the default height and padding, or to `"large"` for a button with more height and padding. By default the size is unset, unless the button is inside of an item, where the size is `"small"` by default. Set the size to `"default"` inside of an item to make it a standard size button.
*/
- "size"?: 'small' | 'default' | 'large';
+ "size"?: 'xsmall' | 'small' | 'default' | 'large' | 'xlarge';
/**
* If `true`, activates a button with a heavier font weight.
*/
@@ -5735,11 +5735,11 @@ declare namespace LocalJSX {
/**
* Set to `"round"` for a button with more rounded corners.
*/
- "shape"?: 'round';
+ "shape"?: 'round' | 'rectangular';
/**
* Set to `"small"` for a button with less height and padding, to `"default"` for a button with the default height and padding, or to `"large"` for a button with more height and padding. By default the size is unset, unless the button is inside of an item, where the size is `"small"` by default. Set the size to `"default"` inside of an item to make it a standard size button.
*/
- "size"?: 'small' | 'default' | 'large';
+ "size"?: 'xsmall' | 'small' | 'default' | 'large' | 'xlarge';
/**
* If `true`, activates a button with a heavier font weight.
*/
diff --git a/core/src/components/button/button.ionic.scss b/core/src/components/button/button.ionic.scss
new file mode 100644
index 00000000000..8bc1d26f995
--- /dev/null
+++ b/core/src/components/button/button.ionic.scss
@@ -0,0 +1,237 @@
+@import "./button";
+@import "./button.ionic.vars";
+
+// Ionic Button
+// -------------------------------------------------------------------------------
+
+:host {
+ --border-radius: #{$button-ionic-border-radius};
+ --padding-bottom: var(--padding-top);
+ --padding-end: #{$button-ionic-padding-end};
+ --padding-start: var(--padding-end);
+ --padding-top: #{$button-ionic-padding-top};
+ --focus-ring-color: #9ec4fd;
+ --focus-ring-width: 2px;
+
+ position: relative;
+
+ min-height: #{$button-ionic-min-height};
+
+ font-size: #{$button-ionic-font-size};
+
+ // Target area
+ &::after {
+ @include position(50%, 0, null, 0);
+ position: absolute;
+
+ height: 100%;
+ min-height: px-to-rem(48);
+
+ transform: translateY(-50%);
+
+ content: "";
+
+ cursor: pointer;
+
+ z-index: 1;
+ }
+
+ ::slotted(ion-icon[slot="start"]) {
+ @include margin-horizontal(null, px-to-rem(8));
+ }
+
+ ::slotted(ion-icon[slot="end"]) {
+ @include margin-horizontal(px-to-rem(8), null);
+ }
+}
+
+// Button Sizes
+// -------------------------------------------------------------------------------
+
+/* Extra Small and Small Button */
+:host(.button-xsmall),
+:host(.button-small) {
+ ::slotted(ion-icon[slot="start"]) {
+ @include margin-horizontal(null, px-to-rem(4));
+ }
+
+ ::slotted(ion-icon[slot="end"]) {
+ @include margin-horizontal(px-to-rem(4), null);
+ }
+}
+
+/* Extra Small Button */
+:host(.button-xsmall) {
+ --border-radius: #{$button-ionic-xsmall-border-radius};
+ --padding-top: #{$button-ionic-xsmall-padding-top};
+ --padding-end: #{$button-ionic-xsmall-padding-end};
+
+ min-height: #{$button-ionic-xsmall-min-height};
+
+ font-size: #{$button-ionic-xsmall-font-size};
+}
+
+/* Small Button */
+:host(.button-small) {
+ --border-radius: #{$button-ionic-small-border-radius};
+ --padding-top: #{$button-ionic-small-padding-top};
+ --padding-end: #{$button-ionic-small-padding-end};
+
+ min-height: #{$button-ionic-small-min-height};
+
+ font-size: #{$button-ionic-small-font-size};
+}
+
+/* Large Button */
+:host(.button-large) {
+ --padding-top: #{$button-ionic-large-padding-top};
+ --padding-end: #{$button-ionic-large-padding-end};
+
+ min-height: #{$button-ionic-large-min-height};
+
+ font-size: #{$button-ionic-large-font-size};
+}
+
+/* Extra Large Button */
+:host(.button-xlarge) {
+ --padding-top: #{$button-ionic-xlarge-padding-top};
+ --padding-end: #{$button-ionic-xlarge-padding-end};
+
+ min-height: #{$button-ionic-xlarge-min-height};
+
+ font-size: #{$button-ionic-xlarge-font-size};
+}
+
+// Button with Icons
+// -------------------------------------------------------------------------------
+
+/* Button containing only an icon */
+::slotted(ion-icon[slot="start"]),
+::slotted(ion-icon[slot="end"]),
+::slotted(ion-icon[slot="icon-only"]) {
+ font-size: 1em;
+}
+
+/* Button extra small */
+:host(.button-has-icon-only.button-xsmall) {
+ --padding-end: #{$button-has-icon-only-padding-end-xsmall};
+}
+
+/* Button small */
+:host(.button-has-icon-only.button-small) {
+ --padding-end: #{$button-has-icon-only-padding-end-small};
+}
+
+/* Default */
+:host(.button-has-icon-only) {
+ --padding-end: #{$button-has-icon-only-padding-end};
+}
+
+/* Button large */
+:host(.button-has-icon-only.button-large) {
+ --padding-end: #{$button-has-icon-only-padding-end-large};
+}
+
+/* Button extra large */
+:host(.button-has-icon-only.button-xlarge) {
+ --padding-end: #{$button-has-icon-only-padding-end-xlarge};
+}
+
+// Button Shapes
+// -------------------------------------------------------------------------------
+
+// Button Shape Rectangular
+// -------------------------------------------------------------------------------
+:host(.button-rectangular) {
+ --border-radius: #{$button-ionic-rectangular-border};
+}
+
+// Button Shape Round
+// -------------------------------------------------------------------------------
+:host(.button-round) {
+ --border-radius: #{$button-ionic-round-border};
+}
+
+// Button Focused
+// -------------------------------------------------------------------------------
+
+// Only show the focus ring when the button is focused
+:host(.ion-focused) {
+ --overflow: visible;
+
+ .button-native::after {
+ @include border-radius(inherit);
+ }
+}
+
+.button-focus-ring {
+ @include position(-4px, -4px, -4px, -4px);
+ @include border-radius(inherit);
+
+ position: absolute;
+
+ transition: border-color 0.3s;
+
+ border: var(--focus-ring-width) solid var(--focus-ring-color);
+
+ content: "";
+ box-sizing: border-box;
+}
+
+// Fill Solid Button
+// -------------------------------------------------------------------------------
+
+:host(.button-solid) {
+ --background-activated: #{ion-color(primary, shade)};
+}
+
+// Fill Outline Button
+// --------------------------------------------------
+
+:host(.button-outline) {
+ --border-width: #{$button-ionic-outline-border-width};
+ --border-style: #{$button-ionic-outline-border-style};
+ --background-activated: #e3e3e3;
+ --background-activated-opacity: 1;
+ --background-focused: transparent;
+ --background-hover: transparent;
+ --background-focused-opacity: 0.1;
+ --color-activated: #{ion-color(primary, base)};
+}
+
+:host(.button-outline.ion-focused) {
+ --border-color: transparent;
+}
+
+// Fill Clear Button
+// --------------------------------------------------
+
+:host(.button-clear) {
+ --background-activated: #e3e3e3;
+ --background-activated-opacity: 1;
+ --background-focused: transparent;
+ --background-hover: transparent;
+}
+
+// Button Hover
+// --------------------------------------------------
+
+:host(.button-outline),
+:host(.button-clear) {
+ --background-hover: #121212;
+ --background-hover-opacity: 0.04;
+}
+
+// Button: Disabled
+// --------------------------------------------------
+
+:host(.button-disabled) {
+ --color: #c9c9c9;
+ --border-color: var(--color);
+
+ opacity: 1;
+}
+
+:host(.button-solid.button-disabled) {
+ --background: #f5f5f5;
+}
diff --git a/core/src/components/button/button.ionic.vars.scss b/core/src/components/button/button.ionic.vars.scss
new file mode 100644
index 00000000000..d543a781f38
--- /dev/null
+++ b/core/src/components/button/button.ionic.vars.scss
@@ -0,0 +1,164 @@
+@import "../../themes/ionic.globals.ios";
+
+// Ionic Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Border radius of the button
+$button-ionic-border-radius: px-to-rem(8) !default;
+
+/// @prop - Padding top of the button
+$button-ionic-padding-top: px-to-rem(12) !default;
+
+/// @prop - Padding end of the button
+$button-ionic-padding-end: px-to-rem(16) !default;
+
+/// @prop - Padding bottom of the button
+$button-ionic-padding-bottom: $button-ionic-padding-top !default;
+
+/// @prop - Padding start of the button
+$button-ionic-padding-start: $button-ionic-padding-end !default;
+
+/// @prop - Minimum height of the button
+$button-ionic-min-height: px-to-rem(40) !default;
+
+/// @prop - Font size of the button text
+/// The maximum font size is calculated by taking the default font size
+/// and multiplying it by 3, since 310% of the default is the maximum
+$button-ionic-font-size: dynamic-font-max(14px, 3) !default;
+
+// Ionic Extra Small Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Border radius of the extra small button
+$button-ionic-xsmall-border-radius: px-to-rem(4) !default;
+
+/// @prop - Padding top of the extra small button
+$button-ionic-xsmall-padding-top: px-to-rem(4) !default;
+
+/// @prop - Padding end of the extra small button
+$button-ionic-xsmall-padding-end: px-to-rem(12) !default;
+
+/// @prop - Padding bottom of the extra small button
+$button-ionic-xsmall-padding-bottom: $button-ionic-xsmall-padding-top !default;
+
+/// @prop - Padding start of the extra small button
+$button-ionic-xsmall-padding-start: $button-ionic-xsmall-padding-end !default;
+
+/// @prop - Minimum height of the extra small button
+$button-ionic-xsmall-min-height: px-to-rem(24) !default;
+
+/// @prop - Font size of the extra small button text
+/// The maximum font size is calculated by taking the default font size
+/// and multiplying it by 3, since 310% of the default is the maximum
+$button-ionic-xsmall-font-size: dynamic-font-max(12px, 3) !default;
+
+// Ionic Small Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Border radius of the small button
+$button-ionic-small-border-radius: px-to-rem(4) !default;
+
+/// @prop - Padding top of the small button
+$button-ionic-small-padding-top: px-to-rem(8) !default;
+
+/// @prop - Padding end of the small button
+$button-ionic-small-padding-end: px-to-rem(16) !default;
+
+/// @prop - Padding bottom of the small button
+$button-ionic-small-padding-bottom: $button-ionic-small-padding-top !default;
+
+/// @prop - Padding start of the small button
+$button-ionic-small-padding-start: $button-ionic-small-padding-end !default;
+
+/// @prop - Minimum height of the small button
+$button-ionic-small-min-height: px-to-rem(32) !default;
+
+/// @prop - Font size of the small button text
+/// The maximum font size is calculated by taking the default font size
+/// and multiplying it by 3, since 310% of the default is the maximum
+$button-ionic-small-font-size: dynamic-font-max(12px, 3) !default;
+
+// Ionic Large Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Padding top of the large button
+$button-ionic-large-padding-top: px-to-rem(16) !default;
+
+/// @prop - Padding end of the large button
+$button-ionic-large-padding-end: px-to-rem(24) !default;
+
+/// @prop - Padding bottom of the large button
+$button-ionic-large-padding-bottom: $button-ionic-large-padding-top !default;
+
+/// @prop - Padding start of the large button
+$button-ionic-large-padding-start: $button-ionic-large-padding-end !default;
+
+/// @prop - Minimum height of the large button
+$button-ionic-large-min-height: px-to-rem(48) !default;
+
+/// @prop - Font size of the large button text
+/// The maximum font size is calculated by taking the default font size
+/// and multiplying it by 3, since 310% of the default is the maximum
+$button-ionic-large-font-size: dynamic-font-max(16px, 3) !default;
+
+// Ionic Extra Large Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Padding top of the extra large button
+$button-ionic-xlarge-padding-top: px-to-rem(16) !default;
+
+/// @prop - Padding end of the extra large button
+$button-ionic-xlarge-padding-end: px-to-rem(32) !default;
+
+/// @prop - Padding bottom of the extra large button
+$button-ionic-xlarge-padding-bottom: $button-ionic-xlarge-padding-top !default;
+
+/// @prop - Padding start of the extra large button
+$button-ionic-xlarge-padding-start: $button-ionic-xlarge-padding-end !default;
+
+/// @prop - Minimum height of the extra large button
+$button-ionic-xlarge-min-height: px-to-rem(56) !default;
+
+/// @prop - Font size of the extra large button text
+/// The maximum font size is calculated by taking the default font size
+/// and multiplying it by 3, since 310% of the default is the maximum
+$button-ionic-xlarge-font-size: dynamic-font-max(20px, 3) !default;
+
+// Ionic Rectangular Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Border radius of the rectangular button
+$button-ionic-rectangular-border: 0 !default;
+
+// Ionic Round Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Border radius of the round button
+$button-ionic-round-border: px-to-rem(999) !default;
+
+// Ionic Outline Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Border width of the outline button
+$button-ionic-outline-border-width: 1px !default;
+
+/// @prop - Border style of the outline button
+$button-ionic-outline-border-style: solid !default;
+
+// Ionic Icon Only Button
+// -------------------------------------------------------------------------------
+
+/// @prop - Padding end of the icon only button
+$button-has-icon-only-padding-end: px-to-rem(13) !default;
+
+/// @prop - Padding end of the icon only extra small button
+$button-has-icon-only-padding-end-xsmall: px-to-rem(6) !default;
+
+/// @prop - Padding end of the icon only small button
+$button-has-icon-only-padding-end-small: px-to-rem(10) !default;
+
+/// @prop - Padding end of the icon only large button
+$button-has-icon-only-padding-end-large: px-to-rem(16) !default;
+
+/// @prop - Padding end of the icon only extra large button
+$button-has-icon-only-padding-end-xlarge: px-to-rem(18) !default;
diff --git a/core/src/components/button/button.tsx b/core/src/components/button/button.tsx
index 920fcb5a43f..85d82c5b3d7 100644
--- a/core/src/components/button/button.tsx
+++ b/core/src/components/button/button.tsx
@@ -20,13 +20,14 @@ import type { RouterDirection } from '../router/utils/interface';
* @slot end - Content is placed to the right of the button text in LTR, and to the left in RTL.
*
* @part native - The native HTML button or anchor element that wraps all child elements.
+ * @part focus-ring - The visual indicator that appears as an outline around the button when focused. Only available for the Ionic theme.
*/
@Component({
tag: 'ion-button',
styleUrls: {
ios: 'button.ios.scss',
md: 'button.md.scss',
- ionic: 'button.md.scss',
+ ionic: 'button.ionic.scss',
},
shadow: true,
})
@@ -117,7 +118,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
/**
* Set to `"round"` for a button with more rounded corners.
*/
- @Prop({ reflect: true }) shape?: 'round';
+ @Prop({ reflect: true }) shape?: 'round' | 'rectangular';
/**
* Set to `"small"` for a button with less height and padding, to `"default"`
@@ -126,7 +127,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
* is inside of an item, where the size is `"small"` by default. Set the size to
* `"default"` inside of an item to make it a standard size button.
*/
- @Prop({ reflect: true }) size?: 'small' | 'default' | 'large';
+ @Prop({ reflect: true }) size?: 'xsmall' | 'small' | 'default' | 'large' | 'xlarge';
/**
* If `true`, activates a button with a heavier font weight.
@@ -216,6 +217,24 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
return 'bounded';
}
+ /**
+ * Disable the "xsmall" and "xlarge" sizes if the theme is "ios" or "md"
+ */
+ private getSize(): string | undefined {
+ const theme = getIonTheme(this);
+ const { size } = this;
+
+ if (size === undefined && this.inItem) {
+ return 'small';
+ }
+
+ if ((theme === 'ios' || theme === 'md') && (size === 'xsmall' || size === 'xlarge')) {
+ return undefined;
+ }
+
+ return size;
+ }
+
/**
* Finds the form element based on the provided `form` selector
* or element reference provided.
@@ -321,7 +340,6 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
disabled,
rel,
target,
- size,
href,
color,
expand,
@@ -332,7 +350,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
} = this;
const theme = getIonTheme(this);
- const finalSize = size === undefined && this.inItem ? 'small' : size;
+ const finalSize = this.getSize();
const TagType = href === undefined ? 'button' : ('a' as any);
const attrs =
TagType === 'button'
@@ -400,6 +418,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
{theme === 'md' && }
+ {theme === 'ionic' &&
}
);
diff --git a/core/src/components/button/test/clear/button.e2e.ts b/core/src/components/button/test/clear/button.e2e.ts
index 92190aec088..6777705ffd5 100644
--- a/core/src/components/button/test/clear/button.e2e.ts
+++ b/core/src/components/button/test/clear/button.e2e.ts
@@ -1,14 +1,17 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
-configs().forEach(({ title, config, screenshot }) => {
- test.describe(title('button: clear'), () => {
+/**
+ * Fill="clear" does not render differently based on the direction.
+ */
+configs({ directions: ['ltr'], themes: ['ios', 'md', 'ionic'] }).forEach(({ title, config, screenshot }) => {
+ test.describe(title('button: fill: clear'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/clear`, config);
await page.setIonViewport();
- await expect(page).toHaveScreenshot(screenshot(`button-clear`));
+ await expect(page).toHaveScreenshot(screenshot(`button-fill-clear`));
});
});
});
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Chrome-linux.png
deleted file mode 100644
index bbdf5664f8c..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Chrome-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Chrome-linux.png
deleted file mode 100644
index 649c80cbee1..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Chrome-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Firefox-linux.png
deleted file mode 100644
index 32edd81d6d4..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Firefox-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Safari-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Safari-linux.png
deleted file mode 100644
index 1e0e968829a..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-rtl-Mobile-Safari-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Chrome-linux.png
deleted file mode 100644
index 57a09d7aadb..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Chrome-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Firefox-linux.png
deleted file mode 100644
index 9cdd91a7e1f..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Firefox-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Chrome-linux.png
deleted file mode 100644
index bd20962d526..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Chrome-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Firefox-linux.png
deleted file mode 100644
index fdc28fec86b..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Firefox-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Safari-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Safari-linux.png
deleted file mode 100644
index 0f4b5f3d61f..00000000000
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-rtl-Mobile-Safari-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..76b9ffcaa75
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..e4fca3bf782
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Safari-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..f27899245fb
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-ios-ltr-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..10f8baf07d9
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..713f3365029
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..b7fc7dba3b4
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ionic-md-ltr-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..48ba51678e4
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Firefox-linux.png
similarity index 63%
rename from core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Firefox-linux.png
rename to core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Firefox-linux.png
index 4fd2a0a8f56..cdaceec423f 100644
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Safari-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Safari-linux.png
similarity index 100%
rename from core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-ios-ltr-Mobile-Safari-linux.png
rename to core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-ios-ltr-Mobile-Safari-linux.png
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..491cfe187f2
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Firefox-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..96231843d30
Binary files /dev/null and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Safari-linux.png b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Safari-linux.png
similarity index 52%
rename from core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Safari-linux.png
rename to core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Safari-linux.png
index 991f6585e1a..c13bdeb5e4e 100644
Binary files a/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-clear-md-ltr-Mobile-Safari-linux.png and b/core/src/components/button/test/clear/button.e2e.ts-snapshots/button-fill-clear-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-ltr-Mobile-Chrome-linux.png
index 99343bf67bb..dd26d65fe1c 100644
Binary files a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-rtl-Mobile-Chrome-linux.png
index eaab63f282a..e7f22e04389 100644
Binary files a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Chrome-linux.png
index 85dd907f2fc..bf813157a5b 100644
Binary files a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Firefox-linux.png b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Firefox-linux.png
index ed51e623bc3..9369a357c5d 100644
Binary files a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Chrome-linux.png b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Chrome-linux.png
index 477ae42f928..3c99de6532a 100644
Binary files a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Firefox-linux.png b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Firefox-linux.png
index bb58587c5f5..996da9e106c 100644
Binary files a/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/button/test/icon/button.e2e.ts-snapshots/button-icon-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/button/test/round/button.e2e.ts b/core/src/components/button/test/round/button.e2e.ts
deleted file mode 100644
index b61a6307367..00000000000
--- a/core/src/components/button/test/round/button.e2e.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { expect } from '@playwright/test';
-import { configs, test } from '@utils/test/playwright';
-
-/**
- * All content takes up the full width, so RTL has no effect.
- */
-configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
- test.describe(title('button: round'), () => {
- test.describe('default', () => {
- test('should not have visual regressions', async ({ page }) => {
- await page.goto(`/src/components/button/test/round`, config);
-
- await page.setIonViewport();
-
- const container = page.locator('#default');
-
- await expect(container).toHaveScreenshot(screenshot(`button-round`));
- });
- });
-
- test.describe('outline', () => {
- test('should not have visual regressions', async ({ page }) => {
- await page.goto(`/src/components/button/test/round`, config);
-
- await page.setIonViewport();
-
- const container = page.locator('#outline');
-
- await expect(container).toHaveScreenshot(screenshot(`button-outline-round`));
- });
- });
-
- test.describe('clear', () => {
- test('should not have visual regressions', async ({ page }) => {
- await page.goto(`/src/components/button/test/round`, config);
-
- await page.setIonViewport();
-
- const container = page.locator('#clear');
-
- await expect(container).toHaveScreenshot(screenshot(`button-clear-round`));
- });
- });
-
- test.describe('color', () => {
- test('should not have visual regressions', async ({ page }) => {
- await page.goto(`/src/components/button/test/round`, config);
-
- await page.setIonViewport();
-
- const container = page.locator('#color');
-
- await expect(container).toHaveScreenshot(screenshot(`button-color-round`));
- });
- });
-
- test.describe('expand', () => {
- test('should not have visual regressions', async ({ page }) => {
- await page.goto(`/src/components/button/test/round`, config);
-
- await page.setIonViewport();
-
- const container = page.locator('#expand');
-
- await expect(container).toHaveScreenshot(screenshot(`button-expand-round`));
- });
- });
- });
-});
diff --git a/core/src/components/button/test/round/button.e2e.ts-snapshots/button-round-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/round/button.e2e.ts-snapshots/button-round-md-ltr-Mobile-Chrome-linux.png
deleted file mode 100644
index dd97f87f422..00000000000
Binary files a/core/src/components/button/test/round/button.e2e.ts-snapshots/button-round-md-ltr-Mobile-Chrome-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/round/button.e2e.ts-snapshots/button-round-md-ltr-Mobile-Firefox-linux.png b/core/src/components/button/test/round/button.e2e.ts-snapshots/button-round-md-ltr-Mobile-Firefox-linux.png
deleted file mode 100644
index ca027b9d824..00000000000
Binary files a/core/src/components/button/test/round/button.e2e.ts-snapshots/button-round-md-ltr-Mobile-Firefox-linux.png and /dev/null differ
diff --git a/core/src/components/button/test/shape/button.e2e.ts b/core/src/components/button/test/shape/button.e2e.ts
new file mode 100644
index 00000000000..40af4fa1960
--- /dev/null
+++ b/core/src/components/button/test/shape/button.e2e.ts
@@ -0,0 +1,111 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+
+/**
+ * All content takes up the full width, so RTL has no effect.
+ */
+// TODO: FW-6077 - Add ionic theme on MD mode to this test.
+configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('button: shape'), () => {
+ test.describe('round', () => {
+ test.describe('default', () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.goto(`/src/components/button/test/shape`, config);
+
+ await page.setIonViewport();
+
+ const container = page.locator('#default');
+
+ await expect(container).toHaveScreenshot(screenshot(`button-round`));
+ });
+ });
+
+ test.describe('outline', () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.goto(`/src/components/button/test/shape`, config);
+
+ await page.setIonViewport();
+
+ const container = page.locator('#outline');
+
+ await expect(container).toHaveScreenshot(screenshot(`button-outline-round`));
+ });
+ });
+
+ test.describe('clear', () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.goto(`/src/components/button/test/shape`, config);
+
+ await page.setIonViewport();
+
+ const container = page.locator('#clear');
+
+ await expect(container).toHaveScreenshot(screenshot(`button-clear-round`));
+ });
+ });
+
+ test.describe('color', () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.goto(`/src/components/button/test/shape`, config);
+
+ await page.setIonViewport();
+
+ const container = page.locator('#color');
+
+ await expect(container).toHaveScreenshot(screenshot(`button-color-round`));
+ });
+ });
+
+ test.describe('expand', () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.goto(`/src/components/button/test/shape`, config);
+
+ await page.setIonViewport();
+
+ const container = page.locator('#expand');
+
+ await expect(container).toHaveScreenshot(screenshot(`button-expand-round`));
+ });
+ });
+ });
+ });
+});
+
+/**
+ * Shape="rectangular" is only available in the Ionic theme.
+ */
+configs({ directions: ['ltr'], themes: ['ionic'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('button: shape'), () => {
+ test.describe('rectangular', () => {
+ test('should not have visual regressions', async ({ page }) => {
+ await page.setContent(
+ `
+
+