diff --git a/core/api.txt b/core/api.txt index be951f2a15..f9e01aaf3b 100644 --- a/core/api.txt +++ b/core/api.txt @@ -184,6 +184,7 @@ ion-app,prop,theme,"ios" | "md" | "ionic",undefined,false,false ion-avatar,shadow ion-avatar,prop,mode,"ios" | "md",undefined,false,false +ion-avatar,prop,size,"medium" | undefined,undefined,false,false ion-avatar,prop,theme,"ios" | "md" | "ionic",undefined,false,false ion-avatar,css-prop,--border-radius,ionic ion-avatar,css-prop,--border-radius,ios diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 59f58e668e..0b7b31f612 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -335,6 +335,10 @@ export namespace Components { * The mode determines the platform behaviors of the component. */ "mode"?: "ios" | "md"; + /** + * Set to `"medium"` for the default height and width. Defaults to `"medium"` for the `ionic` theme, undefined for all other themes. + */ + "size"?: 'medium'; /** * The theme determines the visual appearance of the component. */ @@ -5563,6 +5567,10 @@ declare namespace LocalJSX { * The mode determines the platform behaviors of the component. */ "mode"?: "ios" | "md"; + /** + * Set to `"medium"` for the default height and width. Defaults to `"medium"` for the `ionic` theme, undefined for all other themes. + */ + "size"?: 'medium'; /** * The theme determines the visual appearance of the component. */ diff --git a/core/src/components/avatar/avatar.ionic.scss b/core/src/components/avatar/avatar.ionic.scss new file mode 100644 index 0000000000..2eda3dba71 --- /dev/null +++ b/core/src/components/avatar/avatar.ionic.scss @@ -0,0 +1,38 @@ +@use "../../themes/ionic/ionic.globals.scss" as globals; +@import "./avatar"; + +// Ionic Avatar +// -------------------------------------------------- + +:host { + display: flex; + + align-items: center; + justify-content: center; + + background: globals.$ionic-color-neutral-100; + color: globals.$ionic-color-neutral-800; + + font-weight: globals.$ionic-font-weight-regular; + + line-height: globals.$ionic-line-height-600; +} + +:host(:not(.avatar-image)) { + border: globals.$ionic-border-size-025 solid globals.$ionic-color-neutral-800; +} + +// Avatar Sizes +// -------------------------------------------------- + +:host(.avatar-medium) { + --padding-top: #{globals.$ionic-space-0}; + --padding-end: #{globals.$ionic-space-200}; + --padding-bottom: #{globals.$ionic-space-0}; + --padding-start: #{globals.$ionic-space-200}; + + width: globals.$ionic-scale-1000; + height: globals.$ionic-scale-1000; + + font-size: globals.$ionic-font-size-400; +} diff --git a/core/src/components/avatar/avatar.tsx b/core/src/components/avatar/avatar.tsx index 8f8bbaf3bf..bd1134bfaf 100644 --- a/core/src/components/avatar/avatar.tsx +++ b/core/src/components/avatar/avatar.tsx @@ -1,5 +1,5 @@ import type { ComponentInterface } from '@stencil/core'; -import { Component, Host, h } from '@stencil/core'; +import { Component, Element, Host, Prop, h } from '@stencil/core'; import { getIonTheme } from '../../global/ionic-global'; @@ -12,17 +12,50 @@ import { getIonTheme } from '../../global/ionic-global'; styleUrls: { ios: 'avatar.ios.scss', md: 'avatar.md.scss', - ionic: 'avatar.md.scss', + ionic: 'avatar.ionic.scss', }, shadow: true, }) export class Avatar implements ComponentInterface { + @Element() el!: HTMLElement; + + /** + * Set to `"medium"` for the default height and width. + * + * Defaults to `"medium"` for the `ionic` theme, undefined for all other themes. + */ + @Prop() size?: 'medium'; + + get hasImage() { + return !!this.el.querySelector('ion-img') || !!this.el.querySelector('img'); + } + + private getSize(): string | undefined { + const theme = getIonTheme(this); + const { size } = this; + + // TODO(ROU-10752): Remove theme check when sizes are defined for all themes. + if (theme !== 'ionic') { + return undefined; + } + + if (size === undefined) { + return 'medium'; + } + + return size; + } + render() { const theme = getIonTheme(this); + const size = this.getSize(); + return ( diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts b/core/src/components/avatar/test/size/avatar.e2e.ts new file mode 100644 index 0000000000..3d7360f957 --- /dev/null +++ b/core/src/components/avatar/test/size/avatar.e2e.ts @@ -0,0 +1,54 @@ +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('avatar: size'), () => { + test.describe('medium', () => { + test('should not have visual regressions when containing text', async ({ page }) => { + await page.setContent( + ` + AB + `, + config + ); + + const avatar = page.locator('ion-avatar'); + + await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-medium-text`)); + }); + + test('should not have visual regressions when containing an icon', async ({ page }) => { + await page.setContent( + ` + + + + `, + config + ); + + const avatar = page.locator('ion-avatar'); + + await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-medium-icon`)); + }); + + test('should not have visual regressions when containing an image', async ({ page }) => { + await page.setContent( + ` + + + + `, + config + ); + + const avatar = page.locator('ion-avatar'); + + await expect(avatar).toHaveScreenshot(screenshot(`avatar-size-medium-image`)); + }); + }); + }); +}); diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..dfb50e7fdc Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..d3f2a5e314 Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..cdbb3cec21 Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-icon-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..771f594575 Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..a566b986a1 Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..4b80c96bab Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-image-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..841ddb2029 Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..ff8f260ae6 Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..e8849fc65a Binary files /dev/null and b/core/src/components/avatar/test/size/avatar.e2e.ts-snapshots/avatar-size-medium-text-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/avatar/test/size/index.html b/core/src/components/avatar/test/size/index.html new file mode 100644 index 0000000000..4de374675e --- /dev/null +++ b/core/src/components/avatar/test/size/index.html @@ -0,0 +1,61 @@ + + + + + Avatar - Size + + + + + + + + + + + + + + + Avatar - Size + + + + +

Text

+
+ AB + AB +
+ +

Icons

+
+ + + + + + +
+ +

Images

+
+ + + + + + +
+
+
+ + diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index 3cfff5d14d..20d8c4c3f9 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -210,14 +210,14 @@ export declare interface IonApp extends Components.IonApp {} @ProxyCmp({ - inputs: ['mode', 'theme'] + inputs: ['mode', 'size', 'theme'] }) @Component({ selector: 'ion-avatar', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['mode', 'theme'], + inputs: ['mode', 'size', 'theme'], }) export class IonAvatar { protected el: HTMLElement; diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 2cd74d64fe..2bfb4707a5 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -290,14 +290,14 @@ export declare interface IonApp extends Components.IonApp {} @ProxyCmp({ defineCustomElementFn: defineIonAvatar, - inputs: ['mode', 'theme'] + inputs: ['mode', 'size', 'theme'] }) @Component({ selector: 'ion-avatar', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['mode', 'theme'], + inputs: ['mode', 'size', 'theme'], standalone: true }) export class IonAvatar { diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 391bc1ad11..200c9bd0ab 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -102,7 +102,9 @@ export const IonAccordionGroup = /*@__PURE__*/ defineContainer('ion-avatar', defineIonAvatar); +export const IonAvatar = /*@__PURE__*/ defineContainer('ion-avatar', defineIonAvatar, [ + 'size' +]); export const IonBackdrop = /*@__PURE__*/ defineContainer('ion-backdrop', defineIonBackdrop, [