diff --git a/core/src/components/fab-button/fab-button.scss b/core/src/components/fab-button/fab-button.scss index d3841dd541..0bf1495072 100755 --- a/core/src/components/fab-button/fab-button.scss +++ b/core/src/components/fab-button/fab-button.scss @@ -199,7 +199,7 @@ // -------------------------------------------------- :host(.fab-button-small) { - @include margin(($fab-size - $fab-small-size) * 0.5); + @include margin($fab-button-small-margin); width: #{$fab-small-size}; height: #{$fab-small-size}; diff --git a/core/src/components/fab-button/fab-button.vars.scss b/core/src/components/fab-button/fab-button.vars.scss index 5cca974ef5..2556fec9b3 100755 --- a/core/src/components/fab-button/fab-button.vars.scss +++ b/core/src/components/fab-button/fab-button.vars.scss @@ -11,3 +11,6 @@ $fab-small-size: 40px !default; /// @prop - Border radius of the FAB button $fab-border-radius: 50% !default; + +/// @prop - Margin applied to the small FAB button +$fab-button-small-margin: 8px !default; diff --git a/core/src/components/fab-list/fab-list.scss b/core/src/components/fab-list/fab-list.scss index daff4a6893..5726d77751 100644 --- a/core/src/components/fab-list/fab-list.scss +++ b/core/src/components/fab-list/fab-list.scss @@ -4,7 +4,7 @@ // -------------------------------------------------- :host { - @include margin($fab-size + $fab-list-margin, 0); + @include margin(calc(100% + #{$fab-list-margin}), 0); display: none; position: absolute; @@ -13,8 +13,15 @@ flex-direction: column; align-items: center; - min-width: $fab-size; - min-height: $fab-size; + /** + * The list should be centered relative to the parent + * FAB button. We set minimum dimensions so the + * FAB list can be centered relative to the small FAB button. + * However, the small FAB button adds start/end margin, so we need + * to account for that in the FAB list dimensions. + */ + min-width: $fab-small-size + ($fab-button-small-margin * 2); + min-height: $fab-small-size + ($fab-button-small-margin * 2); } :host(.fab-list-active) { @@ -59,14 +66,14 @@ } :host(.fab-list-side-start) { - @include margin(0, $fab-size + $fab-list-margin); + @include margin(0, calc(100% + #{$fab-list-margin})); @include position-horizontal(null, 0); flex-direction: row-reverse; } :host(.fab-list-side-end) { - @include margin(0, $fab-size + $fab-list-margin); + @include margin(0, calc(100% + #{$fab-list-margin})); @include position(null, null, null, 0); flex-direction: row; diff --git a/core/src/components/fab/fab.scss b/core/src/components/fab/fab.scss index c6c24afc70..73fc4b375d 100644 --- a/core/src/components/fab/fab.scss +++ b/core/src/components/fab/fab.scss @@ -1,4 +1,5 @@ @import "./fab.vars"; +@import "../fab-list/fab-list.vars"; // Floating Action Button Container // -------------------------------------------------- @@ -6,6 +7,9 @@ :host { position: absolute; + width: fit-content; + height: fit-content; + z-index: $z-index-fixed-content; } @@ -14,8 +18,8 @@ // -------------------------------------------------- :host(.fab-horizontal-center) { - @include position(null, null, null, 50%); - @include margin-horizontal(-$fab-size * 0.5, null); + @include position(null, 0px, null, 0px); + @include margin(null, auto); } :host(.fab-horizontal-start) { @@ -38,22 +42,93 @@ top: $fab-content-margin; } +/** + * Reset the top value since edge + * styles use margin-top. + */ :host(.fab-vertical-top.fab-edge) { - top: -$fab-size * 0.5; + top: 0; } +/** + * We need to adjust the parent FAB button up by half + * its height so that half of it sits on the header. As a result, + * we target the slotted ion-fab-button instead of targeting the host. + */ +:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-button) { + margin-top: -50%; +} + +/** + * The small FAB button adds top and bottom margin. We need to account for + * that margin when we adjust the FAB button for edge styles since we + * are overriding the margin-top value below. + */ +:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-button.fab-button-small) { + margin-top: calc((-100% + $fab-button-small-margin * 2) / 2); +} + +/** + * Since we are adjusting the FAB button we also need + * to adjust the sibling ion-fab-list otherwise there will be + * a gap between the parent FAB button and the associated list. + */ +:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-start), +:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-end) { + @include margin(-50%, null, null, null); +} + +:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-top), +:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-bottom) { + @include margin(calc(50% + #{$fab-list-margin}) null, null, null); +} :host(.fab-vertical-bottom) { bottom: $fab-content-margin; } +/** + * Reset the bottom value since edge + * styles use margin-bottom. + */ :host(.fab-vertical-bottom.fab-edge) { - bottom: -$fab-size * 0.5; + bottom: 0; } +/** + * We need to adjust the parent FAB button down by half + * its height so that half of it sits on the footer. As a result, + * we target the slotted ion-fab-button instead of targeting the host. + */ +:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-button) { + margin-bottom: -50%; +} + +/** + * The small FAB button adds top and bottom margin. We need to account for + * that margin when we adjust the FAB button for edge styles since we + * are overriding the margin-bottom value below. + */ +:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-button.fab-button-small) { + margin-bottom: calc((-100% + $fab-button-small-margin * 2) / 2); +} + +/** + * Since we are adjusting the FAB button we also need + * to adjust the sibling ion-fab-list otherwise there will be + * a gap between the parent FAB button and the associated list. + */ +:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-start), +:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-end) { + @include margin(null, null, -50%, null); +} + +:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-top), +:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-bottom) { + @include margin(null, null, calc(50% + #{$fab-list-margin}) null); +} :host(.fab-vertical-center) { - @include margin(-$fab-size * 0.5, null, null, null); - - top: 50%; + @include position(0px, null, 0px, null); + @include margin(auto, null); } diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts b/core/src/components/fab/test/custom-size/fab.e2e.ts new file mode 100644 index 0000000000..1a73994463 --- /dev/null +++ b/core/src/components/fab/test/custom-size/fab.e2e.ts @@ -0,0 +1,17 @@ +import { expect } from '@playwright/test'; +import { configs, test, Viewports } from '@utils/test/playwright'; + +/** + * This behavior does not vary across modes + */ +configs({ modes: ['ios'] }).forEach(({ title, config, screenshot }) => { + test.describe(title('fab: custom size'), () => { + test('should position fabs correctly with custom sizes', async ({ page }) => { + await page.goto(`/src/components/fab/test/custom-size`, config); + + await page.setViewportSize(Viewports.tablet.landscape); + + await expect(page).toHaveScreenshot(screenshot(`fab-custom-size`)); + }); + }); +}); diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..2c259946ef Binary files /dev/null and b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..3999c543b5 Binary files /dev/null and b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Safari-linux.png b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Safari-linux.png new file mode 100644 index 0000000000..8d770f8358 Binary files /dev/null and b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..2c259946ef Binary files /dev/null and b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Chrome-linux.png differ diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..95c09da789 Binary files /dev/null and b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Firefox-linux.png differ diff --git a/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Safari-linux.png b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Safari-linux.png new file mode 100644 index 0000000000..8d770f8358 Binary files /dev/null and b/core/src/components/fab/test/custom-size/fab.e2e.ts-snapshots/fab-custom-size-ios-rtl-Mobile-Safari-linux.png differ diff --git a/core/src/components/fab/test/custom-size/index.html b/core/src/components/fab/test/custom-size/index.html new file mode 100644 index 0000000000..eb2e0b9d25 --- /dev/null +++ b/core/src/components/fab/test/custom-size/index.html @@ -0,0 +1,241 @@ + + +
+ +