Skip to content

Commit c5fb051

Browse files
authored
feat(tab-button): support new badge hint features (#30246)
Issue number: internal ## What is the current behavior? - tab-button with badge only supports status badges (small circle with specific color), missing cases with text or icon. ## What is the new behavior? - Added css on tab-button to support new badge hint functionalities such text and icon - Added css on badge to support the existence of a icon inside it - Added support on ionic theme for different position (top and button) - Added badge test case for this use case - There's no figma for md/iOS implementation, so just added for now a best effort on how it looks. **Theme md:** <img width="418" alt="md" src="https://github.com/user-attachments/assets/0281b616-12aa-4107-bf4c-e8fdbe72d7d3" /> **Theme iOS:** <img width="417" alt="ios" src="https://github.com/user-attachments/assets/6102d874-b608-4527-91fb-4ed8b7e536a0" /> **Theme ionic:** <img width="418" alt="ionic" src="https://github.com/user-attachments/assets/10f59d57-0c30-4f04-bbe8-de625b93eb46" /> ### Notes: - All the styles added are based on the [vertical] attribute in order to prevent breaking changes and only affect the badge hint with the new features implemented. - Also top and bottom position under the context of md/iOS themes are not exactly the same as ionic theme due the usage of an `overflow:hidden;` attribute at the `.button-native` context. This `overflow:hidden;` attribute has been overwritten to `overflow:visible;` for ionic theme. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information [Sample](https://ionic-framework-git-rou-11666-ionic1.vercel.app/src/components/badge/test/hint)
1 parent a7233c2 commit c5fb051

File tree

45 files changed

+403
-9
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+403
-9
lines changed

core/src/components/badge/badge.common.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@
5151
// Badge Empty (hint)
5252
// --------------------------------------------------
5353

54-
:host([vertical]) {
54+
:host([vertical]:not(.in-tab-button)) {
5555
@include position(null, 0, null, null);
5656
position: absolute;
5757
}
5858

59-
:host(:empty.badge-vertical-top) {
59+
:host(:not(.in-tab-button):empty.badge-vertical-top) {
6060
top: 0;
6161
}
6262

63-
:host(:empty.badge-vertical-bottom) {
63+
:host(:not(.in-tab-button):empty.badge-vertical-bottom) {
6464
bottom: 0;
6565
}

core/src/components/badge/badge.ionic.scss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,19 @@
174174
min-width: globals.$ion-scale-400;
175175
height: globals.$ion-scale-400;
176176
}
177+
178+
// Badge Inside Tab Button
179+
// --------------------------------------------------
180+
181+
:host([vertical].in-tab-button) {
182+
position: relative;
183+
}
184+
185+
// Badge Icon when Inside Tab Button
186+
:host([vertical].in-tab-button) ::slotted(ion-icon) {
187+
@include globals.position(50%, null, null, 50%);
188+
189+
position: absolute;
190+
191+
transform: translate(-50%, -50%);
192+
}

core/src/components/badge/badge.ios.scss

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,23 @@
1616
*/
1717
font-size: dynamic-font-min(1, $badge-baseline-font-size);
1818
}
19+
20+
// Badge Inside Tab Button
21+
// --------------------------------------------------
22+
23+
:host([vertical].in-tab-button) {
24+
position: relative;
25+
26+
min-width: $badge-ios-in-tab-button-min-width;
27+
}
28+
29+
:host([vertical].in-tab-button) ::slotted(ion-icon) {
30+
@include position(50%, null, null, 50%);
31+
32+
position: absolute;
33+
34+
width: $badge-ios-in-tab-button-icon-size;
35+
height: $badge-ios-in-tab-button-icon-size;
36+
37+
transform: translate(-50%, -50%);
38+
}

core/src/components/badge/badge.ios.vars.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,15 @@
55

66
/// @prop - Border radius of the badge
77
$badge-ios-border-radius: 10px;
8+
9+
// Badge inside a Tab Button
10+
// --------------------------------------------------
11+
12+
/// @prop - Minimum width of the badge inside a Tab Button
13+
$badge-ios-in-tab-button-min-width: 8px;
14+
15+
/// @prop - Height of the badge inside a Tab Button
16+
$badge-ios-in-tab-button-height: 8px;
17+
18+
/// @prop - Badge icon size inside a Tab Button
19+
$badge-ios-in-tab-button-icon-size: 12px;

core/src/components/badge/badge.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ComponentInterface } from '@stencil/core';
2-
import { Component, Host, Prop, h } from '@stencil/core';
3-
import { createColorClasses } from '@utils/theme';
2+
import { Component, Element, Host, Prop, h } from '@stencil/core';
3+
import { createColorClasses, hostContext } from '@utils/theme';
44

55
import { getIonTheme } from '../../global/ionic-global';
66
import type { Color } from '../../interface';
@@ -19,6 +19,8 @@ import type { Color } from '../../interface';
1919
shadow: true,
2020
})
2121
export class Badge implements ComponentInterface {
22+
@Element() el!: HTMLElement;
23+
2224
/**
2325
* The color to use from your application's color palette.
2426
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
@@ -89,13 +91,15 @@ export class Badge implements ComponentInterface {
8991
const shape = this.getShape();
9092
const size = this.getSize();
9193
const theme = getIonTheme(this);
94+
9295
return (
9396
<Host
9497
class={createColorClasses(this.color, {
9598
[theme]: true,
9699
[`badge-${shape}`]: shape !== undefined,
97100
[`badge-${size}`]: size !== undefined,
98101
[`badge-vertical-${this.vertical}`]: this.vertical !== undefined,
102+
'in-tab-button': hostContext('ion-tab-button', this.el),
99103
})}
100104
>
101105
<slot></slot>

core/src/components/badge/test/hint/badge.e2e.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,22 @@ configs({ directions: ['ltr'], modes: ['md', 'ios', 'ionic-md'] }).forEach(({ co
2121
await expect(container).toHaveScreenshot(screenshot(`badge-hint-avatar`));
2222
});
2323
});
24+
25+
test.describe(title('badge: hint inside tab button'), () => {
26+
test('should not have visual regressions when icon is on the top', async ({ page }) => {
27+
await page.goto('/src/components/badge/test/hint', config);
28+
29+
const container = page.locator('#tab-button');
30+
31+
await expect(container).toHaveScreenshot(screenshot(`badge-hint-tab-button-icon-top`));
32+
});
33+
34+
test('should not have visual regressions when icon is at the bottom', async ({ page }) => {
35+
await page.goto('/src/components/badge/test/hint', config);
36+
37+
const container = page.locator('#tab-button-icon-bottom');
38+
39+
await expect(container).toHaveScreenshot(screenshot(`badge-hint-tab-button-icon-bottom`));
40+
});
41+
});
2442
});
137 Bytes
Loading
1.2 KB
Loading
7 Bytes
Loading
Loading

0 commit comments

Comments
 (0)