diff --git a/docs/components/skeleton.md b/docs/components/skeleton.md index 73baf5e6..b23c3c6b 100644 --- a/docs/components/skeleton.md +++ b/docs/components/skeleton.md @@ -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
- - - +
+ + +
+ + + +
``` +## 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 +
+ + Sheen + + + Pulse + + + None +
+ + +``` + +### Paragraphs + +Use multiple skeletons and some clever styles to simulate paragraphs. + +```html preview +
+ + + + + +
+ + +``` + +### Avatars + +Set a matching width and height to make a circle, square, or rounded avatar skeleton. + +```html preview +
+ + + +
+ + +``` + +### 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 +
+ + + + + +
+ + +``` + +### Custom Colors + +Set the `--color` and `--sheen-color` custom properties to adjust the skeleton's color. + +```html preview + +``` + [component-metadata:sl-skeleton] diff --git a/src/components.d.ts b/src/components.d.ts index d15b5ea0..64f7b849 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -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 { } diff --git a/src/components/skeleton/skeleton.scss b/src/components/skeleton/skeleton.scss index e5a09557..e55a04be 100644 --- a/src/components/skeleton/skeleton.scss +++ b/src/components/skeleton/skeleton.scss @@ -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; } } diff --git a/src/components/skeleton/skeleton.tsx b/src/components/skeleton/skeleton.tsx index feaf0b1f..d6ae2833 100644 --- a/src/components/skeleton/skeleton.tsx +++ b/src/components/skeleton/skeleton.tsx @@ -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" - /> + > +
+
); } }