First version of skeleton

pull/146/head
Cory LaViska 2020-07-28 08:41:45 -04:00
rodzic 6ad0d676ef
commit 919d75c022
4 zmienionych plików z 218 dodań i 26 usunięć

Wyświetl plik

@ -4,26 +4,188 @@
Skeletons are used to show where content will eventually be drawn.
These are simple containers for scaffolding layouts that mimic what users will see when content has finished loading. This prevents large areas of empty space during asynchronous operations.
Skeletons try not to be opinionated, as there are endless possibilities for designing layouts. Therefore, you'll likely use more than one skeleton to create the effect you want. If you find yourself using them frequently, consider creating a template that renders them with the desired arrangement and styles.
```html preview
<div class="skeleton-overview">
<sl-skeleton loading></sl-skeleton>
<sl-skeleton loading></sl-skeleton>
<sl-skeleton loading></sl-skeleton>
<header>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
</header>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
</div>
<style>
.skeleton-overview header {
display: flex;
align-items: center;
margin-bottom: 1rem;
}
.skeleton-overview header sl-skeleton:last-child {
flex: 0 0 auto;
width: 30%;
}
.skeleton-overview sl-skeleton {
margin-bottom: 1rem;
}
.skeleton-overview sl-skeleton:nth-child(2) {
.skeleton-overview sl-skeleton:nth-child(1) {
float: left;
width: 3rem;
height: 3rem;
margin-right: 1rem;
vertical-align: middle;
}
.skeleton-overview sl-skeleton:nth-child(3) {
width: 95%;
}
.skeleton-overview sl-skeleton:last-child {
width: 60%;
.skeleton-overview sl-skeleton:nth-child(4) {
width: 80%;
}
</style>
```
## Examples
### Effects
The default effect is `sheen`, which animates a sheen horizontally across the skeleton. There's also `pulse`, which fades the skeleton in and out. To disable animations, use `none`. Effects are intentionally subtle, as they can be distracting otherwise.
```html preview
<div class="skeleton-effects">
<sl-skeleton effect="sheen"></sl-skeleton>
Sheen
<sl-skeleton effect="pulse"></sl-skeleton>
Pulse
<sl-skeleton effect="none"></sl-skeleton>
None
</div>
<style>
.skeleton-effects {
font-size: var(--sl-font-size-small);
}
.skeleton-effects sl-skeleton:not(:first-child) {
margin-top: 1rem;
}
</style>
```
### Paragraphs
Use multiple skeletons and some clever styles to simulate paragraphs.
```html preview
<div class="skeleton-paragraphs">
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
</div>
<style>
.skeleton-paragraphs sl-skeleton {
margin-bottom: 1rem;
}
.skeleton-paragraphs sl-skeleton:nth-child(2) {
width: 95%;
}
.skeleton-paragraphs sl-skeleton:nth-child(4) {
width: 90%;
}
.skeleton-paragraphs sl-skeleton:last-child {
width: 50%;
}
</style>
```
### Avatars
Set a matching width and height to make a circle, square, or rounded avatar skeleton.
```html preview
<div class="skeleton-avatars">
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
<sl-skeleton></sl-skeleton>
</div>
<style>
.skeleton-avatars sl-skeleton {
display: inline-block;
width: 3rem;
height: 3rem;
margin-right: .5rem;
}
.skeleton-avatars sl-skeleton:nth-child(1) {
--border-radius: 0;
}
.skeleton-avatars sl-skeleton:nth-child(2) {
--border-radius: var(--sl-border-radius-medium);
}
</style>
```
### Custom Shapes
Use the `--border-radius` custom property to make circles, squares, and rectangles. For more complex shapes, you can apply `clip-path` to the `indicator` part. [Try Clippy](https://bennettfeely.com/clippy/) if you need help generating custom shapes.
```html preview
<div class="skeleton-sizes">
<sl-skeleton style="width: 100px; height: 100px; --border-radius: var(--sl-border-radius-medium);"></sl-skeleton>
<sl-skeleton style="width: 100px; height: 100px; --border-radius: var(--sl-border-radius-circle);"></sl-skeleton>
<sl-skeleton style="width: 100px; height: 100px; --border-radius: 0;"></sl-skeleton>
<sl-skeleton style="width: 100px; height: 100px; --border-radius: 0;"></sl-skeleton>
<sl-skeleton style="width: 100px; height: 100px; --border-radius: 0;"></sl-skeleton>
</div>
<style>
.skeleton-sizes sl-skeleton {
display: inline-flex;
}
.skeleton-sizes sl-skeleton:nth-child(3)::part(indicator) {
clip-path: polygon(50% 0, 0 100%, 100% 100%);
}
.skeleton-sizes sl-skeleton:nth-child(4)::part(indicator) {
clip-path: polygon(20% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%);
}
.skeleton-sizes sl-skeleton:nth-child(5)::part(indicator) {
clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
}
.skeleton-sizes sl-skeleton:not(:last-child) {
margin-right: 1rem;
}
</style>
```
### Custom Colors
Set the `--color` and `--sheen-color` custom properties to adjust the skeleton's color.
```html preview
<sl-skeleton style="--color: tomato; --sheen-color: #ffb094;"></sl-skeleton>
```
[component-metadata:sl-skeleton]

12
src/components.d.ts vendored
Wyświetl plik

@ -42,7 +42,7 @@ export namespace Components {
*/
"initials": string;
/**
* Initials to use as a fallback when no image is available (1-2 characters max recommended).
* The shape of the avatar.
*/
"shape": 'circle' | 'square' | 'rounded';
}
@ -669,9 +669,9 @@ export namespace Components {
}
interface SlSkeleton {
/**
* When enabled, the skeleton will be animated to indicate that content is loading.
* Determines which effect the skeleton will use.
*/
"loading": boolean;
"effect": 'pulse' | 'sheen' | 'none';
}
interface SlSpinner {
}
@ -1192,7 +1192,7 @@ declare namespace LocalJSX {
*/
"initials"?: string;
/**
* Initials to use as a fallback when no image is available (1-2 characters max recommended).
* The shape of the avatar.
*/
"shape"?: 'circle' | 'square' | 'rounded';
}
@ -1895,9 +1895,9 @@ declare namespace LocalJSX {
}
interface SlSkeleton {
/**
* When enabled, the skeleton will be animated to indicate that content is loading.
* Determines which effect the skeleton will use.
*/
"loading"?: boolean;
"effect"?: 'pulse' | 'sheen' | 'none';
}
interface SlSpinner {
}

Wyświetl plik

@ -1,34 +1,60 @@
@import 'component';
/**
* @prop --border-radius: The skeleton's border radius.
* @prop --color: The color of the skeleton.
* @prop --sheen-color: The sheen color when the skeleton is in its loading state.
*/
:host {
--border-radius: var(--sl-border-radius-pill);
--color: var(--sl-color-gray-90);
--sheen-color: var(--sl-color-gray-95);
display: flex;
height: 1em;
display: block;
position: relative;
}
.skeleton {
display: flex;
width: 100%;
height: 100%;
min-height: 1rem;
}
.skeleton__indicator {
flex: 1 1 auto;
background: var(--color);
border-radius: var(--sl-border-radius-pill);
border-radius: var(--border-radius);
}
.skeleton--loading {
background: linear-gradient(90deg, var(--sheen-color) 20%, var(--color) 40%, var(--sheen-color) 60%);
.skeleton--sheen .skeleton__indicator {
background: linear-gradient(270deg, var(--sheen-color), var(--color), var(--color), var(--sheen-color));
background-size: 400% 100%;
animation: loading 1.5s ease infinite;
background-size: 400% 100%;
animation: sheen 8s ease-in-out infinite;
}
@keyframes loading {
.skeleton--pulse .skeleton__indicator {
animation: pulse 2s ease-in-out 0.5s infinite;
}
@keyframes sheen {
0% {
background-position: 100% 50%;
background-position: 200% 0;
}
to {
background-position: -200% 0;
}
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.4;
}
100% {
background-position: 0 50%;
opacity: 1;
}
}

Wyświetl plik

@ -5,6 +5,7 @@ import { Component, Prop, h } from '@stencil/core';
* @status stable
*
* @part base - The component's base wrapper.
* @part indicator - The skeleton's indicator which is responsible for its color and animation.
*/
@Component({
@ -13,8 +14,8 @@ import { Component, Prop, h } from '@stencil/core';
shadow: true
})
export class Skeleton {
/** When enabled, the skeleton will be animated to indicate that content is loading. */
@Prop() loading = false;
/** Determines which effect the skeleton will use. */
@Prop() effect: 'pulse' | 'sheen' | 'none' = 'sheen';
render() {
return (
@ -22,11 +23,14 @@ export class Skeleton {
part="base"
class={{
skeleton: true,
'skeleton--loading': this.loading
'skeleton--pulse': this.effect === 'pulse',
'skeleton--sheen': this.effect === 'sheen'
}}
aria-busy={this.loading}
aria-busy
aria-live="polite"
/>
>
<div part="indicator" class="skeleton__indicator" />
</div>
);
}
}