diff --git a/core/api.txt b/core/api.txt index 0b514e6580..d86d9002b1 100644 --- a/core/api.txt +++ b/core/api.txt @@ -310,6 +310,7 @@ ion-backdrop,event,ionBackdropTap,void,true ion-badge,shadow ion-badge,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true ion-badge,prop,mode,"ios" | "md",undefined,false,false +ion-badge,prop,size,"small" | undefined,undefined,false,false ion-badge,prop,theme,"ios" | "md" | "ionic",undefined,false,false ion-badge,css-prop,--background,ionic ion-badge,css-prop,--background,ios diff --git a/core/src/components.d.ts b/core/src/components.d.ts index d9802a3b7c..517586ff27 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -409,6 +409,10 @@ export namespace Components { * The mode determines the platform behaviors of the component. */ "mode"?: "ios" | "md"; + /** + * Set to `"small"` for less height and width. Defaults to `"small"` for the `ionic` theme, undefined for all other themes. + */ + "size"?: 'small'; /** * The theme determines the visual appearance of the component. */ @@ -5637,6 +5641,10 @@ declare namespace LocalJSX { * The mode determines the platform behaviors of the component. */ "mode"?: "ios" | "md"; + /** + * Set to `"small"` for less height and width. Defaults to `"small"` for the `ionic` theme, undefined for all other themes. + */ + "size"?: 'small'; /** * The theme determines the visual appearance of the component. */ diff --git a/core/src/components/badge/badge.ionic.scss b/core/src/components/badge/badge.ionic.scss new file mode 100644 index 0000000000..b6a583e9d4 --- /dev/null +++ b/core/src/components/badge/badge.ionic.scss @@ -0,0 +1,32 @@ +@use "../../themes/ionic/ionic.globals.scss" as globals; +@import "./badge"; + +// Ionic Badge +// -------------------------------------------------- + +:host { + --padding-start: #{globals.$ionic-space-100}; + --padding-end: #{globals.$ionic-space-100}; + --padding-top: #{globals.$ionic-space-0}; + --padding-bottom: #{globals.$ionic-space-0}; + + display: inline-flex; + + align-items: center; + justify-content: center; + + font-weight: globals.$ionic-font-weight-medium; +} + +// Badge Sizes +// -------------------------------------------------- + +/* Small Badge */ +:host(.badge-small) { + min-width: globals.$ionic-scale-800; + height: globals.$ionic-scale-800; + + font-size: globals.$ionic-font-size-400; + + line-height: globals.$ionic-line-height-600; +} diff --git a/core/src/components/badge/badge.tsx b/core/src/components/badge/badge.tsx index 46dbd5a165..59da1fbd13 100644 --- a/core/src/components/badge/badge.tsx +++ b/core/src/components/badge/badge.tsx @@ -14,7 +14,7 @@ import type { Color } from '../../interface'; styleUrls: { ios: 'badge.ios.scss', md: 'badge.md.scss', - ionic: 'badge.md.scss', + ionic: 'badge.ionic.scss', }, shadow: true, }) @@ -26,12 +26,36 @@ export class Badge implements ComponentInterface { */ @Prop({ reflect: true }) color?: Color; + /** + * Set to `"small"` for less height and width. + * Defaults to `"small"` for the `ionic` theme, undefined for all other themes. + */ + @Prop() size?: 'small'; + + private getSize(): string | undefined { + const theme = getIonTheme(this); + const { size } = this; + + // TODO(ROU-10747): Remove theme check when sizes are defined for all themes. + if (theme !== 'ionic') { + return undefined; + } + + if (size === undefined) { + return 'small'; + } + + return size; + } + render() { + const size = this.getSize(); const theme = getIonTheme(this); return ( diff --git a/core/src/components/badge/test/size/badge.e2e.ts b/core/src/components/badge/test/size/badge.e2e.ts new file mode 100644 index 0000000000..c9c8aeb6ac --- /dev/null +++ b/core/src/components/badge/test/size/badge.e2e.ts @@ -0,0 +1,22 @@ +import { expect } from '@playwright/test'; +import { configs, test } from '@utils/test/playwright'; + +/** + * This behavior does not vary across directions. + */ +configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screenshot, title }) => { + test.describe(title('badge: size'), () => { + test('should render small badges', async ({ page }) => { + await page.setContent( + ` + 00 + `, + config + ); + + const badge = page.locator('ion-badge'); + + await expect(badge).toHaveScreenshot(screenshot(`badge-size-small`)); + }); + }); +}); diff --git a/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..9fe9cd84a5 Binary files /dev/null and b/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..030afe81e5 Binary files /dev/null and b/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..94ffc598e3 Binary files /dev/null and b/core/src/components/badge/test/size/badge.e2e.ts-snapshots/badge-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/badge/test/size/index.html b/core/src/components/badge/test/size/index.html new file mode 100644 index 0000000000..addbff82e4 --- /dev/null +++ b/core/src/components/badge/test/size/index.html @@ -0,0 +1,39 @@ + + + + + Badge - Size + + + + + + + + + + + + + Button - Size + + + + + + + Default Badge + 00 + + + Small Badge + 00 + + + + + + diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index 552e9cecbe..3cfff5d14d 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -260,14 +260,14 @@ export declare interface IonBackdrop extends Components.IonBackdrop { @ProxyCmp({ - inputs: ['color', 'mode', 'theme'] + inputs: ['color', 'mode', 'size', 'theme'] }) @Component({ selector: 'ion-badge', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'mode', 'theme'], + inputs: ['color', 'mode', 'size', 'theme'], }) export class IonBadge { protected el: HTMLElement; diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 76ae26028a..2cd74d64fe 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -344,14 +344,14 @@ export declare interface IonBackdrop extends Components.IonBackdrop { @ProxyCmp({ defineCustomElementFn: defineIonBadge, - inputs: ['color', 'mode', 'theme'] + inputs: ['color', 'mode', 'size', 'theme'] }) @Component({ selector: 'ion-badge', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'mode', 'theme'], + inputs: ['color', 'mode', 'size', 'theme'], standalone: true }) export class IonBadge { diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index b114af9f1a..391bc1ad11 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -114,7 +114,8 @@ export const IonBackdrop = /*@__PURE__*/ defineContainer('ion-b export const IonBadge = /*@__PURE__*/ defineContainer('ion-badge', defineIonBadge, [ - 'color' + 'color', + 'size' ]);