Skip to content

Commit 517d5b9

Browse files
BenOsodracIonitronOS-martacarlosbrandyscarney
authored
feat(badge): add support for hint feature (#30213)
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 new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Added new position prop. - Based on the prop, a new badge-position css class is added on the host. - Removed css rule that prevented the badge to be rendered when empty. - Added common and themes styles to support the position prop and new scale size (on ios/md defaults to min-width variable, as size is not yet supported on native themes). - Added new tests specific for this new feature and added new screenshots. - Support to properly work inside Avatar, Button and TabButton will be added on different tasks (in the meantime the snapshots will appear wrong for these use-cases) ## 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. --> - [Ionic Theme Sample](https://ionic-framework-6n0cn175k-ionic1.vercel.app/src/components/badge/test/hint?ionic:theme=ionic) - [MD Theme Sample](https://ionic-framework-6n0cn175k-ionic1.vercel.app/src/components/badge/test/hint?ionic:theme=md) - [iOS Theme Sample](https://ionic-framework-6n0cn175k-ionic1.vercel.app/src/components/badge/test/hint?ionic:theme=ios) --------- Co-authored-by: ionitron <[email protected]> Co-authored-by: Marta Carlos <[email protected]> Co-authored-by: Brandy Smith <[email protected]>
1 parent 5eab76c commit 517d5b9

File tree

53 files changed

+238
-7
lines changed

Some content is hidden

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

53 files changed

+238
-7
lines changed

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ ion-badge,prop,mode,"ios" | "md",undefined,false,false
317317
ion-badge,prop,shape,"round | rectangular" | "soft" | undefined,undefined,false,false
318318
ion-badge,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | "xxsmall" | undefined,undefined,false,false
319319
ion-badge,prop,theme,"ios" | "md" | "ionic",undefined,false,false
320+
ion-badge,prop,vertical,"bottom" | "top" | undefined,undefined,false,false
320321
ion-badge,css-prop,--background,ionic
321322
ion-badge,css-prop,--background,ios
322323
ion-badge,css-prop,--background,md

core/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,10 @@ export namespace Components {
441441
* The theme determines the visual appearance of the component.
442442
*/
443443
"theme"?: "ios" | "md" | "ionic";
444+
/**
445+
* Set to `"top"` to position the badge on top right absolute position of the parent element. Set to `"bottom"` to position the badge on bottom right absolute position of the parent element.
446+
*/
447+
"vertical"?: 'top' | 'bottom';
444448
}
445449
interface IonBreadcrumb {
446450
/**
@@ -5805,6 +5809,10 @@ declare namespace LocalJSX {
58055809
* The theme determines the visual appearance of the component.
58065810
*/
58075811
"theme"?: "ios" | "md" | "ionic";
5812+
/**
5813+
* Set to `"top"` to position the badge on top right absolute position of the parent element. Set to `"bottom"` to position the badge on bottom right absolute position of the parent element.
5814+
*/
5815+
"vertical"?: 'top' | 'bottom';
58085816
}
58095817
interface IonBreadcrumb {
58105818
/**

core/src/components/avatar/avatar.common.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
@include border-radius(var(--border-radius));
1111

1212
display: block;
13+
14+
position: relative;
1315
}
1416

1517
::slotted(ion-img),

core/src/components/avatar/avatar.ionic.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,22 @@
152152
width: globals.$ion-scale-1000;
153153
height: globals.$ion-scale-1000;
154154
}
155+
156+
// Avatar Empty Badge (hint)
157+
// --------------------------------------------------
158+
159+
:host(.avatar-xxsmall) ::slotted(ion-badge.badge-vertical-top:empty) {
160+
transform: translate(globals.$ion-scale-100, calc(globals.$ion-scale-100 * -1));
161+
}
162+
163+
:host(:not(.avatar-xxsmall)) ::slotted(ion-badge.badge-vertical-top:empty) {
164+
transform: translate(globals.$ion-scale-050, calc(globals.$ion-scale-050 * -1));
165+
}
166+
167+
:host(.avatar-xxsmall) ::slotted(ion-badge.badge-vertical-bottom:empty) {
168+
transform: translate(globals.$ion-scale-100, calc(globals.$ion-scale-100));
169+
}
170+
171+
:host(:not(.avatar-xxsmall)) ::slotted(ion-badge.badge-vertical-bottom:empty) {
172+
transform: translate(0, globals.$ion-scale-100);
173+
}

core/src/components/avatar/avatar.md.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,14 @@
1010
width: $avatar-md-width;
1111
height: $avatar-md-height;
1212
}
13+
14+
// Avatar Empty Badge (hint)
15+
// --------------------------------------------------
16+
17+
::slotted(ion-badge.badge-vertical-top:empty) {
18+
transform: translate(-50%, 50%);
19+
}
20+
21+
::slotted(ion-badge.badge-vertical-bottom:empty) {
22+
transform: translateX(-100%);
23+
}

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@
4848
color: #{color.current-color(contrast)};
4949
}
5050

51-
:host(:empty) {
52-
display: none;
51+
// Badge Empty (hint)
52+
// --------------------------------------------------
53+
54+
:host([vertical]) {
55+
@include position(null, 0, null, null);
56+
position: absolute;
57+
}
58+
59+
:host(:empty.badge-vertical-top) {
60+
top: 0;
61+
}
62+
63+
:host(:empty.badge-vertical-bottom) {
64+
bottom: 0;
5365
}

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,32 @@
145145
width: globals.$ion-scale-1000;
146146
height: globals.$ion-scale-1000;
147147
}
148+
149+
// Badge Empty
150+
// --------------------------------------------------
151+
152+
:host(:empty) {
153+
--padding-start: 0;
154+
--padding-end: 0;
155+
}
156+
157+
// Badge Sizes Empty
158+
// --------------------------------------------------
159+
160+
/* sm */
161+
:host(.badge-small:empty) {
162+
min-width: globals.$ion-scale-200;
163+
height: globals.$ion-scale-200;
164+
}
165+
166+
/* md */
167+
:host(.badge-medium:empty) {
168+
min-width: globals.$ion-scale-300;
169+
height: globals.$ion-scale-300;
170+
}
171+
172+
/* lg */
173+
:host(.badge-large:empty) {
174+
min-width: globals.$ion-scale-400;
175+
height: globals.$ion-scale-400;
176+
}

core/src/components/badge/badge.native.scss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,16 @@
1111

1212
font-family: $font-family-base;
1313
}
14+
15+
// TODO(ROU-10747): Review size styles when sizes are defined for native themes.
16+
:host(:empty) {
17+
--padding-start: 0;
18+
--padding-end: 0;
19+
--padding-bottom: 0;
20+
--padding-top: 0;
21+
22+
@include border-radius(999px);
23+
24+
width: $badge-min-width;
25+
height: $badge-min-width;
26+
}

core/src/components/badge/badge.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ export class Badge implements ComponentInterface {
4747
*/
4848
@Prop() size?: 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
4949

50+
/**
51+
* Set to `"top"` to position the badge on top right absolute position of the parent element.
52+
* Set to `"bottom"` to position the badge on bottom right absolute position of the parent element.
53+
*/
54+
@Prop() vertical?: 'top' | 'bottom';
55+
5056
private getShape(): string | undefined {
5157
const theme = getIonTheme(this);
5258
const { shape } = this;
@@ -89,6 +95,7 @@ export class Badge implements ComponentInterface {
8995
[theme]: true,
9096
[`badge-${shape}`]: shape !== undefined,
9197
[`badge-${size}`]: size !== undefined,
98+
[`badge-vertical-${this.vertical}`]: this.vertical !== undefined,
9299
})}
93100
>
94101
<slot></slot>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
configs({ directions: ['ltr'], modes: ['md', 'ios', 'ionic-md'] }).forEach(({ config, screenshot, title }) => {
5+
test.describe(title('badge: hint empty'), () => {
6+
test('should not have visual regressions', async ({ page }) => {
7+
await page.goto('/src/components/badge/test/hint', config);
8+
9+
const container = page.locator('#empty');
10+
11+
await expect(container).toHaveScreenshot(screenshot(`badge-hint-empty`));
12+
});
13+
});
14+
15+
test.describe(title('badge: hint inside avatar'), () => {
16+
test('should not have visual regressions', async ({ page }) => {
17+
await page.goto('/src/components/badge/test/hint', config);
18+
19+
const container = page.locator('#avatar');
20+
21+
await expect(container).toHaveScreenshot(screenshot(`badge-hint-avatar`));
22+
});
23+
});
24+
});

0 commit comments

Comments
 (0)