feat(badge): add icon sizes for ionic theme (#30203)

Issue number: internal

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
Icons inside badges don't have any specific styling.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
According to the design, for the ionic theme, the size of icons inside
badges have specific values. To accommodate those:
- Added new rules for the badge sizes
- Adding a new testing page and screenshot tests

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
This commit is contained in:
Marta Carlos
2025-02-25 15:56:35 +00:00
committed by GitHub
parent d73faf5962
commit a31495091f
56 changed files with 289 additions and 0 deletions

View File

@@ -60,6 +60,11 @@
line-height: globals.$ion-font-line-height-400;
}
:host(.badge-xxsmall) ::slotted(ion-icon) {
width: globals.$ion-scale-300;
height: globals.$ion-scale-300;
}
/* Extra Small Badge */
:host(.badge-xsmall) {
--padding-start: #{globals.$ion-space-100};
@@ -73,6 +78,11 @@
line-height: globals.$ion-font-line-height-600;
}
:host(.badge-xsmall) ::slotted(ion-icon) {
width: globals.$ion-scale-400;
height: globals.$ion-scale-400;
}
/* Small Badge */
:host(.badge-small) {
--padding-start: #{globals.$ion-space-100};
@@ -86,6 +96,11 @@
line-height: globals.$ion-font-line-height-600;
}
:host(.badge-small) ::slotted(ion-icon) {
width: globals.$ion-scale-500;
height: globals.$ion-scale-500;
}
/* Medium Badge */
:host(.badge-medium) {
min-width: globals.$ion-scale-1000;
@@ -96,6 +111,11 @@
line-height: globals.$ion-font-line-height-700;
}
:host(.badge-medium) ::slotted(ion-icon) {
width: globals.$ion-scale-600;
height: globals.$ion-scale-600;
}
/* Large Badge */
:host(.badge-large) {
min-width: globals.$ion-scale-1200;
@@ -106,6 +126,11 @@
line-height: globals.$ion-font-line-height-700;
}
:host(.badge-large) ::slotted(ion-icon) {
width: globals.$ion-scale-800;
height: globals.$ion-scale-800;
}
/* Extra Large Badge */
:host(.badge-xlarge) {
min-width: globals.$ion-scale-1400;
@@ -115,3 +140,8 @@
line-height: globals.$ion-font-line-height-700;
}
:host(.badge-xlarge) ::slotted(ion-icon) {
width: globals.$ion-scale-1000;
height: globals.$ion-scale-1000;
}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -30,42 +30,72 @@
<ion-item>
<ion-label>Default Badge</ion-label>
<ion-badge slot="end">00</ion-badge>
<ion-badge slot="end">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Primary Badge</ion-label>
<ion-badge slot="end" color="primary">11</ion-badge>
<ion-badge slot="end" color="primary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Secondary Badge</ion-label>
<ion-badge slot="end" color="secondary">22</ion-badge>
<ion-badge slot="end" color="secondary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Tertiary Badge</ion-label>
<ion-badge slot="end" color="tertiary">33</ion-badge>
<ion-badge slot="end" color="tertiary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Success Badge</ion-label>
<ion-badge slot="end" color="success">44</ion-badge>
<ion-badge slot="end" color="success">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Warning Badge</ion-label>
<ion-badge slot="end" color="warning">55</ion-badge>
<ion-badge slot="end" color="warning">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Danger Badge</ion-label>
<ion-badge slot="end" color="danger">66</ion-badge>
<ion-badge slot="end" color="danger">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Light Badge</ion-label>
<ion-badge slot="end" color="light">77</ion-badge>
<ion-badge slot="end" color="light">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Medium Badge</ion-label>
<ion-badge slot="end" color="medium">88</ion-badge>
<ion-badge slot="end" color="medium">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Dark Badge</ion-label>
<ion-badge slot="end" color="dark">99</ion-badge>
<ion-badge slot="end" color="dark">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item onclick="toggleColor()">
<ion-badge id="toggleColor" slot="end" color="primary">primary</ion-badge>
@@ -80,42 +110,72 @@
<ion-item>
<ion-label>Default Badge</ion-label>
<ion-badge slot="start">00</ion-badge>
<ion-badge slot="start" color="primary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Primary Badge</ion-label>
<ion-badge slot="start" color="primary">11</ion-badge>
<ion-badge slot="start" color="primary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Secondary Badge</ion-label>
<ion-badge slot="start" color="secondary">22</ion-badge>
<ion-badge slot="start" color="secondary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Tertiary Badge</ion-label>
<ion-badge slot="start" color="tertiary">33</ion-badge>
<ion-badge slot="start" color="tertiary">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Success Badge</ion-label>
<ion-badge slot="start" color="success">44</ion-badge>
<ion-badge slot="start" color="success">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Warning Badge</ion-label>
<ion-badge slot="start" color="warning">55</ion-badge>
<ion-badge slot="start" color="warning">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Danger Badge</ion-label>
<ion-badge slot="start" color="danger">66</ion-badge>
<ion-badge slot="start" color="danger">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Light Badge</ion-label>
<ion-badge slot="start" color="light">77</ion-badge>
<ion-badge slot="start" color="light">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Medium Badge</ion-label>
<ion-badge slot="start" color="medium">88</ion-badge>
<ion-badge slot="start" color="medium">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Dark Badge</ion-label>
<ion-badge slot="start" color="dark">99</ion-badge>
<ion-badge slot="start" color="dark">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
</ion-list>
</ion-content>

