diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts index 3c76469d93..b802cbf1b1 100644 --- a/angular/src/directives/proxies.ts +++ b/angular/src/directives/proxies.ts @@ -748,7 +748,7 @@ export class IonSelectOption { proxyInputs(IonSelectOption, ['disabled', 'selected', 'value']); export declare interface IonSkeletonText extends StencilComponents<'IonSkeletonText'> {} -@Component({ selector: 'ion-skeleton-text', changeDetection: 0, template: '', inputs: ['width'] }) +@Component({ selector: 'ion-skeleton-text', changeDetection: 0, template: '', inputs: ['animated', 'width'] }) export class IonSkeletonText { protected el: HTMLElement; constructor(c: ChangeDetectorRef, r: ElementRef) { @@ -756,7 +756,7 @@ export class IonSkeletonText { this.el = r.nativeElement; } } -proxyInputs(IonSkeletonText, ['width']); +proxyInputs(IonSkeletonText, ['animated', 'width']); export declare interface IonSlide extends StencilComponents<'IonSlide'> {} @Component({ selector: 'ion-slide', changeDetection: 0, template: '' }) diff --git a/core/api.txt b/core/api.txt index 679d727fb6..ed1379141c 100644 --- a/core/api.txt +++ b/core/api.txt @@ -975,8 +975,11 @@ ion-select,css-prop,--padding-start ion-select,css-prop,--padding-top ion-skeleton-text,shadow -ion-skeleton-text,prop,width,string,'100%',false,false +ion-skeleton-text,prop,animated,boolean,false,false,false +ion-skeleton-text,prop,width,string | undefined,undefined,false,false ion-skeleton-text,css-prop,--background +ion-skeleton-text,css-prop,--background-rgb +ion-skeleton-text,css-prop,--border-radius ion-slide,none diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 9119916d90..6da6a69257 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -4102,14 +4102,16 @@ export namespace Components { interface IonSkeletonText { /** - * Width for the element to render at. + * If `true`, the skeleton text will animate. */ - 'width': string; + 'animated': boolean; + 'width'?: string; } interface IonSkeletonTextAttributes extends StencilHTMLAttributes { /** - * Width for the element to render at. + * If `true`, the skeleton text will animate. */ + 'animated'?: boolean; 'width'?: string; } diff --git a/core/src/components/skeleton-text/readme.md b/core/src/components/skeleton-text/readme.md index 7debd73f65..f86a9d6ae6 100644 --- a/core/src/components/skeleton-text/readme.md +++ b/core/src/components/skeleton-text/readme.md @@ -8,24 +8,335 @@ Skeleton Text is a component for rendering placeholder content. The element will ## Usage +### Angular + +```html + +
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac eros est. Cras iaculis pulvinar arcu non vehicula. Fusce at quam a eros malesuada condimentum. Aliquam tincidunt tincidunt vehicula. +
+ + + Data + + + + + +

+ {{ data.heading }} +

+

+ {{ data.para1 }} +

+

+ {{ data.para2 }} +

+
+
+ + + + + +

+ {{ data.heading }} +

+

+ {{ data.para1 }} +

+

+ {{ data.para2 }} +

+
+
+ + + +

+ {{ data.heading }} +

+

+ {{ data.para1 }} +

+

+ {{ data.para2 }} +

+
+
+
+
+ + +
+
+ + + + + +
+ + + + + + + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + +

+ +

+

+ +

+

+ +

+
+
+
+
+``` + +```css +/* Custom Skeleton Line Height and Margin */ +.custom-skeleton ion-skeleton-text { + line-height: 13px; +} + +.custom-skeleton ion-skeleton-text:last-child { + margin-bottom: 5px; +} +``` + +```typescript +import { Component } from '@angular/core'; + +@Component({ + selector: 'skeleton-text-example', + templateUrl: 'skeleton-text-example.html', + styleUrls: ['./skeleton-text-example.css'] +}) +export class SkeletonTextExample { + data: any; + + constructor() {} + + ionViewWillEnter() { + setTimeout(() => { + this.data = { + 'heading': 'Normal text', + 'para1': 'Lorem ipsum dolor sit amet, consectetur', + 'para2': 'adipiscing elit.' + }; + }, 5000); + } +} +``` + + ### Javascript +```html + +
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac eros est. Cras iaculis pulvinar arcu non vehicula. Fusce at quam a eros malesuada condimentum. Aliquam tincidunt tincidunt vehicula. +
+ + Data + + + + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+ + + + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+ + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+
+
+ + +
+
+ + + + + +
+ + + + + + + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + +

+ +

+

+ +

+

+ +

+
+
+
+
+``` + +```css +#data { + display: none; +} + +/* Custom Skeleton Line Height and Margin */ +.custom-skeleton ion-skeleton-text { + line-height: 13px; +} + +.custom-skeleton ion-skeleton-text:last-child { + margin-bottom: 5px; +} +``` + +```javascript +function onLoad() { + const skeletonEl = document.getElementById('skeleton'); + const dataEl = document.getElementById('data'); + + setTimeout(() => { + skeletonEl.style.display = 'none'; + dataEl.style.display = 'block'; + }, 5000); +} +``` ## Properties -| Property | Attribute | Description | Type | Default | -| -------- | --------- | ----------------------------------- | -------- | -------- | -| `width` | `width` | Width for the element to render at. | `string` | `'100%'` | +| Property | Attribute | Description | Type | Default | +| ---------- | ---------- | ------------------------------------------ | --------------------- | ----------- | +| `animated` | `animated` | If `true`, the skeleton text will animate. | `boolean` | `false` | +| `width` | `width` | | `string \| undefined` | `undefined` | ## CSS Custom Properties -| Name | Description | -| -------------- | ------------------------------- | -| `--background` | Background of the skeleton text | +| Name | Description | +| ------------------ | --------------------------------------------- | +| `--background` | Background of the skeleton text | +| `--background-rgb` | Background of the skeleton text in rgb format | +| `--border-radius` | Border radius of the skeleton text | ---------------------------------------------- diff --git a/core/src/components/skeleton-text/skeleton-text.ios.scss b/core/src/components/skeleton-text/skeleton-text.ios.scss deleted file mode 100644 index e623466b43..0000000000 --- a/core/src/components/skeleton-text/skeleton-text.ios.scss +++ /dev/null @@ -1,16 +0,0 @@ -@import "./skeleton-text"; -@import "./skeleton-text.ios.vars"; - - -// iOS Skeleton Text -// -------------------------------------------------- - -:host { - --background: #{$skeleton-text-ios-bar-background-color}; -} - -span { - background: var(--background); - - opacity: $skeleton-text-ios-bar-opacity; -} diff --git a/core/src/components/skeleton-text/skeleton-text.ios.vars.scss b/core/src/components/skeleton-text/skeleton-text.ios.vars.scss deleted file mode 100644 index 301e282b6c..0000000000 --- a/core/src/components/skeleton-text/skeleton-text.ios.vars.scss +++ /dev/null @@ -1,10 +0,0 @@ -@import "../../themes/ionic.globals.ios"; - -// iOS Skeleton Text -// -------------------------------------------------- - -/// @prop - Background color of the skeleton text bar -$skeleton-text-ios-bar-background-color: $text-color !default; - -/// @prop - Opacity of the text bar for the skeleton text -$skeleton-text-ios-bar-opacity: .1 !default; diff --git a/core/src/components/skeleton-text/skeleton-text.md.scss b/core/src/components/skeleton-text/skeleton-text.md.scss deleted file mode 100644 index f3881f357d..0000000000 --- a/core/src/components/skeleton-text/skeleton-text.md.scss +++ /dev/null @@ -1,16 +0,0 @@ -@import "./skeleton-text"; -@import "./skeleton-text.md.vars"; - - -// Material Design Skeleton Text -// -------------------------------------------------- - -:host { - --background: #{$skeleton-text-md-bar-background-color}; -} - -span { - background: var(--background); - - opacity: $skeleton-text-md-bar-opacity; -} diff --git a/core/src/components/skeleton-text/skeleton-text.md.vars.scss b/core/src/components/skeleton-text/skeleton-text.md.vars.scss deleted file mode 100644 index c8288f60e7..0000000000 --- a/core/src/components/skeleton-text/skeleton-text.md.vars.scss +++ /dev/null @@ -1,10 +0,0 @@ -@import "../../themes/ionic.globals.md"; - -// Material Design Skeleton Text -// -------------------------------------------------- - -/// @prop - Background color of the skeleton text bar -$skeleton-text-md-bar-background-color: $text-color !default; - -/// @prop - Opacity of the text bar for the skeleton text -$skeleton-text-md-bar-opacity: .1 !default; diff --git a/core/src/components/skeleton-text/skeleton-text.scss b/core/src/components/skeleton-text/skeleton-text.scss index f002bce4d0..838a06c9d7 100644 --- a/core/src/components/skeleton-text/skeleton-text.scss +++ b/core/src/components/skeleton-text/skeleton-text.scss @@ -1,24 +1,69 @@ -@import "../../themes/ionic.globals"; - +@import "./skeleton-text.vars"; // Skeleton Text // -------------------------------------------------- :host { /** - * --background: Background of the skeleton text + * @prop --background: Background of the skeleton text + * @prop --background-rgb: Background of the skeleton text in rgb format + * + * @prop --border-radius: Border radius of the skeleton text */ + --background: #{$skeleton-text-background}; - display: inline-block; + @include border-radius(var(--border-radius, inherit)); + + display: block; width: 100%; - pointer-events: none; + height: inherit; + + margin-top: 4px; + margin-bottom: 4px; + + background: var(--background); + + line-height: 10px; user-select: none; + + pointer-events: none; } span { display: inline-block; - - font-size: 8px; } + +:host(.in-media) { + @include margin(0); + + height: 100%; +} + +// Animated Skeleton Text +// ----------------------------------------------------------- + +:host(.skeleton-text-animated) { + position: relative; + + background: linear-gradient(to right, $skeleton-text-background 8%, $skeleton-text-background-animated 18%, $skeleton-text-background 33%); + background-size: 800px 104px; + animation-duration: 1s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: shimmer; + animation-timing-function: linear; +} + +/* stylelint-disable property-blacklist */ +@keyframes shimmer { + 0% { + background-position: -468px 0 + } + + 100% { + background-position: 468px 0 + } +} +/* stylelint-enable property-blacklist */ diff --git a/core/src/components/skeleton-text/skeleton-text.tsx b/core/src/components/skeleton-text/skeleton-text.tsx index e2a28f5be5..9dde1e234b 100644 --- a/core/src/components/skeleton-text/skeleton-text.tsx +++ b/core/src/components/skeleton-text/skeleton-text.tsx @@ -1,21 +1,58 @@ -import { Component, ComponentInterface, Prop } from '@stencil/core'; +import { Component, ComponentInterface, Element, Prop } from '@stencil/core'; + +import { Config } from '../../interface'; +import { hostContext } from '../../utils/theme'; @Component({ tag: 'ion-skeleton-text', - styleUrls: { - ios: 'skeleton-text.ios.scss', - md: 'skeleton-text.md.scss' - }, + styleUrl: 'skeleton-text.scss', shadow: true }) export class SkeletonText implements ComponentInterface { + @Element() el!: HTMLElement; + + @Prop({ context: 'config' }) config!: Config; + /** - * Width for the element to render at. + * If `true`, the skeleton text will animate. */ - @Prop() width = '100%'; + @Prop() animated = false; + + /** + * @deprecated - Use CSS instead. The width of the skeleton text. If supplied, it will override the CSS style. + */ + @Prop() width?: string; + + calculateWidth() { + // If width was passed in to the property use that first + if (this.width !== undefined) { + return { + style: { + width: this.width + } + }; + } + + return; + } render() { - return  ; + return ( +   + ); + } + + hostData() { + const animated = this.animated && this.config.getBoolean('animated', true); + const inMedia = hostContext('ion-avatar', this.el) || hostContext('ion-thumbnail', this.el); + + return { + class: { + 'skeleton-text-animated': animated, + 'in-media': inMedia + }, + ...this.calculateWidth() + }; } } diff --git a/core/src/components/skeleton-text/skeleton-text.vars.scss b/core/src/components/skeleton-text/skeleton-text.vars.scss new file mode 100644 index 0000000000..8200e02782 --- /dev/null +++ b/core/src/components/skeleton-text/skeleton-text.vars.scss @@ -0,0 +1,16 @@ +@import "../../themes/ionic.globals"; + +// Skeleton Text +// -------------------------------------------------- + +/// @prop - Background color alpha of the skeleton text +$skeleton-text-background-alpha: .065 !default; + +/// @prop - Background color of the skeleton text +$skeleton-text-background: rgba(var(--background-rgb, var(--ion-text-color-rgb, $text-color-rgb)), $skeleton-text-background-alpha) !default; + +/// @prop - Background color alpha of the skeleton text animation +$skeleton-text-background-animated-alpha: .135 !default; + +/// @prop - Background color of the skeleton text animation +$skeleton-text-background-animated: rgba(var(--background-rgb, var(--ion-text-color-rgb, $text-color-rgb)), $skeleton-text-background-animated-alpha) !default; diff --git a/core/src/components/skeleton-text/test/basic/e2e.ts b/core/src/components/skeleton-text/test/basic/e2e.ts new file mode 100644 index 0000000000..b5894401f0 --- /dev/null +++ b/core/src/components/skeleton-text/test/basic/e2e.ts @@ -0,0 +1,10 @@ +import { newE2EPage } from '@stencil/core/testing'; + +test('skeleton-text: basic', async () => { + const page = await newE2EPage({ + url: '/src/components/skeleton-text/test/basic?ionic:_testing=true' + }); + + const compare = await page.compareScreenshot(); + expect(compare).toMatchScreenshot(); +}); diff --git a/core/src/components/skeleton-text/test/basic/index.html b/core/src/components/skeleton-text/test/basic/index.html index b903c414a1..0daf83bf69 100644 --- a/core/src/components/skeleton-text/test/basic/index.html +++ b/core/src/components/skeleton-text/test/basic/index.html @@ -4,7 +4,8 @@ Skeleton Text - Basic - + @@ -12,11 +13,223 @@ - - - - - + + + + Skeleton Text + + Toggle + + + + +
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac eros est. Cras iaculis pulvinar arcu non vehicula. Fusce at quam a eros malesuada condimentum. Aliquam tincidunt tincidunt vehicula. +
+ + + Data + + + + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+ + + + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+ + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+
+
+ +
+
+ + + + + +
+ + + + + + + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + +

+ +

+

+ +

+

+ +

+
+
+
+
+ + + Animated + + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + +

+ +

+

+ +

+

+ +

+
+
+
+ +
+ +
+ + +
+
+ + + + diff --git a/core/src/components/skeleton-text/test/custom/e2e.ts b/core/src/components/skeleton-text/test/custom/e2e.ts new file mode 100644 index 0000000000..ba4e87cfe1 --- /dev/null +++ b/core/src/components/skeleton-text/test/custom/e2e.ts @@ -0,0 +1,10 @@ +import { newE2EPage } from '@stencil/core/testing'; + +test('skeleton-text: custom', async () => { + const page = await newE2EPage({ + url: '/src/components/skeleton-text/test/custom?ionic:_testing=true' + }); + + const compare = await page.compareScreenshot(); + expect(compare).toMatchScreenshot(); +}); diff --git a/core/src/components/skeleton-text/test/custom/index.html b/core/src/components/skeleton-text/test/custom/index.html new file mode 100644 index 0000000000..7e45941623 --- /dev/null +++ b/core/src/components/skeleton-text/test/custom/index.html @@ -0,0 +1,77 @@ + + + + + + Skeleton Text - Custom + + + + + + + + + + + + Skeleton Text + + + +
Default
+
+ + + + + + +
+
Custom RGB Background
+
+ + + + + + +
+
Global Text Color Dark Theme
+
+ + + + + + +
+ + +
+
+ + + + + diff --git a/core/src/components/skeleton-text/usage/angular.md b/core/src/components/skeleton-text/usage/angular.md new file mode 100644 index 0000000000..5e505c1b4a --- /dev/null +++ b/core/src/components/skeleton-text/usage/angular.md @@ -0,0 +1,157 @@ +```html + +
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac eros est. Cras iaculis pulvinar arcu non vehicula. Fusce at quam a eros malesuada condimentum. Aliquam tincidunt tincidunt vehicula. +
+ + + Data + + + + + +

+ {{ data.heading }} +

+

+ {{ data.para1 }} +

+

+ {{ data.para2 }} +

+
+
+ + + + + +

+ {{ data.heading }} +

+

+ {{ data.para1 }} +

+

+ {{ data.para2 }} +

+
+
+ + + +

+ {{ data.heading }} +

+

+ {{ data.para1 }} +

+

+ {{ data.para2 }} +

+
+
+
+
+ + +
+
+ + + + + +
+ + + + + + + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + +

+ +

+

+ +

+

+ +

+
+
+
+
+``` + +```css +/* Custom Skeleton Line Height and Margin */ +.custom-skeleton ion-skeleton-text { + line-height: 13px; +} + +.custom-skeleton ion-skeleton-text:last-child { + margin-bottom: 5px; +} +``` + +```typescript +import { Component } from '@angular/core'; + +@Component({ + selector: 'skeleton-text-example', + templateUrl: 'skeleton-text-example.html', + styleUrls: ['./skeleton-text-example.css'] +}) +export class SkeletonTextExample { + data: any; + + constructor() {} + + ionViewWillEnter() { + setTimeout(() => { + this.data = { + 'heading': 'Normal text', + 'para1': 'Lorem ipsum dolor sit amet, consectetur', + 'para2': 'adipiscing elit.' + }; + }, 5000); + } +} +``` \ No newline at end of file diff --git a/core/src/components/skeleton-text/usage/javascript.md b/core/src/components/skeleton-text/usage/javascript.md index e69de29bb2..53b5b18c1c 100644 --- a/core/src/components/skeleton-text/usage/javascript.md +++ b/core/src/components/skeleton-text/usage/javascript.md @@ -0,0 +1,148 @@ +```html + +
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac eros est. Cras iaculis pulvinar arcu non vehicula. Fusce at quam a eros malesuada condimentum. Aliquam tincidunt tincidunt vehicula. +
+ + + Data + + + + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+ + + + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+ + + +

+ Normal text +

+

+ Lorem ipsum dolor sit amet, consectetur +

+

+ adipiscing elit. +

+
+
+
+
+ + +
+
+ + + + + +
+ + + + + + + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + + + +

+ +

+

+ +

+

+ +

+
+
+ + + +

+ +

+

+ +

+

+ +

+
+
+
+
+``` + +```css +#data { + display: none; +} + +/* Custom Skeleton Line Height and Margin */ +.custom-skeleton ion-skeleton-text { + line-height: 13px; +} + +.custom-skeleton ion-skeleton-text:last-child { + margin-bottom: 5px; +} +``` + +```javascript +function onLoad() { + const skeletonEl = document.getElementById('skeleton'); + const dataEl = document.getElementById('data'); + + setTimeout(() => { + skeletonEl.style.display = 'none'; + dataEl.style.display = 'block'; + }, 5000); +} +``` \ No newline at end of file