diff --git a/core/api.txt b/core/api.txt index caccbf316f..f956418247 100644 --- a/core/api.txt +++ b/core/api.txt @@ -2118,8 +2118,11 @@ ion-spinner,prop,duration,number | undefined,undefined,false,false ion-spinner,prop,mode,"ios" | "md",undefined,false,false ion-spinner,prop,name,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-sharp" | "lines-sharp-small" | "lines-small" | undefined,undefined,false,false ion-spinner,prop,paused,boolean,false,false,false +ion-spinner,prop,size,"large" | "medium" | "small" | "xlarge" | "xsmall" | undefined,undefined,false,false ion-spinner,prop,theme,"ios" | "md" | "ionic",undefined,false,false -ion-spinner,css-prop,--color +ion-spinner,css-prop,--color,ionic +ion-spinner,css-prop,--color,ios +ion-spinner,css-prop,--color,md ion-split-pane,shadow ion-split-pane,prop,contentId,string | undefined,undefined,false,true diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 1ab52a238e..057be08e40 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -3346,6 +3346,10 @@ export namespace Components { * If `true`, the spinner's animation will be paused. */ "paused": boolean; + /** + * Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes. + */ + "size"?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; /** * The theme determines the visual appearance of the component. */ @@ -8689,6 +8693,10 @@ declare namespace LocalJSX { * If `true`, the spinner's animation will be paused. */ "paused"?: boolean; + /** + * Set to `"xsmall"` for the smallest size. Set to `"small"` for a smaller size. Set to `"medium"` for a medium size. Set to `"large"` for a large size. Set to `"xlarge"` for the largest size. Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes. + */ + "size"?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; /** * The theme determines the visual appearance of the component. */ diff --git a/core/src/components/spinner/spinner.scss b/core/src/components/spinner/spinner.common.scss similarity index 97% rename from core/src/components/spinner/spinner.scss rename to core/src/components/spinner/spinner.common.scss index 2a8d61bce2..9a8dd1dc8b 100644 --- a/core/src/components/spinner/spinner.scss +++ b/core/src/components/spinner/spinner.common.scss @@ -1,4 +1,6 @@ -@import "../../themes/native/native.globals"; +@import "../../themes/functions.string"; +@import "../../themes/functions.color"; +@import "../../themes/mixins"; // Spinners // -------------------------------------------------- diff --git a/core/src/components/spinner/spinner.ionic.scss b/core/src/components/spinner/spinner.ionic.scss new file mode 100644 index 0000000000..ec673b4bc5 --- /dev/null +++ b/core/src/components/spinner/spinner.ionic.scss @@ -0,0 +1,38 @@ +@use "../../themes/ionic/ionic.globals.scss" as globals; +@use "./spinner.common"; + +// Ionic Spinner +// -------------------------------------------------- + +// Sizes +// -------------------------------------------------- + +/* Extra Small */ +:host(.spinner-xsmall) { + width: globals.$ionic-scale-600; + height: globals.$ionic-scale-600; +} + +/* Small */ +:host(.spinner-small) { + width: globals.$ionic-scale-800; + height: globals.$ionic-scale-800; +} + +/* Medium */ +:host(.spinner-medium) { + width: globals.$ionic-scale-1000; + height: globals.$ionic-scale-1000; +} + +/* Large */ +:host(.spinner-large) { + width: globals.$ionic-scale-1200; + height: globals.$ionic-scale-1200; +} + +/* Extra Large */ +:host(.spinner-xlarge) { + width: globals.$ionic-scale-1400; + height: globals.$ionic-scale-1400; +} diff --git a/core/src/components/spinner/spinner.tsx b/core/src/components/spinner/spinner.tsx index 37c94dbe05..98023babf9 100644 --- a/core/src/components/spinner/spinner.tsx +++ b/core/src/components/spinner/spinner.tsx @@ -16,7 +16,11 @@ import type { SpinnerConfig } from './spinner-interface'; */ @Component({ tag: 'ion-spinner', - styleUrl: 'spinner.scss', + styleUrls: { + ios: 'spinner.common.scss', + md: 'spinner.common.scss', + ionic: 'spinner.ionic.scss', + }, shadow: true, }) export class Spinner implements ComponentInterface { @@ -43,6 +47,18 @@ export class Spinner implements ComponentInterface { */ @Prop() paused = false; + /** + * Set to `"xsmall"` for the smallest size. + * Set to `"small"` for a smaller size. + * Set to `"medium"` for a medium size. + * Set to `"large"` for a large size. + * Set to `"xlarge"` for the largest size. + * + * Defaults to `"xsmall"` for the `ionic` theme, undefined for all other themes. + */ + @Prop() size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'; + + // TODO(ROU-10920): Switch `theme` to `mode`. private getName(): SpinnerTypes { const spinnerName = this.name || config.get('spinner'); const theme = getIonTheme(this); @@ -52,10 +68,27 @@ export class Spinner implements ComponentInterface { return theme === 'ios' ? 'lines' : 'circular'; } + private getSize(): string | undefined { + const theme = getIonTheme(this); + const { size } = this; + + // TODO(ROU-10912): Remove theme check when sizes are defined for all themes. + if (theme !== 'ionic') { + return undefined; + } + + if (size === undefined) { + return 'xsmall'; + } + + return size; + } + render() { const self = this; const theme = getIonTheme(self); const spinnerName = self.getName(); + const size = this.getSize(); const spinner = SPINNERS[spinnerName] ?? SPINNERS['lines']; const duration = typeof self.duration === 'number' && self.duration > 10 ? self.duration : spinner.dur; const svgs: SVGElement[] = []; @@ -76,6 +109,7 @@ export class Spinner implements ComponentInterface { [theme]: true, [`spinner-${spinnerName}`]: true, 'spinner-paused': self.paused || config.getBoolean('_testing'), + [`spinner-${size}`]: size !== undefined, })} role="progressbar" style={spinner.elmDuration ? { animationDuration: duration + 'ms' } : {}} diff --git a/core/src/components/spinner/test/size/index.html b/core/src/components/spinner/test/size/index.html new file mode 100644 index 0000000000..f045932d4c --- /dev/null +++ b/core/src/components/spinner/test/size/index.html @@ -0,0 +1,55 @@ + + + + + Spinner - Size + + + + + + + + + + + + + Spinner - Size + + + + + + + +