View File

@@ -40,6 +40,29 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-smaller-sizes-long-text`));
});
test('should render soft badges with icon for smaller sizes', async ({ page }) => {
await page.setContent(
`
<div id="container">
<ion-badge shape="soft" size="xxsmall">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
<ion-badge shape="soft" size="xsmall">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
<ion-badge shape="soft" size="small">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-smaller-sizes-icon`));
});
test('should render soft badges for larger sizes', async ({ page }) => {
await page.setContent(
`
@@ -74,6 +97,29 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-larger-sizes-long-text`));
});
test('should render soft badges with icon for lager sizes', async ({ page }) => {
await page.setContent(
`
<div id="container">
<ion-badge shape="soft" size="medium">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
<ion-badge shape="soft" size="large">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
<ion-badge shape="soft" size="xlarge">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot(`badge-shape-soft-larger-sizes-icon`));
});
test('should render round badges', async ({ page }) => {
await page.setContent(
`
@@ -100,6 +146,21 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-shape-round-long-text`));
});
test('should render round badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge shape="round">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-shape-round-icon`));
});
test('should render rectangular badges', async ({ page }) => {
await page.setContent(
`
@@ -125,5 +186,20 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-shape-rectangular-long-text`));
});
test('should render rectangular badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge shape="rectangular">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-shape-rectangular-icon`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1013 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -28,21 +28,33 @@
<ion-label>Default</ion-label>
<ion-badge slot="end">1</ion-badge>
<ion-badge slot="end">99+</ion-badge>
<ion-badge slot="end">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Soft</ion-label>
<ion-badge slot="end" shape="soft">1</ion-badge>
<ion-badge slot="end" shape="soft">99+</ion-badge>
<ion-badge slot="end" shape="soft">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Round</ion-label>
<ion-badge slot="end" shape="round">1</ion-badge>
<ion-badge slot="end" shape="round">99+</ion-badge>
<ion-badge slot="end" shape="round">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Rectangular</ion-label>
<ion-badge slot="end" shape="rectangular">1</ion-badge>
<ion-badge slot="end" shape="rectangular">99+</ion-badge>
<ion-badge slot="end" shape="rectangular">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
</ion-list>
</ion-content>

View File

@@ -32,6 +32,21 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-size-xxsmall-long-text`));
});
test('should render xxsmall badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge size="xxsmall">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-size-xxsmall-icon`));
});
test('should render xsmall badges', async ({ page }) => {
await page.setContent(
`
@@ -58,6 +73,21 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-size-xsmall-long-text`));
});
test('should render xsmall badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge size="xsmall">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-size-xsmall-icon`));
});
test('should render small badges', async ({ page }) => {
await page.setContent(
`
@@ -84,6 +114,21 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-size-small-long-text`));
});
test('should render small badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge size="small">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-size-small-icon`));
});
test('should render medium badges', async ({ page }) => {
await page.setContent(
`
@@ -110,6 +155,21 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-size-medium-long-text`));
});
test('should render medium badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge size="medium">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-size-medium-icon`));
});
test('should render large badges', async ({ page }) => {
await page.setContent(
`
@@ -136,6 +196,21 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-size-large-long-text`));
});
test('should render large badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge size="large">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-size-large-icon`));
});
test('should render xlarge badges', async ({ page }) => {
await page.setContent(
`
@@ -161,5 +236,20 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
await expect(badge).toHaveScreenshot(screenshot(`badge-size-xlarge-long-text`));
});
test('should render xlarge badges with icon', async ({ page }) => {
await page.setContent(
`
<ion-badge size="xlarge">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-size-xlarge-icon`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

After

Width:  |  Height:  |  Size: 410 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 B

After

Width:  |  Height:  |  Size: 422 B

View File

@@ -28,36 +28,57 @@
<ion-label>Default</ion-label>
<ion-badge slot="end">1</ion-badge>
<ion-badge slot="end">99+</ion-badge>
<ion-badge slot="end">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>XXSmall</ion-label>
<ion-badge slot="end" size="xxsmall">1</ion-badge>
<ion-badge slot="end" size="xxsmall">99+</ion-badge>
<ion-badge slot="end" size="xxsmall">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>XSmall</ion-label>
<ion-badge slot="end" size="xsmall">1</ion-badge>
<ion-badge slot="end" size="xsmall">99+</ion-badge>
<ion-badge slot="end" size="xsmall">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Small</ion-label>
<ion-badge slot="end" size="small">1</ion-badge>
<ion-badge slot="end" size="small">99+</ion-badge>
<ion-badge slot="end" size="small">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Medium</ion-label>
<ion-badge slot="end" size="medium">1</ion-badge>
<ion-badge slot="end" size="medium">99+</ion-badge>
<ion-badge slot="end" size="medium">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>Large</ion-label>
<ion-badge slot="end" size="large">1</ion-badge>
<ion-badge slot="end" size="large">99+</ion-badge>
<ion-badge slot="end" size="large">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
<ion-item>
<ion-label>XLarge</ion-label>
<ion-badge slot="end" size="xlarge">1</ion-badge>
<ion-badge slot="end" size="xlarge">99+</ion-badge>
<ion-badge slot="end" size="xlarge">
<ion-icon name="logo-ionic"></ion-icon>
</ion-badge>
</ion-item>
</ion-list>
</ion-content>