diff --git a/BREAKING.md b/BREAKING.md index 863a3d09e66..3a72ceb9425 100644 --- a/BREAKING.md +++ b/BREAKING.md @@ -30,6 +30,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver - [Radio Group](#version-9x-radio-group) - [Ripple Effect](#version-9x-ripple-effect) - [Row](#version-9x-row) + - [Skeleton Text](#version-9x-skeleton-text) - [Spinner](#version-9x-spinner) - [Text](#version-9x-text) - [Textarea](#version-9x-textarea) @@ -382,6 +383,33 @@ The following breaking changes apply to `ion-row`: Remove any instances that target the theme classes: `ion-row.md`, `ion-row.ios`. +

Skeleton Text

+ +The following breaking changes apply to `ion-skeleton-text`: + +1. `--background` and `--background-rgb` CSS variables have been replaced with per-state background tokens, each split into an RGB value and an alpha. [1](#version-9x-skeleton-text-replaced-css-variables) +2. `--border-radius` has been replaced. [1](#version-9x-skeleton-text-replaced-css-variables) +3. Theme classes (`ion-skeleton-text.md`, `ion-skeleton-text.ios`) are no longer supported. [2](#version-9x-skeleton-text-theme-classes) + +
Replaced CSS variables
+ +The background is now defined per state (resting and animated), and each state exposes an RGB value plus an alpha so the color and its opacity can be set independently. Use the new token structure for global styles, or the corresponding CSS variable for component-specific overrides: + +| Old (8.x) | New token (global) | New CSS variable (component-specific) | +|---|---|---| +| `--background-rgb` | `IonSkeletonText.default.background.rgb` | `--ion-skeleton-text-default-background-rgb` | +| `--background-rgb` | `IonSkeletonText.animated.background.rgb` | `--ion-skeleton-text-animated-background-rgb` | +| `--border-radius` | `IonSkeletonText.border.radius` | `--ion-skeleton-text-border-radius` | + +The previously fixed opacities are now adjustable through new per-state alpha tokens (`IonSkeletonText.default.background.alpha` / `--ion-skeleton-text-default-background-alpha`, and the `animated` equivalents). + +> [!NOTE] +> `--background` (the resting color) has been removed with no one-to-one replacement; set `--ion-skeleton-text-default-background-rgb` (and optionally `--ion-skeleton-text-default-background-alpha`) instead. The single `--background-rgb` variable previously tinted both the resting fill and the animated shimmer. It is now split per state, so set both `--ion-skeleton-text-default-background-rgb` and `--ion-skeleton-text-animated-background-rgb` to recolor both. + +
Theme classes
+ +Remove any instances that target the theme classes: `ion-skeleton-text.md`, `ion-skeleton-text.ios`. +

Spinner

- Component CSS variables have been removed. The component now utilizes the centralized Ionic Theming system. Global updates should be managed via the theme tokens file, while component-specific overrides are handled through localized CSS variables. diff --git a/core/api.txt b/core/api.txt index 125b08bd490..b936224df2d 100644 --- a/core/api.txt +++ b/core/api.txt @@ -2595,10 +2595,14 @@ ion-select-option,prop,value,any,undefined,false,false ion-skeleton-text,shadow ion-skeleton-text,prop,animated,boolean,false,false,false ion-skeleton-text,prop,mode,"ios" | "md",undefined,false,false -ion-skeleton-text,prop,theme,"ios" | "md" | "ionic",undefined,false,false -ion-skeleton-text,css-prop,--background -ion-skeleton-text,css-prop,--background-rgb -ion-skeleton-text,css-prop,--border-radius +ion-skeleton-text,css-prop,--ion-skeleton-text-animated-background-alpha +ion-skeleton-text,css-prop,--ion-skeleton-text-animated-background-rgb +ion-skeleton-text,css-prop,--ion-skeleton-text-border-radius +ion-skeleton-text,css-prop,--ion-skeleton-text-default-background-alpha +ion-skeleton-text,css-prop,--ion-skeleton-text-default-background-rgb +ion-skeleton-text,css-prop,--ion-skeleton-text-line-height +ion-skeleton-text,css-prop,--ion-skeleton-text-margin-bottom +ion-skeleton-text,css-prop,--ion-skeleton-text-margin-top ion-spinner,shadow ion-spinner,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true diff --git a/core/src/components.d.ts b/core/src/components.d.ts index b6060ae638b..8595d453044 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -3889,10 +3889,6 @@ export namespace Components { * The mode determines the platform behaviors of the component. */ "mode"?: "ios" | "md"; - /** - * The theme determines the visual appearance of the component. - */ - "theme"?: "ios" | "md" | "ionic"; } interface IonSpinner { /** @@ -9976,10 +9972,6 @@ declare namespace LocalJSX { * Emitted when the styles change. */ "onIonStyle"?: (event: IonSkeletonTextCustomEvent) => void; - /** - * The theme determines the visual appearance of the component. - */ - "theme"?: "ios" | "md" | "ionic"; } interface IonSpinner { /** diff --git a/core/src/components/avatar/avatar.common.scss b/core/src/components/avatar/avatar.common.scss index e24c047ad72..0f5531bf58c 100644 --- a/core/src/components/avatar/avatar.common.scss +++ b/core/src/components/avatar/avatar.common.scss @@ -25,3 +25,7 @@ overflow: hidden; } + +::slotted(ion-skeleton-text) { + @include border-radius(var(--border-radius, revert-layer)); +} diff --git a/core/src/components/skeleton-text/skeleton-text.interface.ts b/core/src/components/skeleton-text/skeleton-text.interface.ts new file mode 100644 index 00000000000..689e785b75e --- /dev/null +++ b/core/src/components/skeleton-text/skeleton-text.interface.ts @@ -0,0 +1,31 @@ +import type { IonMargin } from '../../themes/themes.interfaces'; + +export type IonSkeletonTextRecipe = { + animated?: { + background?: { + /** Opacity of the animated shimmer highlight, from 0 to 1. */ + alpha?: string | number; + + /** Highlight color of the animated shimmer, in RGB format (e.g. `255, 0, 0`). */ + rgb?: string; + }; + }; + + border?: { + radius?: string; + }; + + default?: { + background?: { + /** Opacity of the background when it's not being animated, from 0 to 1. */ + alpha?: string | number; + + /** Background color when it's not being animated in RGB format (e.g. `255, 0, 0`), also the base of the animated shimmer. */ + rgb?: string; + }; + }; + + lineHeight?: string; + + margin?: Omit; +}; diff --git a/core/src/components/skeleton-text/skeleton-text.scss b/core/src/components/skeleton-text/skeleton-text.scss index 455fe41ade9..1d53548557b 100644 --- a/core/src/components/skeleton-text/skeleton-text.scss +++ b/core/src/components/skeleton-text/skeleton-text.scss @@ -1,30 +1,36 @@ -@import "./skeleton-text.vars"; +@use "../../themes/mixins" as mixins; +@use "./skeleton-text.vars" as variables; -// Skeleton Text +// Skeleton Text: Common Styles // -------------------------------------------------- :host { /** - * @prop --background: Background of the skeleton text - * @prop --background-rgb: Background of the skeleton text in rgb format + * @prop --ion-skeleton-text-default-background-rgb: Background color when it's not being animated in RGB format (e.g. `255, 0, 0`), also the base of the animated shimmer + * @prop --ion-skeleton-text-default-background-alpha: Opacity of the background when it's not being animated, from 0 to 1 * - * @prop --border-radius: Border radius of the skeleton text + * @prop --ion-skeleton-text-animated-background-rgb: Highlight color of the animated shimmer in RGB format (e.g. `255, 0, 0`) + * @prop --ion-skeleton-text-animated-background-alpha: Opacity of the animated shimmer highlight, from 0 to 1 + * + * @prop --ion-skeleton-text-border-radius: Border radius of the skeleton text + * @prop --ion-skeleton-text-line-height: Line height of the skeleton text + * + * @prop --ion-skeleton-text-margin-top: Top margin of the skeleton text + * @prop --ion-skeleton-text-margin-bottom: Bottom margin of the skeleton text */ - --background: #{$skeleton-text-background}; - - @include border-radius(var(--border-radius, inherit)); + @include mixins.border-radius(var(--ion-skeleton-text-border-radius, inherit)); display: block; width: 100%; height: inherit; - margin-top: 4px; - margin-bottom: 4px; + margin-top: var(--ion-skeleton-text-margin-top); + margin-bottom: var(--ion-skeleton-text-margin-bottom); - background: var(--background); + background: variables.$background-default; - line-height: 10px; + line-height: var(--ion-skeleton-text-line-height); user-select: none; @@ -36,7 +42,7 @@ span { } :host(.in-media) { - @include margin(0); + @include mixins.margin(0); height: 100%; } @@ -49,9 +55,9 @@ span { background: linear-gradient( to right, - $skeleton-text-background 8%, - $skeleton-text-background-animated 18%, - $skeleton-text-background 33% + variables.$background-default 8%, + variables.$background-animated 18%, + variables.$background-default 33% ); background-size: 800px 104px; animation-duration: 1s; diff --git a/core/src/components/skeleton-text/skeleton-text.tsx b/core/src/components/skeleton-text/skeleton-text.tsx index 38c0b60f50c..28eb4a95812 100644 --- a/core/src/components/skeleton-text/skeleton-text.tsx +++ b/core/src/components/skeleton-text/skeleton-text.tsx @@ -3,12 +3,10 @@ import { Component, Element, Event, Host, Prop, h } from '@stencil/core'; import { hostContext } from '@utils/theme'; import { config } from '../../global/config'; -import { getIonTheme } from '../../global/ionic-global'; import type { StyleEventDetail } from '../../interface'; /** * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component. - * @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component. */ @Component({ tag: 'ion-skeleton-text', @@ -34,9 +32,10 @@ export class SkeletonText implements ComponentInterface { } private emitStyle() { - // The emitted property is used by item in order - // to add the item-skeleton-text class which applies - // overflow: hidden to its label + /* + * The emitted property is used by `ion-item` in order to add the + * `.item-skeleton-text` class which applies styles to `ion-label`. + */ const style: StyleEventDetail = { 'skeleton-text': true, }; @@ -47,12 +46,10 @@ export class SkeletonText implements ComponentInterface { render() { const animated = this.animated && config.getBoolean('animated', true); const inMedia = hostContext('ion-avatar', this.el) || hostContext('ion-thumbnail', this.el); - const theme = getIonTheme(this); return ( { +/** + * This behavior does not vary across modes/directions + */ +configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => { test.describe(title('skeleton-text: basic'), () => { test('should not have visual regressions', async ({ page }) => { - await page.goto('/src/components/skeleton-text/test/basic', config); + await page.setContent( + ` + + +
+
+ + + + + +
+ +
+ +
+ + + + + + + + + + + + +
+ `, + config + ); + + const container = page.locator('#container'); + + await expect(container).toHaveScreenshot(screenshot('skeleton-text-basic')); + }); + }); +}); + +/** + * This behavior does not vary across modes/directions + */ +configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('skeleton-text: border radius'), () => { + test('should match the border radius of its containing element', async ({ page }) => { + await page.setContent( + ` + + + + + + + + + + +
+ +
+ `, + config + ); + + const thumbnailSkeleton = page.locator('ion-thumbnail ion-skeleton-text'); + const avatarSkeleton = page.locator('ion-avatar ion-skeleton-text'); + const boxSkeleton = page.locator('#box ion-skeleton-text'); + + await expect(thumbnailSkeleton).toHaveCSS('border-top-left-radius', '10px'); + await expect(avatarSkeleton).toHaveCSS('border-top-left-radius', '12px'); + await expect(boxSkeleton).toHaveCSS('border-top-left-radius', '8px'); + }); + }); + + test.describe(title('skeleton-text: basic'), () => { + // The ionStyle event is emitted once on load so a parent (e.g. ion-item) + // can react to the skeleton. + test('should emit ionStyle on load', async ({ page }) => { + await page.setContent('', config); + + const ionStyle = await page.spyOnEvent('ionStyle'); + + await page.evaluate(() => { + const skeleton = document.createElement('ion-skeleton-text'); + document.body.appendChild(skeleton); + }); + + await ionStyle.next(); + + expect(ionStyle).toHaveReceivedEventDetail({ 'skeleton-text': true }); }); }); }); diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Chrome-linux.png deleted file mode 100644 index 73e7df82ec3..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Firefox-linux.png deleted file mode 100644 index 0fb511d0521..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Safari-linux.png deleted file mode 100644 index 05af97e85ca..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-ltr-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Chrome-linux.png deleted file mode 100644 index 8a06e76ef66..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Firefox-linux.png deleted file mode 100644 index acf3945a3ea..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Safari-linux.png deleted file mode 100644 index 7e4670d21fd..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-ios-rtl-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Chrome-linux.png index 8b114cb6b24..e22e659592d 100644 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Firefox-linux.png index 86288178f3f..12929db15c6 100644 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Safari-linux.png index 0d02a882a14..cf5be96ff70 100644 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Safari-linux.png and b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Chrome-linux.png deleted file mode 100644 index ba26c3f8f09..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Firefox-linux.png deleted file mode 100644 index 35d5b405163..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Safari-linux.png deleted file mode 100644 index 3004db62a0c..00000000000 Binary files a/core/src/components/skeleton-text/test/basic/skeleton-text.e2e.ts-snapshots/skeleton-text-basic-md-rtl-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/index.html b/core/src/components/skeleton-text/test/custom/index.html index b64097472e6..c6a8054d34a 100644 --- a/core/src/components/skeleton-text/test/custom/index.html +++ b/core/src/components/skeleton-text/test/custom/index.html @@ -61,7 +61,8 @@ } .custom-skeleton-color ion-skeleton-text { - --background-rgb: 255, 0, 0; + --ion-skeleton-text-default-background-rgb: 255, 0, 0; + --ion-skeleton-text-animated-background-rgb: 255, 0, 0; } .custom-skeleton-dark { diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts index 7f31fedc003..7686d0c1f1e 100644 --- a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts +++ b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts @@ -1,14 +1,48 @@ import { expect } from '@playwright/test'; import { configs, test } from '@utils/test/playwright'; -configs().forEach(({ title, screenshot, config }) => { +/** + * This behavior does not vary across modes/directions + */ +configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => { test.describe(title('skeleton-text: custom'), () => { test('should not have visual regressions', async ({ page }) => { - await page.goto('/src/components/skeleton-text/test/custom', config); + await page.setContent( + ` + + +
+ + +
+ +
+
+ `, + config + ); + + const container = page.locator('#container'); + + await expect(container).toHaveScreenshot(screenshot('skeleton-text-custom')); }); }); }); diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Chrome-linux.png deleted file mode 100644 index 00ba41da00a..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Firefox-linux.png deleted file mode 100644 index 619c62d8e92..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Safari-linux.png deleted file mode 100644 index 03bac9c3024..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-ltr-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Chrome-linux.png deleted file mode 100644 index 01ae2f16a00..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Firefox-linux.png deleted file mode 100644 index ef1ec8cb36c..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Safari-linux.png deleted file mode 100644 index 2f975528f40..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-ios-rtl-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Chrome-linux.png index ff99e173acc..af4252b6bd0 100644 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Chrome-linux.png differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Firefox-linux.png index c0d3d86fb13..dc243a679e2 100644 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Firefox-linux.png differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Safari-linux.png index 7e3c941dde1..48278b93799 100644 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Safari-linux.png and b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-ltr-Mobile-Safari-linux.png differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Chrome-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Chrome-linux.png deleted file mode 100644 index 60ab88a16da..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Chrome-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Firefox-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Firefox-linux.png deleted file mode 100644 index a9c9f2b4a0c..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Firefox-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Safari-linux.png b/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Safari-linux.png deleted file mode 100644 index 9cb9a71d3b1..00000000000 Binary files a/core/src/components/skeleton-text/test/custom/skeleton-text.e2e.ts-snapshots/skeleton-text-custom-md-rtl-Mobile-Safari-linux.png and /dev/null differ diff --git a/core/src/components/skeleton-text/test/skeleton-text.spec.ts b/core/src/components/skeleton-text/test/skeleton-text.spec.ts new file mode 100644 index 00000000000..576b02f44c9 --- /dev/null +++ b/core/src/components/skeleton-text/test/skeleton-text.spec.ts @@ -0,0 +1,31 @@ +import { newSpecPage } from '@stencil/core/testing'; + +import { config } from '../../../global/config'; +import { SkeletonText } from '../skeleton-text'; + +describe('ion-skeleton-text: class', () => { + beforeEach(() => config.reset({})); + afterEach(() => config.reset({})); + + it('adds skeleton-text-animated when animated and animations are enabled', async () => { + const page = await newSpecPage({ + components: [SkeletonText], + html: ``, + }); + + const skeleton = page.body.querySelector('ion-skeleton-text')!; + expect(skeleton.classList.contains('skeleton-text-animated')).toBe(true); + }); + + it('does not animate when the global animated config is false', async () => { + config.reset({ animated: false }); + + const page = await newSpecPage({ + components: [SkeletonText], + html: ``, + }); + + const skeleton = page.body.querySelector('ion-skeleton-text')!; + expect(skeleton.classList.contains('skeleton-text-animated')).toBe(false); + }); +}); diff --git a/core/src/components/thumbnail/thumbnail.scss b/core/src/components/thumbnail/thumbnail.scss index 54119f85d0a..ae3d54e87a5 100644 --- a/core/src/components/thumbnail/thumbnail.scss +++ b/core/src/components/thumbnail/thumbnail.scss @@ -27,3 +27,7 @@ object-fit: cover; overflow: hidden; } + +::slotted(ion-skeleton-text) { + @include mixins.border-radius(var(--ion-thumbnail-border-radius, revert-layer)); +} diff --git a/core/src/themes/ionic/default.tokens.ts b/core/src/themes/ionic/default.tokens.ts index c6bfc6660c0..cb71652f20d 100644 --- a/core/src/themes/ionic/default.tokens.ts +++ b/core/src/themes/ionic/default.tokens.ts @@ -879,6 +879,29 @@ export const defaultTheme: DefaultTheme = { gap: 'var(--ion-spacing-0)', }, + IonSkeletonText: { + animated: { + background: { + alpha: 0.135, + rgb: baseColors.textColorRgb, + }, + }, + + default: { + background: { + alpha: 0.065, + rgb: baseColors.textColorRgb, + }, + }, + + lineHeight: 'var(--ion-scaling-250)', + + margin: { + bottom: 'var(--ion-spacing-xxs)', + top: 'var(--ion-spacing-xxs)', + }, + }, + IonSpinner: { color: '#626262', diff --git a/core/src/themes/ios/default.tokens.ts b/core/src/themes/ios/default.tokens.ts index 7bf27661a23..6a0a32a35dc 100644 --- a/core/src/themes/ios/default.tokens.ts +++ b/core/src/themes/ios/default.tokens.ts @@ -907,6 +907,29 @@ export const defaultTheme: DefaultTheme = { gap: 'var(--ion-spacing-0)', }, + IonSkeletonText: { + animated: { + background: { + alpha: 0.135, + rgb: baseColors.textColorRgb, + }, + }, + + default: { + background: { + alpha: 0.065, + rgb: baseColors.textColorRgb, + }, + }, + + lineHeight: 'var(--ion-scaling-250)', + + margin: { + bottom: 'var(--ion-spacing-xxs)', + top: 'var(--ion-spacing-xxs)', + }, + }, + IonSpinner: { color: 'var(--ion-text-color, #000)', diff --git a/core/src/themes/md/default.tokens.ts b/core/src/themes/md/default.tokens.ts index c60dc77f60d..9e7626e67cb 100644 --- a/core/src/themes/md/default.tokens.ts +++ b/core/src/themes/md/default.tokens.ts @@ -1032,6 +1032,29 @@ export const defaultTheme: DefaultTheme = { gap: 'var(--ion-spacing-0)', }, + IonSkeletonText: { + animated: { + background: { + alpha: 0.135, + rgb: baseColors.textColorRgb, + }, + }, + + default: { + background: { + alpha: 0.065, + rgb: baseColors.textColorRgb, + }, + }, + + lineHeight: 'var(--ion-scaling-250)', + + margin: { + bottom: 'var(--ion-spacing-xxs)', + top: 'var(--ion-spacing-xxs)', + }, + }, + IonSpinner: { color: 'var(--ion-text-color, #000)', diff --git a/core/src/themes/themes.interfaces.ts b/core/src/themes/themes.interfaces.ts index 4d036580aab..2dd54367014 100644 --- a/core/src/themes/themes.interfaces.ts +++ b/core/src/themes/themes.interfaces.ts @@ -7,6 +7,7 @@ import type { IonItemDividerRecipe } from '../components/item-divider/item-divid import type { IonProgressBarConfig, IonProgressBarRecipe } from '../components/progress-bar/progress-bar.interfaces'; import type { IonRippleEffectRecipe } from '../components/ripple-effect/ripple-effect.interface'; import type { IonRowRecipe } from '../components/row/row.interface'; +import type { IonSkeletonTextRecipe } from '../components/skeleton-text/skeleton-text.interface'; import type { IonSpinnerConfig, IonSpinnerRecipe } from '../components/spinner/spinner.interfaces'; import type { IonTextConfig, IonTextRecipe } from '../components/text/text.interfaces'; import type { IonThumbnailRecipe } from '../components/thumbnail/thumbnail.interfaces'; @@ -302,6 +303,7 @@ type Components = { IonProgressBar?: IonProgressBarRecipe; IonRippleEffect?: IonRippleEffectRecipe; IonRow?: IonRowRecipe; + IonSkeletonText?: IonSkeletonTextRecipe; IonSpinner?: IonSpinnerRecipe; IonText?: IonTextRecipe; IonThumbnail?: IonThumbnailRecipe; diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts index faa50529794..a0c75538967 100644 --- a/packages/angular/src/directives/proxies.ts +++ b/packages/angular/src/directives/proxies.ts @@ -2297,14 +2297,14 @@ export declare interface IonSelectOption extends Components.IonSelectOption {} @ProxyCmp({ - inputs: ['animated', 'mode', 'theme'] + inputs: ['animated', 'mode'] }) @Component({ selector: 'ion-skeleton-text', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['animated', 'mode', 'theme'], + inputs: ['animated', 'mode'], }) export class IonSkeletonText { protected el: HTMLIonSkeletonTextElement; diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts index 7e08227991a..6c11f16f3d4 100644 --- a/packages/angular/standalone/src/directives/proxies.ts +++ b/packages/angular/standalone/src/directives/proxies.ts @@ -2035,14 +2035,14 @@ export declare interface IonSelectOption extends Components.IonSelectOption {} @ProxyCmp({ defineCustomElementFn: defineIonSkeletonText, - inputs: ['animated', 'mode', 'theme'] + inputs: ['animated', 'mode'] }) @Component({ selector: 'ion-skeleton-text', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['animated', 'mode', 'theme'], + inputs: ['animated', 'mode'], standalone: true }) export class IonSkeletonText {