Default

+
+ + +

xsmall

+
+ + +

small

+
+ + +

medium

+
+ + +

large

+
+ + +

xlarge

+
+
+
+
+ + diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts b/core/src/components/spinner/test/size/spinner.e2e.ts new file mode 100644 index 0000000000..bb62285cba --- /dev/null +++ b/core/src/components/spinner/test/size/spinner.e2e.ts @@ -0,0 +1,74 @@ +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('spinner: size'), () => { + test('should render xsmall spinner', async ({ page }) => { + await page.setContent( + ` + + `, + config + ); + + const spinner = page.locator('ion-spinner'); + + await expect(spinner).toHaveScreenshot(screenshot(`spinner-size-xsmall`)); + }); + + test('should render small spinner', async ({ page }) => { + await page.setContent( + ` + + `, + config + ); + + const spinner = page.locator('ion-spinner'); + + await expect(spinner).toHaveScreenshot(screenshot(`spinner-size-small`)); + }); + + test('should render medium spinner', async ({ page }) => { + await page.setContent( + ` + + `, + config + ); + + const spinner = page.locator('ion-spinner'); + + await expect(spinner).toHaveScreenshot(screenshot(`spinner-size-medium`)); + }); + + test('should render large spinner', async ({ page }) => { + await page.setContent( + ` + + `, + config + ); + + const spinner = page.locator('ion-spinner'); + + await expect(spinner).toHaveScreenshot(screenshot(`spinner-size-large`)); + }); + + test('should render xlarge spinner', async ({ page }) => { + await page.setContent( + ` + + `, + config + ); + + const spinner = page.locator('ion-spinner'); + + await expect(spinner).toHaveScreenshot(screenshot(`spinner-size-xlarge`)); + }); + }); +}); diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..e72e1059e2 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..d111f35881 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..ddd9ffde01 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-large-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..14b3c9113e Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..7ced01a6ec Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..f8038adcb6 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-medium-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..b4dfd2a063 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..eb0a82f44f Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..60932bf8b8 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..eb4b59c5ba Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..f4fbb0aae5 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..41e37be72e Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xlarge-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..db035b8957 Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..f4259badfa Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..7bc3f22bdb Binary files /dev/null and b/core/src/components/spinner/test/size/spinner.e2e.ts-snapshots/spinner-size-xsmall-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index bc9b1f2cdd..716420d6a8 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -2105,14 +2105,14 @@ export declare interface IonSkeletonText extends Components.IonSkeletonText {} @ProxyCmp({ - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'theme'] + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'] }) @Component({ selector: 'ion-spinner', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'theme'], + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'], }) export class IonSpinner { protected el: HTMLElement; diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 78255ae950..7084b56195 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -1892,14 +1892,14 @@ export declare interface IonSkeletonText extends Components.IonSkeletonText {} @ProxyCmp({ defineCustomElementFn: defineIonSpinner, - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'theme'] + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'] }) @Component({ selector: 'ion-spinner', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['color', 'duration', 'mode', 'name', 'paused', 'theme'], + inputs: ['color', 'duration', 'mode', 'name', 'paused', 'size', 'theme'], standalone: true }) export class IonSpinner { diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 6cee863eb1..301eaa8d26 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -811,7 +811,8 @@ export const IonSpinner = /*@__PURE__*/ defineContainer('ion-spi 'color', 'duration', 'name', - 'paused' + 'paused', + 'size' ]);