Skip to content

Commit

Permalink
feat(button): add circular shape as round (#29161)
Browse files Browse the repository at this point in the history
Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 21, 2024
1 parent 500854d commit 44529f0
Show file tree
Hide file tree
Showing 145 changed files with 288 additions and 59 deletions.
47 changes: 41 additions & 6 deletions core/src/components/button/button.ios.scss
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,6 @@
font-size: #{$button-ios-small-font-size};
}

:host(.button-has-icon-only) {
--padding-top: 0;
--padding-bottom: 0;
}


// iOS Round Button
// --------------------------------------------------
Expand All @@ -131,14 +126,54 @@
--padding-bottom: #{$button-ios-round-padding-bottom};
}


// iOS Strong Button
// --------------------------------------------------

:host(.button-strong) {
font-weight: #{$button-ios-strong-font-weight};
}

// iOS Icon Only Button
// --------------------------------------------------

:host(.button-has-icon-only) {
--padding-top: 0;
--padding-bottom: var(--padding-top);
--padding-end: var(--padding-top);
--padding-start: var(--padding-end);
// TODO(FW-6053): replace em value with the min-height variable.
min-width: clamp(30px, 2.125em, 60px);

// TODO(FW-6053): replace em value with the min-height variable.
min-height: clamp(30px, 2.125em, 60px);
}

::slotted(ion-icon[slot="icon-only"]) {
font-size: 1.125em;
}

:host(.button-small.button-has-icon-only) {
// TODO(FW-6053): replace em value with the min-height variable.
min-width: clamp(23px, 2.16em, 54px);
// TODO(FW-6053): replace em value with the min-height variable.
min-height: clamp(23px, 2.16em, 54px);

}

:host(.button-small) ::slotted(ion-icon[slot="icon-only"]) {
font-size: 1.4em;
}

:host(.button-large.button-has-icon-only) {
// TODO(FW-6053): replace em value with the min-height variable.
min-width: clamp(46px, 2.5em, 78px);
// TODO(FW-6053): replace em value with the min-height variable.
min-height: clamp(46px, 2.5em, 78px);
}

:host(.button-large) ::slotted(ion-icon[slot="icon-only"]) {
font-size: 1em;
}

// iOS Button Focused
// --------------------------------------------------
Expand Down
50 changes: 43 additions & 7 deletions core/src/components/button/button.md.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,23 +113,59 @@
font-size: #{$button-md-small-font-size};
}

:host(.button-has-icon-only) {
--padding-top: 0;
--padding-bottom: 0;
}


// MD strong Button
// --------------------------------------------------

:host(.button-strong) {
font-weight: #{$button-md-strong-font-weight};
}

// MD Icon Only Button
//
// MD does not specify a small size, these
// styles are based on the iOS small size.
//
// MD does not specify a large size, these
// styles are based on the iOS large size.
// --------------------------------------------------

:host(.button-has-icon-only) {
--padding-top: 0;
--padding-bottom: var(--padding-top);
--padding-end: var(--padding-top);
--padding-start: var(--padding-end);
// TODO(FW-6053): replace em value with the min-height variable.
min-width: clamp(30px, 2.86em, 60px);

// TODO(FW-6053): replace em value with the min-height variable.
min-height: clamp(30px, 2.86em, 60px);
}

::slotted(ion-icon[slot="icon-only"]) {
@include padding(0);
font-size: 1.6em;
}

:host(.button-small.button-has-icon-only) {
// TODO(FW-6053): replace em value with the min-height variable.
min-width: clamp(23px, 2.16em, 54px);
// TODO(FW-6053): replace em value with the min-height variable.
min-height: clamp(23px, 2.16em, 54px);
}

:host(.button-small) ::slotted(ion-icon[slot="icon-only"]) {
font-size: 1.23em;
}

:host(.button-large.button-has-icon-only) {
// TODO(FW-6053): replace em value with the min-height variable.
min-width: clamp(46px, 2.5em, 78px);
// TODO(FW-6053): replace em value with the min-height variable.
min-height: clamp(46px, 2.5em, 78px);
}

:host(.button-large) ::slotted(ion-icon[slot="icon-only"]) {
font-size: 1.4em;
}

// Material Design Button: Hover
// --------------------------------------------------
Expand Down
5 changes: 0 additions & 5 deletions core/src/components/button/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,6 @@
@include margin(0, -0.2em, 0, 0.3em);
}

::slotted(ion-icon[slot="icon-only"]) {
font-size: 1.8em;
}


// Button Ripple effect
// --------------------------------------------------

Expand Down
21 changes: 19 additions & 2 deletions core/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Component, Element, Event, Host, Prop, Watch, h } from '@stencil/core';
import { Component, Element, Event, Host, Prop, Watch, State, h } from '@stencil/core';
import type { AnchorInterface, ButtonInterface } from '@utils/element-interface';
import type { Attributes } from '@utils/helpers';
import { inheritAriaAttributes, hasShadowDom } from '@utils/helpers';
Expand Down Expand Up @@ -38,6 +38,11 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf

@Element() el!: HTMLElement;

/**
* If `true`, the button only has an icon.
*/
@State() isCircle: boolean = false;

/**
* The color to use from your application's color palette.
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
Expand Down Expand Up @@ -295,6 +300,18 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
this.ionBlur.emit();
};

private slotChanged = () => {
/**
* Ensures that the 'has-icon-only' class is properly added
* or removed from `ion-button` when manipulating the
* `icon-only` slot.
*
* Without this, the 'has-icon-only' class is only checked
* or added when `ion-button` component first renders.
*/
this.isCircle = this.hasIconOnly;
};

render() {
const mode = getIonMode(this);
const {
Expand Down Expand Up @@ -374,7 +391,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
{...inheritedAttributes}
>
<span class="button-inner">
<slot name="icon-only"></slot>
<slot name="icon-only" onSlotchange={this.slotChanged}></slot>
<slot name="start"></slot>
<slot></slot>
<slot name="end"></slot>
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/button/button.vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ $button-round-padding-bottom: $button-round-padding-top !default;
$button-round-padding-start: $button-round-padding-end !default;

/// @prop - Border radius of the round button
$button-round-border-radius: 64px !default;
$button-round-border-radius: 999px !default;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 56 additions & 4 deletions core/src/components/button/test/round/button.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,64 @@ import { configs, test } from '@utils/test/playwright';
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: round'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/round`, config);
test.describe('default', () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/round`, config);

await page.setIonViewport();
await page.setIonViewport();

await expect(page).toHaveScreenshot(screenshot(`button-round`));
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`));
});
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 44529f0

Please sign in to comment.