Skip to content

Commit

Permalink
feat(skeleton-text): adds animated prop and support for CSS styling (#…
Browse files Browse the repository at this point in the history
…17612)

* moves most of the CSS to the host element so that it's easier to customize the skeleton text
* adds auto inherit for border-radius
* moves height to 100% so it will naturally fill an avatar and thumbnail
* adds animated property defaulted to `false`
* removes mode specific styles as they're the same
* changes background to an rgba making it easier to customize
* still works outside of a container element
* adds usage examples for javascript and angular
* moves the width to the parent element making it easier to style
* adds the ability to style the width using CSS
* uses the global theme text color as the background if a custom background is not supplied before defaulting

closes ionic-team/ionic-docs#407
  • Loading branch information
brandyscarney committed Feb 27, 2019
1 parent a99d179 commit d66b12b
Show file tree
Hide file tree
Showing 17 changed files with 1,061 additions and 84 deletions.
4 changes: 2 additions & 2 deletions angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -748,15 +748,15 @@ export class IonSelectOption {
proxyInputs(IonSelectOption, ['disabled', 'selected', 'value']);

export declare interface IonSkeletonText extends StencilComponents<'IonSkeletonText'> {}
@Component({ selector: 'ion-skeleton-text', changeDetection: 0, template: '<ng-content></ng-content>', inputs: ['width'] })
@Component({ selector: 'ion-skeleton-text', changeDetection: 0, template: '<ng-content></ng-content>', inputs: ['animated', 'width'] })
export class IonSkeletonText {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef) {
c.detach();
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: '<ng-content></ng-content>' })
Expand Down
5 changes: 4 additions & 1 deletion core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 5 additions & 3 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
323 changes: 317 additions & 6 deletions core/src/components/skeleton-text/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,335 @@ Skeleton Text is a component for rendering placeholder content. The element will

## Usage

### Angular

```html
<!-- Data to display after skeleton screen -->
<div *ngIf="data">
<div class="ion-padding">
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.
</div>

<ion-list>
<ion-list-header>Data</ion-list-header>
<ion-item>
<ion-avatar slot="start">
<img src="./avatar.svg">
</ion-avatar>
<ion-label>
<h3>
{{ data.heading }}
</h3>
<p>
{{ data.para1 }}
</p>
<p>
{{ data.para2 }}
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-thumbnail slot="start">
<img src="./thumbnail.svg">
</ion-thumbnail>
<ion-label>
<h3>
{{ data.heading }}
</h3>
<p>
{{ data.para1 }}
</p>
<p>
{{ data.para2 }}
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-icon name="call" slot="start"></ion-icon>
<ion-label>
<h3>
{{ data.heading }}
</h3>
<p>
{{ data.para1 }}
</p>
<p>
{{ data.para2 }}
</p>
</ion-label>
</ion-item>
</ion-list>
</div>

<!-- Skeleton screen -->
<div *ngIf="!data">
<div class="ion-padding custom-skeleton">
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
<ion-skeleton-text animated></ion-skeleton-text>
<ion-skeleton-text animated style="width: 88%"></ion-skeleton-text>
<ion-skeleton-text animated style="width: 70%"></ion-skeleton-text>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</div>

<ion-list>
<ion-list-header>
<ion-skeleton-text animated style="width: 20%"></ion-skeleton-text>
</ion-list-header>
<ion-item>
<ion-avatar slot="start">
<ion-skeleton-text animated></ion-skeleton-text>
</ion-avatar>
<ion-label>
<h3>
<ion-skeleton-text animated style="width: 50%"></ion-skeleton-text>
</h3>
<p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text>
</p>
<p>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-thumbnail slot="start">
<ion-skeleton-text animated></ion-skeleton-text>
</ion-thumbnail>
<ion-label>
<h3>
<ion-skeleton-text animated style="width: 50%"></ion-skeleton-text>
</h3>
<p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text>
</p>
<p>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-skeleton-text animated style="width: 27px; height: 27px" slot="start"></ion-skeleton-text>
<ion-label>
<h3>
<ion-skeleton-text animated style="width: 50%"></ion-skeleton-text>
</h3>
<p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text>
</p>
<p>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</p>
</ion-label>
</ion-item>
</ion-list>
</div>
```

```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
<!-- Data to display after skeleton screen -->
<div id="data">
<div class="ion-padding">
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.
</div>

<ion-list>
<ion-list-header>Data</ion-list-header>
<ion-item>
<ion-avatar slot="start">
<img src="./avatar.svg">
</ion-avatar>
<ion-label>
<h3>
Normal text
</h3>
<p>
Lorem ipsum dolor sit amet, consectetur
</p>
<p>
adipiscing elit.
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-thumbnail slot="start">
<img src="./thumbnail.svg">
</ion-thumbnail>
<ion-label>
<h3>
Normal text
</h3>
<p>
Lorem ipsum dolor sit amet, consectetur
</p>
<p>
adipiscing elit.
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-icon name="call" slot="start"></ion-icon>
<ion-label>
<h3>
Normal text
</h3>
<p>
Lorem ipsum dolor sit amet, consectetur
</p>
<p>
adipiscing elit.
</p>
</ion-label>
</ion-item>
</ion-list>
</div>

<!-- Skeleton screen -->
<div id="skeleton">
<div class="ion-padding custom-skeleton">
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
<ion-skeleton-text animated></ion-skeleton-text>
<ion-skeleton-text animated style="width: 88%"></ion-skeleton-text>
<ion-skeleton-text animated style="width: 70%"></ion-skeleton-text>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</div>

<ion-list>
<ion-list-header>
<ion-skeleton-text animated style="width: 20%"></ion-skeleton-text>
</ion-list-header>
<ion-item>
<ion-avatar slot="start">
<ion-skeleton-text animated></ion-skeleton-text>
</ion-avatar>
<ion-label>
<h3>
<ion-skeleton-text animated style="width: 50%"></ion-skeleton-text>
</h3>
<p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text>
</p>
<p>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-thumbnail slot="start">
<ion-skeleton-text animated></ion-skeleton-text>
</ion-thumbnail>
<ion-label>
<h3>
<ion-skeleton-text animated style="width: 50%"></ion-skeleton-text>
</h3>
<p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text>
</p>
<p>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</p>
</ion-label>
</ion-item>
<ion-item>
<ion-skeleton-text animated style="width: 27px; height: 27px" slot="start"></ion-skeleton-text>
<ion-label>
<h3>
<ion-skeleton-text animated style="width: 50%"></ion-skeleton-text>
</h3>
<p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text>
</p>
<p>
<ion-skeleton-text animated style="width: 60%"></ion-skeleton-text>
</p>
</ion-label>
</ion-item>
</ion-list>
</div>
```

```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 |


----------------------------------------------
Expand Down
Loading

0 comments on commit d66b12b

Please sign in to comment.