diff --git a/dist/legacy-tokens/ds4-light.css b/dist/legacy-tokens/ds4-light.css
index 063f94702..8562c292d 100644
--- a/dist/legacy-tokens/ds4-light.css
+++ b/dist/legacy-tokens/ds4-light.css
@@ -134,4 +134,39 @@
var(--color-ai-solid-green-subtle) 0%,
var(--color-ai-solid-blue-subtle) 154.5%
);
+ --color-loading-fill: #f2f2f2;
+ --color-loading-shimmer: linear-gradient(
+ 270deg,
+ var(--color-loading-fill) 0%,
+ var(--color-loading-fill) 34%,
+ #f8f8f8 50%,
+ var(--color-loading-fill) 66%,
+ var(--color-loading-fill) 100%
+ );
+ --color-loading-fill-elevated: var(--color-loading-fill);
+ --color-loading-shimmer-elevated: var(--color-loading-shimmer);
+ --color-loading-ai-gradient-purple-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-red-subtle) 0%,
+ var(--color-ai-solid-red-subtle) 34%,
+ var(--color-ai-solid-purple-subtle) 50%,
+ var(--color-ai-solid-red-subtle) 66%,
+ var(--color-ai-solid-red-subtle) 100%
+ );
+ --color-loading-ai-gradient-blue-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-blue-subtle) 0%,
+ var(--color-ai-solid-blue-subtle) 34%,
+ var(--color-ai-solid-purple-subtle) 50%,
+ var(--color-ai-solid-blue-subtle) 66%,
+ var(--color-ai-solid-blue-subtle) 100%
+ );
+ --color-loading-ai-gradient-green-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-green-subtle) 0%,
+ var(--color-ai-solid-green-subtle) 34%,
+ var(--color-ai-solid-blue-subtle) 50%,
+ var(--color-ai-solid-green-subtle) 66%,
+ var(--color-ai-solid-green-subtle) 100%
+ );
}
diff --git a/dist/mixins/skeleton-mixins.less b/dist/mixins/skeleton-mixins.less
new file mode 100644
index 000000000..f37f9fd49
--- /dev/null
+++ b/dist/mixins/skeleton-mixins.less
@@ -0,0 +1,15 @@
+:root {
+ --skeleton-border-radius: 0;
+ --skeleton-height: 48px;
+ --skeleton-width: 100%;
+ --skeleton-background: var(--color-loading-fill);
+}
+
+.skeleton-base(@border-radius: var(--skeleton-border-radius), @height: var(--skeleton-height), @width: var(--skeleton-width) ) {
+ background: var(--skeleton-background);
+ border-radius: @border-radius;
+ cursor: progress;
+ height: @height;
+ min-height: 12px;
+ width: @width;
+}
diff --git a/dist/skeleton/skeleton.css b/dist/skeleton/skeleton.css
new file mode 100644
index 000000000..eede3b728
--- /dev/null
+++ b/dist/skeleton/skeleton.css
@@ -0,0 +1,196 @@
+:root {
+ --skeleton-border-radius: 0;
+ --skeleton-height: 48px;
+ --skeleton-width: 100%;
+ --skeleton-background: var(--color-loading-fill);
+}
+.skeleton {
+ container-name: skeleton-container;
+ container-type: inline-size;
+}
+.skeleton__avatar {
+ background: var(--skeleton-background);
+ border-radius: 50%;
+ cursor: progress;
+ height: var(--skeleton-height);
+ min-height: 12px;
+ width: var(--skeleton-height);
+}
+.skeleton__button {
+ background: var(--skeleton-background);
+ border-radius: 20px;
+ cursor: progress;
+ height: 40px;
+ min-height: 12px;
+ width: var(--skeleton-width);
+}
+.skeleton__button--small {
+ background: var(--skeleton-background);
+ border-radius: 16px;
+ cursor: progress;
+ height: 32px;
+ min-height: 12px;
+ width: var(--skeleton-width);
+}
+.skeleton__button--large {
+ background: var(--skeleton-background);
+ border-radius: 24px;
+ cursor: progress;
+ height: 48px;
+ min-height: 12px;
+ width: var(--skeleton-width);
+}
+.skeleton__text {
+ background: var(--skeleton-background);
+ border-radius: 3px;
+ cursor: progress;
+ height: 16px;
+ min-height: 12px;
+ width: calc(100% - var(--spacing-300));
+}
+.skeleton__text::after {
+ height: 16px;
+ margin-top: calc(16px + var(--spacing-100));
+}
+.skeleton__text--large {
+ background: var(--skeleton-background);
+ border-radius: 3px;
+ cursor: progress;
+ height: 24px;
+ min-height: 12px;
+ width: calc(100% - var(--spacing-300));
+}
+.skeleton__text--large::after {
+ height: 24px;
+ margin-top: calc(24px + var(--spacing-100));
+}
+.skeleton__text--multiline {
+ margin-bottom: var(--spacing-300);
+ position: relative;
+ width: calc(100% - var(--spacing-300));
+}
+.skeleton__text--multiline::after {
+ background: inherit;
+ content: "";
+ position: absolute;
+ width: calc(100% - var(--spacing-700));
+}
+.skeleton__text--large.skeleton__text--multiline {
+ margin-bottom: var(--spacing-400);
+}
+.skeleton__textbox {
+ background: var(--skeleton-background);
+ border-radius: 8px;
+ cursor: progress;
+ height: 48px;
+ min-height: 12px;
+ width: var(--skeleton-width);
+}
+.skeleton__image {
+ background: var(--skeleton-background);
+ border-radius: 8px;
+ cursor: progress;
+ height: 100%;
+ min-height: 12px;
+ width: var(--skeleton-width);
+ max-width: initial;
+}
+.skeleton__image::after {
+ bottom: 0;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 100%;
+}
+span.skeleton__avatar,
+span.skeleton__button,
+span.skeleton__text,
+span.skeleton__image,
+span.skeleton__textbox {
+ display: inline-block;
+}
+span.skeleton__avatar + span,
+span.skeleton__button + span,
+span.skeleton__text + span,
+span.skeleton__image + span,
+span.skeleton__textbox + span {
+ -webkit-margin-start: var(--spacing-100);
+ margin-inline-start: var(--spacing-100);
+}
+div.skeleton__avatar,
+div.skeleton__button,
+div.skeleton__text,
+div.skeleton__image,
+div.skeleton__textbox {
+ -webkit-margin-before: var(--spacing-150);
+ margin-block-start: var(--spacing-150);
+}
+.skeleton--elevated {
+ --skeleton-background: var(--color-loading-fill-elevated);
+}
+@media screen and (max-width: 512px) {
+ .skeleton {
+ --skeleton-background: var(--color-loading-shimmer);
+ }
+ .skeleton--elevated {
+ --skeleton-background: var(--color-loading-shimmer-elevated);
+ }
+}
+.skeleton--purple {
+ --skeleton-background: var(--color-loading-ai-gradient-purple-subtle);
+}
+.skeleton--green {
+ --skeleton-background: var(--color-loading-ai-gradient-green-subtle);
+}
+.skeleton--blue {
+ --skeleton-background: var(--color-loading-ai-gradient-blue-subtle);
+}
+@media (prefers-reduced-motion: no-preference) {
+ @keyframes loading-frames {
+ 0% {
+ background-position: 0% 0%;
+ }
+ 50% {
+ background-position: 45% 0%;
+ }
+ 100% {
+ background-position: 90% 0%;
+ }
+ }
+ @keyframes fade-in {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+ }
+ .skeleton__avatar,
+ .skeleton__button,
+ .skeleton__text,
+ .skeleton__image,
+ .skeleton__textbox {
+ /* setting animation-iteration-count to 6 (5000/833ms) */
+ /* so it does not exceed 5s per WCAG 2.2.2 */
+ animation: fade-in 500ms forwards, loading-frames 833ms 667ms linear 6;
+ animation-fill-mode: both;
+ background-size: 200%;
+ }
+}
+@container skeleton-container (width > 79px) {
+ .skeleton__image {
+ border-radius: 16px;
+ }
+}
+[dir="rtl"] .skeleton__avatar,
+[dir="rtl"] .skeleton__button,
+[dir="rtl"] .skeleton__text,
+[dir="rtl"] .skeleton__image,
+[dir="rtl"] .skeleton__textbox {
+ animation-direction: normal, reverse;
+}
+[dir="rtl"] .skeleton__text--multiline::after {
+ left: var(--spacing-700);
+}
diff --git a/dist/tokens/evo-core.css b/dist/tokens/evo-core.css
index 15638a4fb..974c20ccf 100644
--- a/dist/tokens/evo-core.css
+++ b/dist/tokens/evo-core.css
@@ -121,5 +121,6 @@
--spacing-400: 32px;
--spacing-450: 36px;
--spacing-600: 48px;
+ --spacing-700: 56px;
--spacing-800: 64px;
}
diff --git a/dist/tokens/evo-dark.css b/dist/tokens/evo-dark.css
index 4a1065606..c41e2eb16 100644
--- a/dist/tokens/evo-dark.css
+++ b/dist/tokens/evo-dark.css
@@ -136,5 +136,47 @@
var(--color-ai-solid-green-subtle) 0%,
var(--color-ai-solid-blue-subtle) 154.5%
);
+ --color-loading-fill: #1b1b1b;
+ --color-loading-shimmer: linear-gradient(
+ 270deg,
+ var(--color-loading-fill) 0%,
+ var(--color-loading-fill) 34%,
+ #0e0e0e 50%,
+ var(--color-loading-fill) 66%,
+ var(--color-loading-fill) 100%
+ );
+ --color-loading-fill-elevated: #222;
+ --color-loading-shimmer-elevated: linear-gradient(
+ 270deg,
+ var(--color-loading-fill-elevated) 0%,
+ var(--color-loading-fill-elevated) 34%,
+ #1c1c1c 50%,
+ var(--color-loading-fill-elevated) 66%,
+ var(--color-loading-fill-elevated) 100%
+ );
+ --color-loading-ai-gradient-purple-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-red-subtle-dark) 0%,
+ var(--color-ai-solid-red-subtle-dark) 34%,
+ var(--color-ai-solid-purple-subtle-dark) 50%,
+ var(--color-ai-solid-red-subtle-dark) 66%,
+ var(--color-ai-solid-red-subtle-dark) 100%
+ );
+ --color-loading-ai-gradient-blue-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-blue-subtle-dark) 0%,
+ var(--color-ai-solid-blue-subtle-dark) 34%,
+ var(--color-ai-solid-purple-subtle-dark) 50%,
+ var(--color-ai-solid-blue-subtle-dark) 66%,
+ var(--color-ai-solid-blue-subtle-dark) 100%
+ );
+ --color-loading-ai-gradient-green-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-green-subtle-dark) 0%,
+ var(--color-ai-solid-green-subtle-dark) 34%,
+ var(--color-ai-solid-blue-subtle-dark) 50%,
+ var(--color-ai-solid-green-subtle-dark) 66%,
+ var(--color-ai-solid-green-subtle-dark) 100%
+ );
}
}
diff --git a/dist/tokens/evo-light.css b/dist/tokens/evo-light.css
index 063f94702..8562c292d 100644
--- a/dist/tokens/evo-light.css
+++ b/dist/tokens/evo-light.css
@@ -134,4 +134,39 @@
var(--color-ai-solid-green-subtle) 0%,
var(--color-ai-solid-blue-subtle) 154.5%
);
+ --color-loading-fill: #f2f2f2;
+ --color-loading-shimmer: linear-gradient(
+ 270deg,
+ var(--color-loading-fill) 0%,
+ var(--color-loading-fill) 34%,
+ #f8f8f8 50%,
+ var(--color-loading-fill) 66%,
+ var(--color-loading-fill) 100%
+ );
+ --color-loading-fill-elevated: var(--color-loading-fill);
+ --color-loading-shimmer-elevated: var(--color-loading-shimmer);
+ --color-loading-ai-gradient-purple-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-red-subtle) 0%,
+ var(--color-ai-solid-red-subtle) 34%,
+ var(--color-ai-solid-purple-subtle) 50%,
+ var(--color-ai-solid-red-subtle) 66%,
+ var(--color-ai-solid-red-subtle) 100%
+ );
+ --color-loading-ai-gradient-blue-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-blue-subtle) 0%,
+ var(--color-ai-solid-blue-subtle) 34%,
+ var(--color-ai-solid-purple-subtle) 50%,
+ var(--color-ai-solid-blue-subtle) 66%,
+ var(--color-ai-solid-blue-subtle) 100%
+ );
+ --color-loading-ai-gradient-green-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-green-subtle) 0%,
+ var(--color-ai-solid-green-subtle) 34%,
+ var(--color-ai-solid-blue-subtle) 50%,
+ var(--color-ai-solid-green-subtle) 66%,
+ var(--color-ai-solid-green-subtle) 100%
+ );
}
diff --git a/dist/variables/variables.less b/dist/variables/variables.less
index af14c8f8d..0faf8c987 100644
--- a/dist/variables/variables.less
+++ b/dist/variables/variables.less
@@ -57,6 +57,7 @@
@spacing-400: @spacing-100 * 4;
@spacing-450: @spacing-100 * 4.5;
@spacing-600: @spacing-100 * 6;
+@spacing-700: @spacing-100 * 7;
@spacing-800: @spacing-100 * 8;
@font-size-giant-3: @font-size-46;
diff --git a/docs/_data/modules.yaml b/docs/_data/modules.yaml
index 59eb207ce..fcb5bfaf6 100644
--- a/docs/_data/modules.yaml
+++ b/docs/_data/modules.yaml
@@ -50,6 +50,7 @@ list:
- segmented-buttons
- select
- signal
+ - skeleton
- snackbar-dialog
- split-button
- star-rating
diff --git a/docs/_includes/skeleton-examples.html b/docs/_includes/skeleton-examples.html
new file mode 100644
index 000000000..3b669cead
--- /dev/null
+++ b/docs/_includes/skeleton-examples.html
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+ Skeleton examples
+
+
+
+
+ Implementation 1: Using single DOM element and CSS :empty selector
+ In this progressive enhancement approach, :empty pseudo-class in CSS is used for
+ showing a skeleton loader without the need for client-side JavaScript. This approach detects if the container
+ with the class skeleton is empty and displays the skeleton loader until the asynchronous content is available.
+ When the asynchronous content is ready, the skeleton loader will automatically disappear because the :empty pseudo-class no longer applies.
+
+ This approach is highly performant and consumes less resources especially on devices with limited CPU resources.
+
+ NOTE: The :empty pseudo-class considers elements with whitespace as not empty.
+ Therefore, it is important to ensure that the skeleton container doesn't contain any whitespace or comments
+ before
+ the asynchronous content is loaded.
+
+ {% highlight html %}
+
+
+ {% endhighlight %}
+
+ {% highlight css %}
+ /* example css to demonstrate the approach */
+ .demo-skeleton:empty {
+ background: var(--color-loading-fill);
+ border-radius: 8px;
+ height: 300px;
+ width: 100%;
+ }
+ {% endhighlight %}
+
+ Implementation 2: Using multiple DOM elements and JavaScript
+ In this approach using JavaScript, we gain more flexibility and control over when and how the skeleton loader is
+ replaced with the actual content. Here we can completely hide or replace the skeleton loader and display the
+ asyncronous content instead. This could be done by toggling the hidden attribute
+ on
+ the skeleton loader and the content container.
+ NOTE: JavaScript is required to toggle visbility of the skeletons and content container.
+ {% highlight html %}
+
+
+
+
+
+
+ asynchronous content
+
+
+ asynchronous content
+ {% endhighlight %}
+
+ {% highlight css %}
+ /* example css to demonstrate the approach */
+ .skeleton__button {
+ background: var(--color-loading-fill);
+ border-radius: 8px;
+ height: 300px;
+ width: 100%;
+ }
+ {% endhighlight %}
+
+ When to use one over the other?
+ Usually, skeletons can be ingressed to four loading scenarios.
+
+ Buffered rendering
+ Progressive rendering - In-order (where browser renders different chunks of the page in specified order.)
+ Progressive rendering - Out of order (where browser renders different chunks of the page asynchronously)
+ Client side rendering
+
+ In Buffered rendering, the content is loaded in chunks or buffers. Because the content is not loaded all at once,
+ there is no fixed point where skeletons can be displayed.
+ For, progressive in-order rendering the CSS :empty technique is very performant, but requires the app team to
+ construct the customn skeleton. The Skin currently provides following mixins to make importing easier. For scenarios 3 &
+ 4, that require JavaScript to load implementation 2 is the right choice.
+ {% highlight css %}
+ /* if using a less file, skin provides following mixins to use */
+ .skeleton-base(@border-radius: var(--skeleton-border-radius), @height: var(--skeleton-height), @width: var(--skeleton-width) ) {
+ background: var(--color-loading-fill);
+ border-radius: @border-radius;
+ cursor: progress;
+ height: @height;
+ min-height: 12px;
+ width: @width;
+ }
+
+ .demo-skeleton:empty {
+ .skeleton-base(8px, 300px);
+ }
+ {% endhighlight %}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_includes/skeleton.html b/docs/_includes/skeleton.html
new file mode 100644
index 000000000..48af70b8e
--- /dev/null
+++ b/docs/_includes/skeleton.html
@@ -0,0 +1,408 @@
+
+
+
@ebay/skin/skeleton BETA
+
+
+
+
Attention
+
Skeletons are currently work in progress and in BETA mode. For guidance and appropriate usage, please reachout
+ the core team.
+
+
+
The Skeletons are simplified versions of layouts to indicate that information has not
+ been fully loaded to improve the perceived performance.
+
+
+
+ Skeleton type
+ default
+ elevated
+ purple
+ green
+ blue
+
+
+
+
+ Avatar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Button
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Textbox
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Image
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Usage
+
+ Skeletons should only appear once loading time reaches 500ms or longer.
+ Not every page or page section requires skeleton.
+ Skeletons are primarily intended as a replacement for
+ spinners.
+ Do not use skeletons if either layout/dimensions are not known.
+ Do not use skeletons if it will cause layout to shift content.
+ Do not use skeletons for content that is below the fold i.e, for lazy loading images etc.
+
+
+
Labelling
+
By default, the skeleton loaders doesn't convey to screen reader users in a meaningful way. The aria-label
+ attribute, set to "loading", is utilized to signify the loading state of the
+ skeleton loader to screen reader users. To prevent the screen reader from repeating the label, the
+ aria-label attribute should be positioned on the container element. For a better
+ understanding of this subtlety, please refer to below examples.
+
+
Colors
+
On larger screens, skeleton loaders use standard fill color in the background where as a shimmer is applied on
+ smaller screens. An elevated color can be applied by overriding container skeletons with their color classes respectively. For
+ example, any skeleton shape can inherit elevated background using skeleton--elevated
+ class.
+
Similarly, for AI purposes, respective colors can be applied using skeleton--purple , skeleton--green and skeleton--blue classes. For example, checkout the examples under custom skeletons section.
+
+
Skeleton Examples
+
The Skeleton examples shown illustrate when to utilize skeletons
+ and various techniques for implementing them in different loading scenarios.
+
+
CSS Properties
+
We've set up CSS properties to provide developers with easy reference for responsive
+ adjustments of UIs. The CSS properties allow for customization of skeletons for UIs
+ that require it, but please use them sparingly and be mindful of the impact those overrides can
+ have .
+
+
+
+ {% highlight css %}
+ --skeleton-border-radius: 0; /* The default border radius */
+ --skeleton-height: 48px; /* The default skeleton height */
+ --skeleton-width: 100%; /* The default skeleton width */
+ --skeleton-background: var(--color-loading-fill); /* The default background color of the skeleton */
+ {% endhighlight %}
+
+
Building blocks
+
Avatar
+
Use the skeleton__avatar class to load a skeleton avatar.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
+
Regular Button
+
Use the skeleton__button class, to create a minimal, default skeleton button loader.
+
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
Small Button
+
Use the small modifier to decrease the size of the skeleton.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
Large Button
+
Use the large modifier to increase the size of the skeleton.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
Textbox
+
Use the skeleton__textbox class, when loading form controls.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
Image
+
Use the skeleton__image class, while loading images. By default, skeleton image
+ loader inherits the height and width of the element.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
Text
+
Use the skeleton__text class, to display content block in a single
+ row.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
Variant: Large Text
+
Use the skeleton__text--large class, to display large content block in a single
+ row.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
Variant: Two row text
+
Use the skeleton__text--multiline classes, to display content changes in
+ multiple rows.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
Custom Skeletons
+
Tile
+
A custom tile layout is shown here with image and text content.
+
+ {% highlight html %}
+
+ {% endhighlight %}
+
+
Inline blocks
+
To use skeletons inline, replace div with span.
+
+ {% highlight html %}
+
+
+
+
+ {% endhighlight %}
\ No newline at end of file
diff --git a/docs/_layouts/page-grid-templates.html b/docs/_layouts/page-grid-templates.html
index 98aa96609..459941402 100644
--- a/docs/_layouts/page-grid-templates.html
+++ b/docs/_layouts/page-grid-templates.html
@@ -19,7 +19,7 @@
diff --git a/docs/index.html b/docs/index.html
index 945bfb9ef..4b2781044 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -50,6 +50,7 @@
segmented-buttons: 1.0
select: 2.2
signal: 1.0
+ skeleton: 1.0
snackbar-dialog: 2.0
split-button: 1.6
star-rating: 1.0
diff --git a/docs/page-grid-templates/index.html b/docs/page-grid-templates/index.html
index 78d4ac16a..90eb6f764 100644
--- a/docs/page-grid-templates/index.html
+++ b/docs/page-grid-templates/index.html
@@ -2,6 +2,7 @@
layout: page-grid-templates
title: Page Grid Templates
static_dir: ../static
+slug: page-grid
---
{% include page-grid-templates.html %}
\ No newline at end of file
diff --git a/docs/skeleton-examples/index.html b/docs/skeleton-examples/index.html
new file mode 100644
index 000000000..2dd30c605
--- /dev/null
+++ b/docs/skeleton-examples/index.html
@@ -0,0 +1,8 @@
+---
+layout: page-grid-templates
+title: Skeleton examples
+static_dir: ../static
+slug: skeleton
+---
+
+{% include skeleton-examples.html %}
\ No newline at end of file
diff --git a/docs/skeleton-examples/using-empty/index.html b/docs/skeleton-examples/using-empty/index.html
new file mode 100644
index 000000000..c2853667e
--- /dev/null
+++ b/docs/skeleton-examples/using-empty/index.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+ Progressive rendering(In-order): Using CSS :empty
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Title of a longer featured blog post
+ Multiple lines of text that form the lede, informing new readers quickly and efficiently about what's most
+ interesting in this post's contents.
+ Continue reading...
+
+
+
+
+
Featured Post 1
+
This is a wider card with supporting text below as a natural lead-in to additional content.
+
+
+ Thumbnail
+
+
+
+
+
+
+
Featured Post 2
+
This is a wider card with supporting text below as a natural lead-in to additional content.
+
+
+ Thumbnail
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/skeleton-examples/using-empty/script.js b/docs/skeleton-examples/using-empty/script.js
new file mode 100644
index 000000000..126438d18
--- /dev/null
+++ b/docs/skeleton-examples/using-empty/script.js
@@ -0,0 +1,65 @@
+// Here we are using JavaScript setTimeout function here to simulate a delay in loading the content.
+setTimeout(() => {
+
+const skeleton = document.querySelector('.demo-skeleton');
+const main = document.querySelector('main');
+const body = document.querySelector('body');
+
+skeleton.innerHTML = `
+ From the Firehose
+ Sample blog post
+ This blog post shows a few different types of content that's supported and styled with Bootstrap. Basic
+ typography, images, and code are all supported.
+
+ Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean eu leo quam.
+ Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras
+ mattis consectetur purus sit amet fermentum.
+
+ Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor
+ id nibh ultricies vehicula ut id elit.
+
+ Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean
+ lacinia bibendum nulla sed consectetur.
+
+ Heading
+ Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus,
+ nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac,
+ vestibulum at eros.
+
+ Sub-heading
+ Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+
+ Example code block
+ Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce
+ dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.
+
+ Sub-heading
+ Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia
+ bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac
+ cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
+
+ Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
+ Donec id elit non mi porta gravida at eget metus.
+ Nulla vitae elit libero, a pharetra augue.
+ Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.
+
+ Vestibulum id ligula porta felis euismod semper.
+ Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ Maecenas sed diam eget risus varius blandit sit amet non magna.
+ Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis.
+`;
+
+main.insertAdjacentHTML('afterend', ``);
+
+body.insertAdjacentHTML('beforeend', ``);
+
+}, 5000);
\ No newline at end of file
diff --git a/docs/skeleton-examples/using-empty/style.css b/docs/skeleton-examples/using-empty/style.css
new file mode 100644
index 000000000..188f3de63
--- /dev/null
+++ b/docs/skeleton-examples/using-empty/style.css
@@ -0,0 +1,200 @@
+:root {
+ --spacing-large: 16px;
+}
+
+body {
+ color: #212529;
+ font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
+ margin: 0;
+}
+
+a {
+ color: currentColor;
+}
+
+header {
+ display: flex;
+ justify-content: space-between;
+ padding: var(--spacing-large) 0;
+}
+
+header > p {
+ font-size: 1.75rem;
+ font-weight: bold;
+ margin: 0;
+}
+
+nav ul {
+ display: flex;
+ justify-content: space-around;
+ list-style: none;
+ margin: 0;
+ overflow: auto;
+ padding: 0;
+}
+
+nav li {
+ margin: 0 8px;
+}
+
+#hero {
+ background-color: #343a40;
+ color: white;
+ padding: var(--spacing-large);
+}
+
+aside,
+main {
+ outline: 1px solid;
+ outline-offset: -1px;
+ padding: var(--spacing-large);
+}
+
+footer {
+ background-color: #eee;
+ padding: var(--spacing-large);
+ text-align: center;
+}
+
+
+/* skeleton styles */
+.demo-skeleton:empty {
+ background: var(--color-loading-fill);
+ border-radius: 8px;
+ cursor: progress;
+ position: relative;
+ min-height: 24px;
+ margin-bottom: 320px;
+}
+
+.demo-skeleton:empty::after {
+ background: inherit;
+ border-radius: 8px;
+ content: "";
+ margin-top: 32px;
+ position: absolute;
+ width: 100%;
+ height: 300px;
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ @keyframes loading-frames {
+ 0% {
+ background-position: 0% 0%;
+ }
+ 50% {
+ background-position: 45% 0%;
+ }
+ 100% {
+ background-position: 90% 0%;
+ }
+ }
+ @keyframes fade-in {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+ }
+
+ .skeleton:empty,
+ .skeleton:empty::after {
+ animation: fade-in 1s forwards;
+ animation-fill-mode: both;
+ background-size: 200%;
+ }
+}
+
+
+/* add some lines marking the edges of grids */
+.page-grid {
+ outline: 1px solid;
+ outline-offset: -1px;
+}
+
+.featured__article {
+ grid-area: 1 / 1 / span 1 / span 8;
+}
+
+.featured__article,
+.featured__thumbnail {
+ padding: var(--spacing-large);
+}
+
+.featured__thumbnail {
+ display: none;
+}
+
+header {
+ /* syntax: row-start / col-start / row-span / col-span */
+ grid-area: 1 / 1 / span 1 / span 8;
+}
+
+nav {
+ grid-area: 2 / 1 / span 1 / span 8;
+}
+
+#hero {
+ grid-area: 3 / 1 / span 1 / span 8;
+}
+
+#featured-1 {
+ grid-area: 4 / 1 / span 1 / span 8;
+}
+
+#featured-2 {
+ grid-area: 5 / 1 / span 1 / span 8;
+}
+
+main {
+ grid-area: 6 / 1 / span 1 / span 8;
+}
+
+aside {
+ grid-area: 7 / 1 / span 1 / span 8;
+}
+
+/* Skin goes from 8 columns to 16 columns at this SM (small) breakpoint */
+@media (min-width: 512px) {
+ header {
+ grid-area: 1 / 1 / span 1 / span 16;
+ }
+
+ nav {
+ grid-area: 2 / 1 / span 1 / span 16;
+ }
+
+ #hero {
+ grid-area: 3 / 1 / span 1 / span 16;
+ }
+
+ #featured-1 {
+ grid-area: 4 / 1 / span 1 / span 8;
+ }
+
+ #featured-2 {
+ grid-area: 4 / 9 / span 1 / span 8;
+ }
+
+ .featured__article {
+ grid-area: 1 / 1 / span 1 / span 12;
+ }
+
+ .featured__thumbnail {
+ grid-area: 1 / 13 / span 1 / span 4;
+ align-items: center;
+ background-color: #343a40;
+ color: white;
+ display: flex;
+ justify-content: center;
+ }
+
+ main {
+ grid-area: 5 / 1 / span 1 / span 10;
+ }
+
+ aside {
+ grid-area: 5 / 11 / span 1 / span 6;
+ }
+}
diff --git a/docs/skeleton-examples/using-js-1/index.html b/docs/skeleton-examples/using-js-1/index.html
new file mode 100644
index 000000000..6ba0acf01
--- /dev/null
+++ b/docs/skeleton-examples/using-js-1/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+ Skeleton example: Using JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Title of a longer featured blog post
+ Multiple lines of text that form the lede, informing new readers quickly and efficiently about what's most
+ interesting in this post's contents.
+ Continue reading...
+
+
+
+
+
Featured Post 1
+
This is a wider card with supporting text below as a natural lead-in to additional content.
+
+
+ Thumbnail
+
+
+
+
+
+
+
Featured Post 2
+
This is a wider card with supporting text below as a natural lead-in to additional content.
+
+
+ Thumbnail
+
+
+
+
+ From the Firehose
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/skeleton-examples/using-js-1/script.js b/docs/skeleton-examples/using-js-1/script.js
new file mode 100644
index 000000000..c1964c531
--- /dev/null
+++ b/docs/skeleton-examples/using-js-1/script.js
@@ -0,0 +1,72 @@
+// Function to generate random time in milliseconds
+function getTimeinMS() {
+ return Math.floor(Math.random() * 4000) + 1000;
+}
+
+// Function to set content for a given element
+function setAsyncContent(elementId, content) {
+ setTimeout(() => {
+ const element = document.getElementById(elementId);
+ element.innerHTML = content;
+ element.previousElementSibling.setAttribute('hidden', true);
+ }, getTimeinMS());
+}
+
+// Set content for featured-3 section
+const content = `
+Sample blog post
+This blog post shows a few different types of content that's supported and styled with Bootstrap. Basic
+ typography, images, and code are all supported.
+
+Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean eu leo quam.
+ Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras
+ mattis consectetur purus sit amet fermentum.
+
+Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor
+ id nibh ultricies vehicula ut id elit.
+
+ Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean
+ lacinia bibendum nulla sed consectetur.
+
+Heading
+Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus,
+ nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac,
+ vestibulum at eros.
+
+Sub-heading
+Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+
+Example code block
+Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce
+ dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.
+
+Sub-heading
+Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia
+ bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac
+ cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
+
+Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
+ Donec id elit non mi porta gravida at eget metus.
+ Nulla vitae elit libero, a pharetra augue.
+ Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.
+
+Vestibulum id ligula porta felis euismod semper.
+ Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ Maecenas sed diam eget risus varius blandit sit amet non magna.
+ Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis.
+`;
+setAsyncContent('featured-3', content);
+
+// Set content for section-1
+const content2 = `
+About
+Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.
+`;
+setAsyncContent('section-1', content2);
+
+
+const content3 = `
+Archives
+Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.
+`;
+setAsyncContent('section-2', content3);
\ No newline at end of file
diff --git a/docs/skeleton-examples/using-js-1/style.css b/docs/skeleton-examples/using-js-1/style.css
new file mode 100644
index 000000000..db1452dca
--- /dev/null
+++ b/docs/skeleton-examples/using-js-1/style.css
@@ -0,0 +1,191 @@
+:root {
+ --spacing-large: 16px;
+}
+
+body {
+ color: #212529;
+ font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
+ margin: 0;
+}
+
+a {
+ color: currentColor;
+}
+
+header {
+ display: flex;
+ justify-content: space-between;
+ padding: var(--spacing-large) 0;
+}
+
+header > p {
+ font-size: 1.75rem;
+ font-weight: bold;
+ margin: 0;
+}
+
+nav ul {
+ display: flex;
+ justify-content: space-around;
+ list-style: none;
+ margin: 0;
+ overflow: auto;
+ padding: 0;
+}
+
+nav li {
+ margin: 0 8px;
+}
+
+#hero {
+ background-color: #343a40;
+ color: white;
+ padding: var(--spacing-large);
+}
+
+aside,
+main {
+ outline: 1px solid;
+ outline-offset: -1px;
+ padding: var(--spacing-large);
+}
+
+aside section {
+ margin-bottom: var(--spacing-large);
+}
+
+footer {
+ background-color: #eee;
+ padding: var(--spacing-large);
+ text-align: center;
+}
+
+
+/* skeleton styles */
+.skeleton {
+ background: var(--color-loading-fill);
+ border-radius: 8px;
+ cursor: progress;
+ min-height: 300px;
+ width: 100%;
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ @keyframes loading-frames {
+ 0% {
+ background-position: 0% 0%;
+ }
+ 50% {
+ background-position: 45% 0%;
+ }
+ 100% {
+ background-position: 90% 0%;
+ }
+ }
+ @keyframes fade-in {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+ }
+
+ .skeleton {
+ animation: fade-in 1s forwards;
+ animation-fill-mode: both;
+ background-size: 200%;
+ }
+}
+
+/* add some lines marking the edges of grids */
+.page-grid {
+ outline: 1px solid;
+ outline-offset: -1px;
+}
+
+.featured__article {
+ grid-area: 1 / 1 / span 1 / span 8;
+}
+
+.featured__article,
+.featured__thumbnail {
+ padding: var(--spacing-large);
+}
+
+.featured__thumbnail {
+ display: none;
+}
+
+header {
+ /* syntax: row-start / col-start / row-span / col-span */
+ grid-area: 1 / 1 / span 1 / span 8;
+}
+
+nav {
+ grid-area: 2 / 1 / span 1 / span 8;
+}
+
+#hero {
+ grid-area: 3 / 1 / span 1 / span 8;
+}
+
+#featured-1 {
+ grid-area: 4 / 1 / span 1 / span 8;
+}
+
+#featured-2 {
+ grid-area: 5 / 1 / span 1 / span 8;
+}
+
+main {
+ grid-area: 6 / 1 / span 1 / span 8;
+}
+
+aside {
+ grid-area: 7 / 1 / span 1 / span 8;
+}
+
+/* Skin goes from 8 columns to 16 columns at this SM (small) breakpoint */
+@media (min-width: 512px) {
+ header {
+ grid-area: 1 / 1 / span 1 / span 16;
+ }
+
+ nav {
+ grid-area: 2 / 1 / span 1 / span 16;
+ }
+
+ #hero {
+ grid-area: 3 / 1 / span 1 / span 16;
+ }
+
+ #featured-1 {
+ grid-area: 4 / 1 / span 1 / span 8;
+ }
+
+ #featured-2 {
+ grid-area: 4 / 9 / span 1 / span 8;
+ }
+
+ .featured__article {
+ grid-area: 1 / 1 / span 1 / span 12;
+ }
+
+ .featured__thumbnail {
+ grid-area: 1 / 13 / span 1 / span 4;
+ align-items: center;
+ background-color: #343a40;
+ color: white;
+ display: flex;
+ justify-content: center;
+ }
+
+ main {
+ grid-area: 5 / 1 / span 1 / span 10;
+ }
+
+ aside {
+ grid-area: 5 / 11 / span 1 / span 6;
+ }
+}
diff --git a/docs/skeleton-examples/using-js-2/index.html b/docs/skeleton-examples/using-js-2/index.html
new file mode 100644
index 000000000..b58e41694
--- /dev/null
+++ b/docs/skeleton-examples/using-js-2/index.html
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+ Skeleton example: Using client side re-render
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Title of a longer featured blog post
+ Multiple lines of text that form the lede, informing new readers quickly and efficiently about what's most
+ interesting in this post's contents.
+ Continue reading...
+
+
+
+
+
Featured Post 1
+
This is a wider card with supporting text below as a natural lead-in to additional content.
+
+
+ Thumbnail
+
+
+
+
+
+
+
Featured Post 2
+
This is a wider card with supporting text below as a natural lead-in to additional content.
+
+
+ Thumbnail
+
+
+
+
+ From the Firehose
+ Load images
+
+
+
+
+
+ About
+ Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean
+ lacinia bibendum nulla sed consectetur.
+
+
+ Archives
+ Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean
+ lacinia bibendum nulla sed consectetur.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/skeleton-examples/using-js-2/script.js b/docs/skeleton-examples/using-js-2/script.js
new file mode 100644
index 000000000..e3e04537f
--- /dev/null
+++ b/docs/skeleton-examples/using-js-2/script.js
@@ -0,0 +1,52 @@
+setTimeout(() => {
+ const asyncButton = document.getElementById('asyncButton');
+ asyncButton.addEventListener('click', function(event) {
+ event.preventDefault();
+ asyncButton.setAttribute('disabled', true);
+ // load some skeletons first
+ document.getElementById('featured-3').innerHTML = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+ // load async content
+ setTimeout(() => {
+ document.getElementById('featured-3').innerHTML = `
+
+
+
+
+
+
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia.
+
+
+
+
+
+
+
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia
+
+
+
+
+
+
+
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia
+
+
+
+ `;
+ }, 3000);
+ });
+}, 1000);
diff --git a/docs/skeleton-examples/using-js-2/style.css b/docs/skeleton-examples/using-js-2/style.css
new file mode 100644
index 000000000..514a60e31
--- /dev/null
+++ b/docs/skeleton-examples/using-js-2/style.css
@@ -0,0 +1,160 @@
+:root {
+ --spacing-large: 16px;
+}
+
+body {
+ color: #212529;
+ font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
+ margin: 0;
+}
+
+a {
+ color: currentColor;
+}
+
+header {
+ display: flex;
+ justify-content: space-between;
+ padding: var(--spacing-large) 0;
+}
+
+header > p {
+ font-size: 1.75rem;
+ font-weight: bold;
+ margin: 0;
+}
+
+nav ul,
+main ul {
+ display: flex;
+ justify-content: space-around;
+ list-style: none;
+ margin: 0;
+ overflow: auto;
+ padding: 0;
+}
+
+nav li {
+ margin: 0 8px;
+}
+
+#hero {
+ background-color: #343a40;
+ color: white;
+ padding: var(--spacing-large);
+}
+
+aside,
+main {
+ outline: 1px solid;
+ outline-offset: -1px;
+ padding: var(--spacing-large);
+}
+
+aside section {
+ margin-bottom: var(--spacing-large);
+}
+
+footer {
+ background-color: #eee;
+ padding: var(--spacing-large);
+ text-align: center;
+}
+
+/* skeleton styles */
+.example-tile-container li{
+ margin-right: 10px;
+ width: 220px;
+}
+
+/* add some lines marking the edges of grids */
+.page-grid {
+ outline: 1px solid;
+ outline-offset: -1px;
+}
+
+.featured__article {
+ grid-area: 1 / 1 / span 1 / span 8;
+}
+
+.featured__article,
+.featured__thumbnail {
+ padding: var(--spacing-large);
+}
+
+.featured__thumbnail {
+ display: none;
+}
+
+header {
+ /* syntax: row-start / col-start / row-span / col-span */
+ grid-area: 1 / 1 / span 1 / span 8;
+}
+
+nav {
+ grid-area: 2 / 1 / span 1 / span 8;
+}
+
+#hero {
+ grid-area: 3 / 1 / span 1 / span 8;
+}
+
+#featured-1 {
+ grid-area: 4 / 1 / span 1 / span 8;
+}
+
+#featured-2 {
+ grid-area: 5 / 1 / span 1 / span 8;
+}
+
+main {
+ grid-area: 6 / 1 / span 1 / span 8;
+}
+
+aside {
+ grid-area: 7 / 1 / span 1 / span 8;
+}
+
+/* Skin goes from 8 columns to 16 columns at this SM (small) breakpoint */
+@media (min-width: 512px) {
+ header {
+ grid-area: 1 / 1 / span 1 / span 16;
+ }
+
+ nav {
+ grid-area: 2 / 1 / span 1 / span 16;
+ }
+
+ #hero {
+ grid-area: 3 / 1 / span 1 / span 16;
+ }
+
+ #featured-1 {
+ grid-area: 4 / 1 / span 1 / span 8;
+ }
+
+ #featured-2 {
+ grid-area: 4 / 9 / span 1 / span 8;
+ }
+
+ .featured__article {
+ grid-area: 1 / 1 / span 1 / span 12;
+ }
+
+ .featured__thumbnail {
+ grid-area: 1 / 13 / span 1 / span 4;
+ align-items: center;
+ background-color: #343a40;
+ color: white;
+ display: flex;
+ justify-content: center;
+ }
+
+ main {
+ grid-area: 5 / 1 / span 1 / span 10;
+ }
+
+ aside {
+ grid-area: 5 / 11 / span 1 / span 6;
+ }
+}
diff --git a/docs/src/less/index.less b/docs/src/less/index.less
index 8b2bc963b..d015bbab1 100644
--- a/docs/src/less/index.less
+++ b/docs/src/less/index.less
@@ -446,25 +446,35 @@ span.icon {
vertical-align: middle;
}
-/* EEK SECTION */
+/* EEK, Skeleton SECTION */
-.eek-table {
+.eek-table,
+.skeleton-table,
+.skeleton-table-colors {
border-collapse: collapse;
margin: var(--spacing-300) 0;
width: 100%;
}
.eek-table th,
-.eek-table td {
+.eek-table td,
+.skeleton-table th,
+.skeleton-table td,
+.skeleton-table-colors th,
+.skeleton-table-colors td {
padding: var(--spacing-100);
text-align: left;
}
-.eek-table th {
+.eek-table th,
+.skeleton-table th,
+.skeleton-table-colors th {
background-color: var(--color-background-tertiary);
}
-.eek-table td {
+.eek-table td,
+.skeleton-table td,
+.skeleton-table-colors td {
border-bottom: 1px solid #eee;
}
diff --git a/docs/static/docs.min.css b/docs/static/docs.min.css
index 7753a3c82..8729c9be2 100644
--- a/docs/static/docs.min.css
+++ b/docs/static/docs.min.css
@@ -1 +1 @@
-/*! Wombat VIM theme */.highlight pre,.highlight table,figure .highlight{background:#242424!important;color:#f6f3e8!important}.highlight .hll{background-color:#ffc!important}.highlight .c{color:#99968b!important;font-style:italic!important}.highlight .err{color:#f6f3e8!important}.highlight .g{color:#f6f3e8!important}.highlight .k{color:#8ac6f2!important}.highlight .l{color:#f6f3e8!important}.highlight .h,.highlight .n{color:#f6f3e8!important}.highlight .o{color:#f6f3e8!important}.highlight .x{color:#f6f3e8!important}.highlight .p{color:#f6f3e8!important}.highlight .cm{color:#99968b!important;font-style:italic!important}.highlight .cp{color:#e5786d!important}.highlight .c1{color:#99968b!important;font-style:italic!important}.highlight .cs{color:#99968b!important;font-style:italic!important}.highlight .gd{color:#f6f3e8!important}.highlight .ge{color:#f6f3e8!important}.highlight .gr{color:#f6f3e8!important}.highlight .gh{color:#f6f3e8!important;font-weight:700!important}.highlight .gi{color:#f6f3e8!important}.highlight .go{color:grey!important;background-color:#303030!important}.highlight .gp{color:#f6f3e8!important}.highlight .gs{color:#f6f3e8!important}.highlight .gu{color:#f6f3e8!important;font-weight:700!important}.highlight .gt{color:#f6f3e8!important}.highlight .kc{color:#8ac6f2!important}.highlight .kd{color:#8ac6f2!important}.highlight .kn{color:#8ac6f2!important}.highlight .kp{color:#8ac6f2!important}.highlight .kr{color:#8ac6f2!important}.highlight .kt{color:#cae682!important}.highlight .ld{color:#f6f3e8!important}.highlight .m{color:#e5786d!important}.highlight .s{color:#95e454!important;font-style:italic!important}.highlight .na{color:#cae682!important}.highlight .nb{color:#f6f3e8!important}.highlight .nc{color:#f6f3e8!important}.highlight .no{color:#e5786d!important}.highlight .nd{color:#f6f3e8!important}.highlight .ni{color:#e7f6da!important}.highlight .ne{color:#f6f3e8!important}.highlight .nf{color:#cae682!important}.highlight .nl{color:#f6f3e8!important}.highlight .nn{color:#f6f3e8!important}.highlight .nx{color:#f6f3e8!important}.highlight .py{color:#f6f3e8!important}.highlight .nt{color:#8ac6f2!important}.highlight .nv{color:#cae682!important}.highlight .ow{color:#f6f3e8!important}.highlight .w{color:#f6f3e8!important}.highlight .mf{color:#e5786d!important}.highlight .mh{color:#e5786d!important}.highlight .mi{color:#e5786d!important}.highlight .mo{color:#e5786d!important}.highlight .sb{color:#95e454!important;font-style:italic!important}.highlight .sc{color:#95e454!important;font-style:italic!important}.highlight .sd{color:#95e454!important;font-style:italic!important}.highlight .s2{color:#95e454!important;font-style:italic!important}.highlight .se{color:#95e454!important;font-style:italic!important}.highlight .sh{color:#95e454!important;font-style:italic!important}.highlight .si{color:#95e454!important;font-style:italic!important}.highlight .sx{color:#95e454!important;font-style:italic!important}.highlight .sr{color:#95e454!important;font-style:italic!important}.highlight .s1{color:#95e454!important;font-style:italic!important}.highlight .ss{color:#95e454!important;font-style:italic!important}.highlight .bp{color:#f6f3e8!important}.highlight .vc{color:#cae682!important}.highlight .vg{color:#cae682!important}.highlight .vi{color:#cae682!important}.highlight .il{color:#e5786d!important}.demo-color-blue-1::before{background-color:var(--color-blue-1)}.demo-color-blue-2::before{background-color:var(--color-blue-2)}.demo-color-blue-3::before{background-color:var(--color-blue-3)}.demo-color-blue-4::before{background-color:var(--color-blue-4)}.demo-color-blue-5::before{background-color:var(--color-blue-5)}.demo-color-blue-6::before{background-color:var(--color-blue-6)}.demo-color-blue-7::before{background-color:var(--color-blue-7)}.demo-color-red-1::before{background-color:var(--color-red-1)}.demo-color-red-2::before{background-color:var(--color-red-2)}.demo-color-red-3::before{background-color:var(--color-red-3)}.demo-color-red-4::before{background-color:var(--color-red-4)}.demo-color-red-5::before{background-color:var(--color-red-5)}.demo-color-red-6::before{background-color:var(--color-red-6)}.demo-color-red-7::before{background-color:var(--color-red-7)}.demo-color-green-1::before{background-color:var(--color-green-1)}.demo-color-green-2::before{background-color:var(--color-green-2)}.demo-color-green-3::before{background-color:var(--color-green-3)}.demo-color-green-4::before{background-color:var(--color-green-4)}.demo-color-green-5::before{background-color:var(--color-green-5)}.demo-color-green-6::before{background-color:var(--color-green-6)}.demo-color-green-7::before{background-color:var(--color-green-7)}.demo-color-magenta-1::before{background-color:var(--color-magenta-1)}.demo-color-magenta-2::before{background-color:var(--color-magenta-2)}.demo-color-magenta-3::before{background-color:var(--color-magenta-3)}.demo-color-magenta-4::before{background-color:var(--color-magenta-4)}.demo-color-magenta-5::before{background-color:var(--color-magenta-5)}.demo-color-magenta-6::before{background-color:var(--color-magenta-6)}.demo-color-magenta-7::before{background-color:var(--color-magenta-7)}.demo-color-orange-1::before{background-color:var(--color-orange-1)}.demo-color-orange-2::before{background-color:var(--color-orange-2)}.demo-color-orange-3::before{background-color:var(--color-orange-3)}.demo-color-orange-4::before{background-color:var(--color-orange-4)}.demo-color-orange-5::before{background-color:var(--color-orange-5)}.demo-color-orange-6::before{background-color:var(--color-orange-6)}.demo-color-orange-7::before{background-color:var(--color-orange-7)}.demo-color-yellow-1::before{background-color:var(--color-yellow-1)}.demo-color-yellow-2::before{background-color:var(--color-yellow-2)}.demo-color-yellow-3::before{background-color:var(--color-yellow-3)}.demo-color-yellow-4::before{background-color:var(--color-yellow-4)}.demo-color-yellow-5::before{background-color:var(--color-yellow-5)}.demo-color-yellow-6::before{background-color:var(--color-yellow-6)}.demo-color-yellow-7::before{background-color:var(--color-yellow-7)}.demo-color-teal-1::before{background-color:var(--color-teal-1)}.demo-color-teal-2::before{background-color:var(--color-teal-2)}.demo-color-teal-3::before{background-color:var(--color-teal-3)}.demo-color-teal-4::before{background-color:var(--color-teal-4)}.demo-color-teal-5::before{background-color:var(--color-teal-5)}.demo-color-teal-6::before{background-color:var(--color-teal-6)}.demo-color-teal-7::before{background-color:var(--color-teal-7)}.demo-color-lime-1::before{background-color:var(--color-lime-1)}.demo-color-lime-2::before{background-color:var(--color-lime-2)}.demo-color-lime-3::before{background-color:var(--color-lime-3)}.demo-color-lime-4::before{background-color:var(--color-lime-4)}.demo-color-lime-5::before{background-color:var(--color-lime-5)}.demo-color-lime-6::before{background-color:var(--color-lime-6)}.demo-color-lime-7::before{background-color:var(--color-lime-7)}.demo-color-neutral-0::before{background-color:var(--color-neutral-0);outline:1px dashed var(--color-neutral-3)}.demo-color-neutral-1::before{background-color:var(--color-neutral-1)}.demo-color-neutral-2::before{background-color:var(--color-neutral-2)}.demo-color-neutral-3::before{background-color:var(--color-neutral-3)}.demo-color-neutral-4::before{background-color:var(--color-neutral-4)}.demo-color-neutral-5::before{background-color:var(--color-neutral-5)}.demo-color-neutral-6::before{background-color:var(--color-neutral-6)}.demo-color-neutral-7::before{background-color:var(--color-neutral-7)}.demo-color-neutral-8::before{background-color:var(--color-neutral-8)}.demo-color-background-primary::before{background-color:var(--color-background-primary);border:1px solid var(--color-stroke-default)}.demo-color-background-secondary::before{background-color:var(--color-background-secondary)}.demo-color-background-disabled::before{background-color:var(--color-background-disabled)}.demo-color-background-inverse::before{background-color:var(--color-background-inverse)}.demo-color-background-attention::before{background-color:var(--color-background-attention)}.demo-color-background-confirmation::before{background-color:var(--color-background-confirmation)}.demo-color-background-information::before{background-color:var(--color-background-information)}.demo-color-background-accent::before{background-color:var(--color-background-accent)}.demo-color-background-invalid::before{background-color:var(--color-background-invalid)}.demo-color-foreground-primary::before{background-color:var(--color-foreground-primary)}.demo-color-foreground-secondary::before{background-color:var(--color-foreground-secondary)}.demo-color-foreground-disabled::before{background-color:var(--color-foreground-disabled)}.demo-color-foreground-attention::before{background-color:var(--color-foreground-attention)}.demo-color-foreground-confirmation::before{background-color:var(--color-foreground-confirmation)}.demo-color-foreground-information::before{background-color:var(--color-foreground-information)}.demo-color-foreground-accent::before{background-color:var(--color-foreground-accent)}.demo-color-foreground-visited::before{background-color:var(--color-foreground-visited)}.demo-color-foreground-on-primary::before{background-color:var(--color-foreground-on-primary)}.demo-color-foreground-on-secondary::before{background-color:var(--color-foreground-on-secondary)}.demo-color-foreground-on-disabled::before{background-color:var(--color-foreground-on-disabled)}.demo-color-foreground-on-inverse::before{background-color:var(--color-foreground-on-inverse);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-attention::before{background-color:var(--color-foreground-on-attention);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-confirmation::before{background-color:var(--color-foreground-on-confirmation);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-information::before{background-color:var(--color-foreground-on-information);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-accent::before{background-color:var(--color-foreground-on-accent);border:1px solid var(--color-stroke-default)}.demo-color-stroke-default::before{background-color:var(--color-stroke-default)}.demo-color-stroke-accent::before{background-color:var(--color-stroke-accent)}.demo-color-stroke-attention::before{background-color:var(--color-stroke-attention)}.demo-color-stroke-confirmation::before{background-color:var(--color-stroke-confirmation)}.demo-color-stroke-information::before{background-color:var(--color-stroke-information)}.demo-color-stroke-disabled::before{background-color:var(--color-stroke-disabled)}.demo-color-stroke-strong::before{background-color:var(--color-stroke-strong)}.demo-color-stroke-subtle::before{background-color:var(--color-stroke-subtle)}.demo-color-state-visited::before{background-color:var(--color-state-visited)}.demo-color-state-primary-hover::before{background-color:var(--color-state-primary-hover)}.demo-color-state-primary-active::before{background-color:var(--color-state-primary-active)}.demo-color-state-secondary-hover::before{background-color:var(--color-state-secondary-hover)}.demo-color-state-secondary-active::before{background-color:var(--color-state-secondary-active)}.demo-color-state-inverse-hover::before{background-color:var(--color-state-inverse-hover)}.demo-color-state-inverse-active::before{background-color:var(--color-state-inverse-active)}.demo-color-state-accent-hover::before{background-color:var(--color-state-accent-hover)}.demo-color-state-accent-active::before{background-color:var(--color-state-accent-active)}.demo-color-state-attention-hover::before{background-color:var(--color-state-attention-hover)}.demo-color-state-attention-active::before{background-color:var(--color-state-attention-active)}.demo-color-scrim-image::before{background-color:var(--color-scrim-image)}.demo-color-scrim-background::before{background-color:var(--color-scrim-background)}.demo-color-ai-gradient-full-spectrum::before{background:var(--color-ai-gradient-full-spectrum)}.demo-color-ai-gradient-green-strong::before{background:var(--color-ai-gradient-green-strong)}.demo-color-ai-gradient-blue-strong::before{background:var(--color-ai-gradient-blue-strong)}.demo-color-ai-gradient-purple-strong::before{background:var(--color-ai-gradient-purple-strong)}.demo-color-ai-gradient-green-subtle::before{background:var(--color-ai-gradient-green-subtle)}.demo-color-ai-gradient-blue-subtle::before{background:var(--color-ai-gradient-blue-subtle)}.demo-color-ai-gradient-purple-subtle::before{background:var(--color-ai-gradient-purple-subtle)}.content{grid-area:1/1/span 1/span 8}main{grid-area:1/1/span 1/span 8}footer{grid-area:2/1/span 1/span 8}@media screen and (min-width:512px){.site-nav{grid-area:1/1/span 1/span 5}.content{grid-area:1/1/span 1/span 16}main{grid-area:1/6/span 1/span 11}footer{grid-area:2/1/span 1/span 16}}@media screen and (min-width:768px){.site-nav{grid-area:1/1/span 1/span 3}.content{grid-area:1/1/span 1/span 16}main{grid-area:1/4/span 1/span 13}footer{grid-area:2/1/span 1/span 16}}@media screen and (min-width:1280px){.site-nav{grid-area:1/1/span 1/span 2}main{grid-area:1/3/span 1/span 14}}body{margin:0}body>svg{height:0;position:absolute;width:0}header{background-color:var(--color-background-accent)}footer{margin-top:var(--spacing-400)}main>div>h2{font-size:var(--font-size-large-1);margin-bottom:var(--spacing-100);margin-top:var(--spacing-300);padding-top:var(--spacing-100)}main>div>h3{font-size:var(--font-size-medium)}div.highlight{background-color:var(--color-background-tertiary);padding:var(--spacing-200)}span.highlight{background-color:#eee;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}span.highlight .s{word-break:break-all;word-wrap:break-word}figure.highlight{box-sizing:border-box;font-size:12px;margin:var(--spacing-100) 0;width:100%}figure.highlight pre{font-family:monospace;margin:0;padding:var(--spacing-100) var(--spacing-100) 0}figure.highlight code{white-space:pre-wrap}.skin-graphic{box-sizing:border-box;display:block;margin:var(--spacing-800) auto 0 auto;max-width:600px;width:100%}.modules-expander{background:var(--color-neutral-2);font-size:var(--font-size-medium);padding:4px var(--spacing-200)}.modules-expander__tip{color:var(--color-neutral-8);display:none;font-size:var(--font-size-default);font-style:italic;margin-left:var(--spacing-200)}.modules-expander__list{column-count:3;line-height:1.75em;list-style-type:none;margin:0;padding:0;width:100%}.modules-expander[open]{padding-bottom:var(--spacing-100)}.modules-expander[open] .modules-expander__tip{display:inline-block}.modules-expander__list a{text-decoration:none}.modules-expander .details__summary{padding:var(--spacing-100) 0}.app-bar{align-items:center;box-sizing:border-box;color:var(--color-neutral-0);display:flex;grid-area:1/1/span 1/span 8;justify-content:space-between;margin:0 auto;padding:var(--spacing-200) 0;width:100%}@media screen and (min-width:768px){.app-bar{grid-area:1/1/span 1/span 16}}.app-bar__title{font-size:var(--font-size-large-2);margin:0}.app-bar__links{display:flex;flex-direction:row;flex-shrink:0;list-style-type:none;margin-left:var(--spacing-100);padding:0}.app-bar__links li:not(:last-child)::after{content:'';margin:0 var(--spacing-100)}.app-bar__links a{color:var(--color-neutral-0);text-decoration:none}.modules-expander__list a:visited{color:var(--color-foreground-accent)}.app-bar__links a:hover{text-decoration:underline}.app-bar__links a:focus{outline:1px auto var(--color-neutral-0)}.app-bar__links a:visited{color:var(--color-neutral-0)}.section-header{display:flex;margin:var(--spacing-200) 0}.section-header h2{font-size:var(--font-size-large-1);margin:0}.section-header__version{align-self:flex-end;background-color:var(--color-neutral-1);margin-left:auto;padding:2px 4px}#about dl{margin:16px 0 32px}#about dt{font-weight:700;margin:0 0 12px}#about dd{margin:0 0 12px}.demo{border:1px dashed var(--color-neutral-2)}.demo__inner{margin:var(--spacing-100)}span.demo,span.demo__inner{display:inline-block}.demo-color-primitive{column-count:2}.demo-icon-header{margin:10px 5px 0}.demo-color-primitive,.demo-color-swatches,.demo-color-token,.demo-flag-boxes,.demo-icon-boxes{list-style:none;margin:0;padding:0}.color-swatch,.demo-color-primitive li::before,.demo-color-token li::before{border-radius:4px;content:'';display:inline-block;height:2em;margin-bottom:4px;margin-right:8px;vertical-align:middle;width:50px}.color-swatch{background-color:currentColor}.demo-typography{list-style:none;margin:0;padding:0}.demo-typography li{margin:1rem 0}.carousel__list--default-demo li{background-color:var(--color-blue-1);border-radius:var(--border-radius-50);color:var(--color-foreground-primary);font-size:var(--font-size-large-2);font-weight:700;height:120px;line-height:120px;margin-right:var(--spacing-200);text-align:center;width:200px}.carousel__list--discrete-demo li{background-color:var(--color-blue-1);border-radius:var(--border-radius-50);box-sizing:border-box;color:var(--color-foreground-primary);font-size:var(--font-size-large-2);font-weight:700;height:120px;line-height:120px;margin-right:var(--spacing-200);text-align:center;width:calc(25% - 24px)}.carousel__list--slideshow-demo li{background-color:var(--color-blue-1);border-radius:var(--border-radius-50);color:var(--color-foreground-primary);font-size:var(--font-size-giant-2);font-weight:700;height:300px;line-height:300px;margin-right:var(--spacing-200);text-align:center;width:100%}.carousel__list--discrete-demo li:last-child,.carousel__list--slideshow-demo li:last-child{margin-right:0}.striped-table{border:1px solid var(--color-stroke-subtle);border-spacing:0;width:100%}.striped-table th{text-transform:uppercase}.striped-table th:first-child{width:175px}.striped-table td,.striped-table th{padding:var(--spacing-100);text-align:left}.striped-table tbody tr:nth-child(odd){background-color:var(--color-background-secondary)}.striped-table td{border-top:1px solid var(--color-stroke-subtle)}.demo-typography-giant-3{font-size:var(--font-size-giant-3);font-weight:var(--font-weight-bold);line-height:52px}.demo-typography-giant-2{font-size:var(--font-size-giant-2);font-weight:var(--font-weight-bold);line-height:46px}.demo-typography-giant-1{font-size:var(--font-size-giant-1);font-weight:var(--font-weight-bold);line-height:40px}.demo-typography-large-2{font-size:var(--font-size-large-2);font-weight:var(--font-weight-bold);line-height:32px}.demo-typography-large-2-secondary{font-size:var(--font-size-large-2);font-weight:var(--font-weight-bold);line-height:32px;color:var(--color-foreground-secondary)}.demo-typography-large-1{font-size:var(--font-size-large-1);font-weight:var(--font-weight-bold);line-height:28px}.demo-typography-large-1-secondary{font-size:var(--font-size-large-1);font-weight:var(--font-weight-bold);line-height:28px;color:var(--color-foreground-secondary)}.demo-typography-medium-bold{font-size:var(--font-size-medium);line-height:24px;font-weight:var(--font-weight-bold)}.demo-typography-medium{font-size:var(--font-size-medium);line-height:24px}.demo-typography-medium-secondary{font-size:var(--font-size-medium);line-height:24px;color:var(--color-foreground-secondary)}.demo-typography-regular-bold{font-size:var(--font-size-default);line-height:20px;font-weight:var(--font-weight-bold)}.demo-typography-regular{font-size:var(--font-size-default);line-height:20px}.demo-typography-regular-secondary{font-size:var(--font-size-default);line-height:20px;color:var(--color-foreground-secondary)}.demo-typography-small-bold{font-size:var(--font-size-small);line-height:16px;font-weight:var(--font-weight-bold)}.demo-typography-small{font-size:var(--font-size-small);line-height:16px}.demo-typography-small-secondary{font-size:var(--font-size-small);line-height:16px;color:var(--color-foreground-secondary)}.demo-flag-boxes li,.demo-icon-boxes li{align-items:center;background-color:var(--color-background-secondary);border:1px solid var(--color-neutral-3);display:inline-flex;flex-direction:column;font-size:var(--font-size-small);height:100px;justify-content:space-around;list-style-type:none;margin:4px 2px;padding:4px;text-align:center;vertical-align:middle;width:100px}.demo-icon-boxes li.demo-icon-box--large{width:218px}.demo-flag-boxes li{height:140px}span.icon{background-repeat:no-repeat;background-size:contain;display:inline-block;vertical-align:middle}.eek-table{border-collapse:collapse;margin:var(--spacing-300) 0;width:100%}.eek-table td,.eek-table th{padding:var(--spacing-100);text-align:left}.eek-table th{background-color:var(--color-background-tertiary)}.eek-table td{border-bottom:1px solid #eee}.eek__rating-range{background-color:var(--color-background-primary);color:var(--color-foreground-primary)}.site-nav{display:none}@media screen and (min-width:512px){.modules-expander{display:none}.site-nav{display:block}}@media screen and (min-width:768px){.site-nav{height:100vh;margin-bottom:var(--spacing-800);overflow-y:scroll;position:sticky;top:0}.site-nav h2{color:var(--color-neutral-5);font-size:var(--font-size-large-1);margin-bottom:var(--spacing-100);margin-top:var(--spacing-200);text-transform:uppercase}.site-nav h2:first-of-type{margin-top:var(--spacing-400)}.site-nav ul{line-height:1.5em;list-style-type:none;margin:0;padding:0}.site-nav ul:last-child{padding-bottom:var(--spacing-400)}.site-nav a{text-decoration:none}.site-nav a:visited{color:var(--color-foreground-primary)}.demo-color-primitve li::before,.demo-color-token li::before{display:inline-block;width:50px}}@media screen and (min-width:1280px){#about dl{column-count:2}.demo-color-primitive{column-count:4}.demo-color-swatches,.demo-color-token{column-count:2}}@media screen and (min-width:1680px){.app-bar{padding-left:0;padding-right:0}.demo-color-primitive{column-count:5}.demo-color-swatches,.demo-color-token{column-count:3}}@media (prefers-color-scheme:dark){header{background-color:var(--color-foreground-accent)}a.demo-link-visited{color:var(--color-state-visited)}a.demo-link-visited:link,a.demo-link-visited:visited{color:var(--color-state-visited)}.section-header__version,span.highlight{background-color:var(--color-neutral-6)}.site-nav a,.site-nav a:visited{color:var(--color-foreground-primary)}.site-nav a:hover{color:var(--color-foreground-primary)}}
\ No newline at end of file
+/*! Wombat VIM theme */.highlight pre,.highlight table,figure .highlight{background:#242424!important;color:#f6f3e8!important}.highlight .hll{background-color:#ffc!important}.highlight .c{color:#99968b!important;font-style:italic!important}.highlight .err{color:#f6f3e8!important}.highlight .g{color:#f6f3e8!important}.highlight .k{color:#8ac6f2!important}.highlight .l{color:#f6f3e8!important}.highlight .h,.highlight .n{color:#f6f3e8!important}.highlight .o{color:#f6f3e8!important}.highlight .x{color:#f6f3e8!important}.highlight .p{color:#f6f3e8!important}.highlight .cm{color:#99968b!important;font-style:italic!important}.highlight .cp{color:#e5786d!important}.highlight .c1{color:#99968b!important;font-style:italic!important}.highlight .cs{color:#99968b!important;font-style:italic!important}.highlight .gd{color:#f6f3e8!important}.highlight .ge{color:#f6f3e8!important}.highlight .gr{color:#f6f3e8!important}.highlight .gh{color:#f6f3e8!important;font-weight:700!important}.highlight .gi{color:#f6f3e8!important}.highlight .go{color:grey!important;background-color:#303030!important}.highlight .gp{color:#f6f3e8!important}.highlight .gs{color:#f6f3e8!important}.highlight .gu{color:#f6f3e8!important;font-weight:700!important}.highlight .gt{color:#f6f3e8!important}.highlight .kc{color:#8ac6f2!important}.highlight .kd{color:#8ac6f2!important}.highlight .kn{color:#8ac6f2!important}.highlight .kp{color:#8ac6f2!important}.highlight .kr{color:#8ac6f2!important}.highlight .kt{color:#cae682!important}.highlight .ld{color:#f6f3e8!important}.highlight .m{color:#e5786d!important}.highlight .s{color:#95e454!important;font-style:italic!important}.highlight .na{color:#cae682!important}.highlight .nb{color:#f6f3e8!important}.highlight .nc{color:#f6f3e8!important}.highlight .no{color:#e5786d!important}.highlight .nd{color:#f6f3e8!important}.highlight .ni{color:#e7f6da!important}.highlight .ne{color:#f6f3e8!important}.highlight .nf{color:#cae682!important}.highlight .nl{color:#f6f3e8!important}.highlight .nn{color:#f6f3e8!important}.highlight .nx{color:#f6f3e8!important}.highlight .py{color:#f6f3e8!important}.highlight .nt{color:#8ac6f2!important}.highlight .nv{color:#cae682!important}.highlight .ow{color:#f6f3e8!important}.highlight .w{color:#f6f3e8!important}.highlight .mf{color:#e5786d!important}.highlight .mh{color:#e5786d!important}.highlight .mi{color:#e5786d!important}.highlight .mo{color:#e5786d!important}.highlight .sb{color:#95e454!important;font-style:italic!important}.highlight .sc{color:#95e454!important;font-style:italic!important}.highlight .sd{color:#95e454!important;font-style:italic!important}.highlight .s2{color:#95e454!important;font-style:italic!important}.highlight .se{color:#95e454!important;font-style:italic!important}.highlight .sh{color:#95e454!important;font-style:italic!important}.highlight .si{color:#95e454!important;font-style:italic!important}.highlight .sx{color:#95e454!important;font-style:italic!important}.highlight .sr{color:#95e454!important;font-style:italic!important}.highlight .s1{color:#95e454!important;font-style:italic!important}.highlight .ss{color:#95e454!important;font-style:italic!important}.highlight .bp{color:#f6f3e8!important}.highlight .vc{color:#cae682!important}.highlight .vg{color:#cae682!important}.highlight .vi{color:#cae682!important}.highlight .il{color:#e5786d!important}.demo-color-blue-1::before{background-color:var(--color-blue-1)}.demo-color-blue-2::before{background-color:var(--color-blue-2)}.demo-color-blue-3::before{background-color:var(--color-blue-3)}.demo-color-blue-4::before{background-color:var(--color-blue-4)}.demo-color-blue-5::before{background-color:var(--color-blue-5)}.demo-color-blue-6::before{background-color:var(--color-blue-6)}.demo-color-blue-7::before{background-color:var(--color-blue-7)}.demo-color-red-1::before{background-color:var(--color-red-1)}.demo-color-red-2::before{background-color:var(--color-red-2)}.demo-color-red-3::before{background-color:var(--color-red-3)}.demo-color-red-4::before{background-color:var(--color-red-4)}.demo-color-red-5::before{background-color:var(--color-red-5)}.demo-color-red-6::before{background-color:var(--color-red-6)}.demo-color-red-7::before{background-color:var(--color-red-7)}.demo-color-green-1::before{background-color:var(--color-green-1)}.demo-color-green-2::before{background-color:var(--color-green-2)}.demo-color-green-3::before{background-color:var(--color-green-3)}.demo-color-green-4::before{background-color:var(--color-green-4)}.demo-color-green-5::before{background-color:var(--color-green-5)}.demo-color-green-6::before{background-color:var(--color-green-6)}.demo-color-green-7::before{background-color:var(--color-green-7)}.demo-color-magenta-1::before{background-color:var(--color-magenta-1)}.demo-color-magenta-2::before{background-color:var(--color-magenta-2)}.demo-color-magenta-3::before{background-color:var(--color-magenta-3)}.demo-color-magenta-4::before{background-color:var(--color-magenta-4)}.demo-color-magenta-5::before{background-color:var(--color-magenta-5)}.demo-color-magenta-6::before{background-color:var(--color-magenta-6)}.demo-color-magenta-7::before{background-color:var(--color-magenta-7)}.demo-color-orange-1::before{background-color:var(--color-orange-1)}.demo-color-orange-2::before{background-color:var(--color-orange-2)}.demo-color-orange-3::before{background-color:var(--color-orange-3)}.demo-color-orange-4::before{background-color:var(--color-orange-4)}.demo-color-orange-5::before{background-color:var(--color-orange-5)}.demo-color-orange-6::before{background-color:var(--color-orange-6)}.demo-color-orange-7::before{background-color:var(--color-orange-7)}.demo-color-yellow-1::before{background-color:var(--color-yellow-1)}.demo-color-yellow-2::before{background-color:var(--color-yellow-2)}.demo-color-yellow-3::before{background-color:var(--color-yellow-3)}.demo-color-yellow-4::before{background-color:var(--color-yellow-4)}.demo-color-yellow-5::before{background-color:var(--color-yellow-5)}.demo-color-yellow-6::before{background-color:var(--color-yellow-6)}.demo-color-yellow-7::before{background-color:var(--color-yellow-7)}.demo-color-teal-1::before{background-color:var(--color-teal-1)}.demo-color-teal-2::before{background-color:var(--color-teal-2)}.demo-color-teal-3::before{background-color:var(--color-teal-3)}.demo-color-teal-4::before{background-color:var(--color-teal-4)}.demo-color-teal-5::before{background-color:var(--color-teal-5)}.demo-color-teal-6::before{background-color:var(--color-teal-6)}.demo-color-teal-7::before{background-color:var(--color-teal-7)}.demo-color-lime-1::before{background-color:var(--color-lime-1)}.demo-color-lime-2::before{background-color:var(--color-lime-2)}.demo-color-lime-3::before{background-color:var(--color-lime-3)}.demo-color-lime-4::before{background-color:var(--color-lime-4)}.demo-color-lime-5::before{background-color:var(--color-lime-5)}.demo-color-lime-6::before{background-color:var(--color-lime-6)}.demo-color-lime-7::before{background-color:var(--color-lime-7)}.demo-color-neutral-0::before{background-color:var(--color-neutral-0);outline:1px dashed var(--color-neutral-3)}.demo-color-neutral-1::before{background-color:var(--color-neutral-1)}.demo-color-neutral-2::before{background-color:var(--color-neutral-2)}.demo-color-neutral-3::before{background-color:var(--color-neutral-3)}.demo-color-neutral-4::before{background-color:var(--color-neutral-4)}.demo-color-neutral-5::before{background-color:var(--color-neutral-5)}.demo-color-neutral-6::before{background-color:var(--color-neutral-6)}.demo-color-neutral-7::before{background-color:var(--color-neutral-7)}.demo-color-neutral-8::before{background-color:var(--color-neutral-8)}.demo-color-background-primary::before{background-color:var(--color-background-primary);border:1px solid var(--color-stroke-default)}.demo-color-background-secondary::before{background-color:var(--color-background-secondary)}.demo-color-background-disabled::before{background-color:var(--color-background-disabled)}.demo-color-background-inverse::before{background-color:var(--color-background-inverse)}.demo-color-background-attention::before{background-color:var(--color-background-attention)}.demo-color-background-confirmation::before{background-color:var(--color-background-confirmation)}.demo-color-background-information::before{background-color:var(--color-background-information)}.demo-color-background-accent::before{background-color:var(--color-background-accent)}.demo-color-background-invalid::before{background-color:var(--color-background-invalid)}.demo-color-foreground-primary::before{background-color:var(--color-foreground-primary)}.demo-color-foreground-secondary::before{background-color:var(--color-foreground-secondary)}.demo-color-foreground-disabled::before{background-color:var(--color-foreground-disabled)}.demo-color-foreground-attention::before{background-color:var(--color-foreground-attention)}.demo-color-foreground-confirmation::before{background-color:var(--color-foreground-confirmation)}.demo-color-foreground-information::before{background-color:var(--color-foreground-information)}.demo-color-foreground-accent::before{background-color:var(--color-foreground-accent)}.demo-color-foreground-visited::before{background-color:var(--color-foreground-visited)}.demo-color-foreground-on-primary::before{background-color:var(--color-foreground-on-primary)}.demo-color-foreground-on-secondary::before{background-color:var(--color-foreground-on-secondary)}.demo-color-foreground-on-disabled::before{background-color:var(--color-foreground-on-disabled)}.demo-color-foreground-on-inverse::before{background-color:var(--color-foreground-on-inverse);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-attention::before{background-color:var(--color-foreground-on-attention);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-confirmation::before{background-color:var(--color-foreground-on-confirmation);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-information::before{background-color:var(--color-foreground-on-information);border:1px solid var(--color-stroke-default)}.demo-color-foreground-on-accent::before{background-color:var(--color-foreground-on-accent);border:1px solid var(--color-stroke-default)}.demo-color-stroke-default::before{background-color:var(--color-stroke-default)}.demo-color-stroke-accent::before{background-color:var(--color-stroke-accent)}.demo-color-stroke-attention::before{background-color:var(--color-stroke-attention)}.demo-color-stroke-confirmation::before{background-color:var(--color-stroke-confirmation)}.demo-color-stroke-information::before{background-color:var(--color-stroke-information)}.demo-color-stroke-disabled::before{background-color:var(--color-stroke-disabled)}.demo-color-stroke-strong::before{background-color:var(--color-stroke-strong)}.demo-color-stroke-subtle::before{background-color:var(--color-stroke-subtle)}.demo-color-state-visited::before{background-color:var(--color-state-visited)}.demo-color-state-primary-hover::before{background-color:var(--color-state-primary-hover)}.demo-color-state-primary-active::before{background-color:var(--color-state-primary-active)}.demo-color-state-secondary-hover::before{background-color:var(--color-state-secondary-hover)}.demo-color-state-secondary-active::before{background-color:var(--color-state-secondary-active)}.demo-color-state-inverse-hover::before{background-color:var(--color-state-inverse-hover)}.demo-color-state-inverse-active::before{background-color:var(--color-state-inverse-active)}.demo-color-state-accent-hover::before{background-color:var(--color-state-accent-hover)}.demo-color-state-accent-active::before{background-color:var(--color-state-accent-active)}.demo-color-state-attention-hover::before{background-color:var(--color-state-attention-hover)}.demo-color-state-attention-active::before{background-color:var(--color-state-attention-active)}.demo-color-scrim-image::before{background-color:var(--color-scrim-image)}.demo-color-scrim-background::before{background-color:var(--color-scrim-background)}.demo-color-ai-gradient-full-spectrum::before{background:var(--color-ai-gradient-full-spectrum)}.demo-color-ai-gradient-green-strong::before{background:var(--color-ai-gradient-green-strong)}.demo-color-ai-gradient-blue-strong::before{background:var(--color-ai-gradient-blue-strong)}.demo-color-ai-gradient-purple-strong::before{background:var(--color-ai-gradient-purple-strong)}.demo-color-ai-gradient-green-subtle::before{background:var(--color-ai-gradient-green-subtle)}.demo-color-ai-gradient-blue-subtle::before{background:var(--color-ai-gradient-blue-subtle)}.demo-color-ai-gradient-purple-subtle::before{background:var(--color-ai-gradient-purple-subtle)}.content{grid-area:1/1/span 1/span 8}main{grid-area:1/1/span 1/span 8}footer{grid-area:2/1/span 1/span 8}@media screen and (min-width:512px){.site-nav{grid-area:1/1/span 1/span 5}.content{grid-area:1/1/span 1/span 16}main{grid-area:1/6/span 1/span 11}footer{grid-area:2/1/span 1/span 16}}@media screen and (min-width:768px){.site-nav{grid-area:1/1/span 1/span 3}.content{grid-area:1/1/span 1/span 16}main{grid-area:1/4/span 1/span 13}footer{grid-area:2/1/span 1/span 16}}@media screen and (min-width:1280px){.site-nav{grid-area:1/1/span 1/span 2}main{grid-area:1/3/span 1/span 14}}body{margin:0}body>svg{height:0;position:absolute;width:0}header{background-color:var(--color-background-accent)}footer{margin-top:var(--spacing-400)}main>div>h2{font-size:var(--font-size-large-1);margin-bottom:var(--spacing-100);margin-top:var(--spacing-300);padding-top:var(--spacing-100)}main>div>h3{font-size:var(--font-size-medium)}div.highlight{background-color:var(--color-background-tertiary);padding:var(--spacing-200)}span.highlight{background-color:#eee;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace}span.highlight .s{word-break:break-all;word-wrap:break-word}figure.highlight{box-sizing:border-box;font-size:12px;margin:var(--spacing-100) 0;width:100%}figure.highlight pre{font-family:monospace;margin:0;padding:var(--spacing-100) var(--spacing-100) 0}figure.highlight code{white-space:pre-wrap}.skin-graphic{box-sizing:border-box;display:block;margin:var(--spacing-800) auto 0 auto;max-width:600px;width:100%}.modules-expander{background:var(--color-neutral-2);font-size:var(--font-size-medium);padding:4px var(--spacing-200)}.modules-expander__tip{color:var(--color-neutral-8);display:none;font-size:var(--font-size-default);font-style:italic;margin-left:var(--spacing-200)}.modules-expander__list{column-count:3;line-height:1.75em;list-style-type:none;margin:0;padding:0;width:100%}.modules-expander[open]{padding-bottom:var(--spacing-100)}.modules-expander[open] .modules-expander__tip{display:inline-block}.modules-expander__list a{text-decoration:none}.modules-expander .details__summary{padding:var(--spacing-100) 0}.app-bar{align-items:center;box-sizing:border-box;color:var(--color-neutral-0);display:flex;grid-area:1/1/span 1/span 8;justify-content:space-between;margin:0 auto;padding:var(--spacing-200) 0;width:100%}@media screen and (min-width:768px){.app-bar{grid-area:1/1/span 1/span 16}}.app-bar__title{font-size:var(--font-size-large-2);margin:0}.app-bar__links{display:flex;flex-direction:row;flex-shrink:0;list-style-type:none;margin-left:var(--spacing-100);padding:0}.app-bar__links li:not(:last-child)::after{content:'';margin:0 var(--spacing-100)}.app-bar__links a{color:var(--color-neutral-0);text-decoration:none}.modules-expander__list a:visited{color:var(--color-foreground-accent)}.app-bar__links a:hover{text-decoration:underline}.app-bar__links a:focus{outline:1px auto var(--color-neutral-0)}.app-bar__links a:visited{color:var(--color-neutral-0)}.section-header{display:flex;margin:var(--spacing-200) 0}.section-header h2{font-size:var(--font-size-large-1);margin:0}.section-header__version{align-self:flex-end;background-color:var(--color-neutral-1);margin-left:auto;padding:2px 4px}#about dl{margin:16px 0 32px}#about dt{font-weight:700;margin:0 0 12px}#about dd{margin:0 0 12px}.demo{border:1px dashed var(--color-neutral-2)}.demo__inner{margin:var(--spacing-100)}span.demo,span.demo__inner{display:inline-block}.demo-color-primitive{column-count:2}.demo-icon-header{margin:10px 5px 0}.demo-color-primitive,.demo-color-swatches,.demo-color-token,.demo-flag-boxes,.demo-icon-boxes{list-style:none;margin:0;padding:0}.color-swatch,.demo-color-primitive li::before,.demo-color-token li::before{border-radius:4px;content:'';display:inline-block;height:2em;margin-bottom:4px;margin-right:8px;vertical-align:middle;width:50px}.color-swatch{background-color:currentColor}.demo-typography{list-style:none;margin:0;padding:0}.demo-typography li{margin:1rem 0}.carousel__list--default-demo li{background-color:var(--color-blue-1);border-radius:var(--border-radius-50);color:var(--color-foreground-primary);font-size:var(--font-size-large-2);font-weight:700;height:120px;line-height:120px;margin-right:var(--spacing-200);text-align:center;width:200px}.carousel__list--discrete-demo li{background-color:var(--color-blue-1);border-radius:var(--border-radius-50);box-sizing:border-box;color:var(--color-foreground-primary);font-size:var(--font-size-large-2);font-weight:700;height:120px;line-height:120px;margin-right:var(--spacing-200);text-align:center;width:calc(25% - 24px)}.carousel__list--slideshow-demo li{background-color:var(--color-blue-1);border-radius:var(--border-radius-50);color:var(--color-foreground-primary);font-size:var(--font-size-giant-2);font-weight:700;height:300px;line-height:300px;margin-right:var(--spacing-200);text-align:center;width:100%}.carousel__list--discrete-demo li:last-child,.carousel__list--slideshow-demo li:last-child{margin-right:0}.striped-table{border:1px solid var(--color-stroke-subtle);border-spacing:0;width:100%}.striped-table th{text-transform:uppercase}.striped-table th:first-child{width:175px}.striped-table td,.striped-table th{padding:var(--spacing-100);text-align:left}.striped-table tbody tr:nth-child(odd){background-color:var(--color-background-secondary)}.striped-table td{border-top:1px solid var(--color-stroke-subtle)}.demo-typography-giant-3{font-size:var(--font-size-giant-3);font-weight:var(--font-weight-bold);line-height:52px}.demo-typography-giant-2{font-size:var(--font-size-giant-2);font-weight:var(--font-weight-bold);line-height:46px}.demo-typography-giant-1{font-size:var(--font-size-giant-1);font-weight:var(--font-weight-bold);line-height:40px}.demo-typography-large-2{font-size:var(--font-size-large-2);font-weight:var(--font-weight-bold);line-height:32px}.demo-typography-large-2-secondary{font-size:var(--font-size-large-2);font-weight:var(--font-weight-bold);line-height:32px;color:var(--color-foreground-secondary)}.demo-typography-large-1{font-size:var(--font-size-large-1);font-weight:var(--font-weight-bold);line-height:28px}.demo-typography-large-1-secondary{font-size:var(--font-size-large-1);font-weight:var(--font-weight-bold);line-height:28px;color:var(--color-foreground-secondary)}.demo-typography-medium-bold{font-size:var(--font-size-medium);line-height:24px;font-weight:var(--font-weight-bold)}.demo-typography-medium{font-size:var(--font-size-medium);line-height:24px}.demo-typography-medium-secondary{font-size:var(--font-size-medium);line-height:24px;color:var(--color-foreground-secondary)}.demo-typography-regular-bold{font-size:var(--font-size-default);line-height:20px;font-weight:var(--font-weight-bold)}.demo-typography-regular{font-size:var(--font-size-default);line-height:20px}.demo-typography-regular-secondary{font-size:var(--font-size-default);line-height:20px;color:var(--color-foreground-secondary)}.demo-typography-small-bold{font-size:var(--font-size-small);line-height:16px;font-weight:var(--font-weight-bold)}.demo-typography-small{font-size:var(--font-size-small);line-height:16px}.demo-typography-small-secondary{font-size:var(--font-size-small);line-height:16px;color:var(--color-foreground-secondary)}.demo-flag-boxes li,.demo-icon-boxes li{align-items:center;background-color:var(--color-background-secondary);border:1px solid var(--color-neutral-3);display:inline-flex;flex-direction:column;font-size:var(--font-size-small);height:100px;justify-content:space-around;list-style-type:none;margin:4px 2px;padding:4px;text-align:center;vertical-align:middle;width:100px}.demo-icon-boxes li.demo-icon-box--large{width:218px}.demo-flag-boxes li{height:140px}span.icon{background-repeat:no-repeat;background-size:contain;display:inline-block;vertical-align:middle}.eek-table,.skeleton-table,.skeleton-table-colors{border-collapse:collapse;margin:var(--spacing-300) 0;width:100%}.eek-table td,.eek-table th,.skeleton-table td,.skeleton-table th,.skeleton-table-colors td,.skeleton-table-colors th{padding:var(--spacing-100);text-align:left}.eek-table th,.skeleton-table th,.skeleton-table-colors th{background-color:var(--color-background-tertiary)}.eek-table td,.skeleton-table td,.skeleton-table-colors td{border-bottom:1px solid #eee}.eek__rating-range{background-color:var(--color-background-primary);color:var(--color-foreground-primary)}.site-nav{display:none}@media screen and (min-width:512px){.modules-expander{display:none}.site-nav{display:block}}@media screen and (min-width:768px){.site-nav{height:100vh;margin-bottom:var(--spacing-800);overflow-y:scroll;position:sticky;top:0}.site-nav h2{color:var(--color-neutral-5);font-size:var(--font-size-large-1);margin-bottom:var(--spacing-100);margin-top:var(--spacing-200);text-transform:uppercase}.site-nav h2:first-of-type{margin-top:var(--spacing-400)}.site-nav ul{line-height:1.5em;list-style-type:none;margin:0;padding:0}.site-nav ul:last-child{padding-bottom:var(--spacing-400)}.site-nav a{text-decoration:none}.site-nav a:visited{color:var(--color-foreground-primary)}.demo-color-primitve li::before,.demo-color-token li::before{display:inline-block;width:50px}}@media screen and (min-width:1280px){#about dl{column-count:2}.demo-color-primitive{column-count:4}.demo-color-swatches,.demo-color-token{column-count:2}}@media screen and (min-width:1680px){.app-bar{padding-left:0;padding-right:0}.demo-color-primitive{column-count:5}.demo-color-swatches,.demo-color-token{column-count:3}}@media (prefers-color-scheme:dark){header{background-color:var(--color-foreground-accent)}a.demo-link-visited{color:var(--color-state-visited)}a.demo-link-visited:link,a.demo-link-visited:visited{color:var(--color-state-visited)}.section-header__version,span.highlight{background-color:var(--color-neutral-6)}.site-nav a,.site-nav a:visited{color:var(--color-foreground-primary)}.site-nav a:hover{color:var(--color-foreground-primary)}}
\ No newline at end of file
diff --git a/src/less/bundles/skin-headless.less b/src/less/bundles/skin-headless.less
index 16d91a3d6..cae7f9df7 100644
--- a/src/less/bundles/skin-headless.less
+++ b/src/less/bundles/skin-headless.less
@@ -49,6 +49,7 @@
@import "../section-title/section-title.less";
@import "../segmented-buttons/segmented-buttons.less";
@import "../select/select.less";
+@import "../skeleton/skeleton.less";
@import "../snackbar-dialog/snackbar-dialog.less";
@import "../split-button/split-button.less";
@import "../star-rating/star-rating.less";
diff --git a/src/less/mixins/public/skeleton-mixins.less b/src/less/mixins/public/skeleton-mixins.less
new file mode 100644
index 000000000..f37f9fd49
--- /dev/null
+++ b/src/less/mixins/public/skeleton-mixins.less
@@ -0,0 +1,15 @@
+:root {
+ --skeleton-border-radius: 0;
+ --skeleton-height: 48px;
+ --skeleton-width: 100%;
+ --skeleton-background: var(--color-loading-fill);
+}
+
+.skeleton-base(@border-radius: var(--skeleton-border-radius), @height: var(--skeleton-height), @width: var(--skeleton-width) ) {
+ background: var(--skeleton-background);
+ border-radius: @border-radius;
+ cursor: progress;
+ height: @height;
+ min-height: 12px;
+ width: @width;
+}
diff --git a/src/less/skeleton/skeleton.less b/src/less/skeleton/skeleton.less
new file mode 100644
index 000000000..b516126de
--- /dev/null
+++ b/src/less/skeleton/skeleton.less
@@ -0,0 +1,190 @@
+@import "../variables/variables.less";
+@import "../mixins/public/skeleton-mixins.less";
+
+@skeleton-text-border-radius: 3px;
+@skeleton-text-height-small: 16px;
+@skeleton-text-height-large: 24px;
+
+.skeleton {
+ container-name: skeleton-container;
+ container-type: inline-size;
+}
+
+.skeleton__avatar {
+ .skeleton-base(50%, var(--skeleton-height), var(--skeleton-height));
+}
+
+.skeleton__button {
+ .skeleton-base(20px, 40px);
+}
+
+.skeleton__button--small {
+ .skeleton-base(16px, 32px);
+}
+
+.skeleton__button--large {
+ .skeleton-base(24px, 48px);
+}
+
+.skeleton__text {
+ .skeleton-base(@skeleton-text-border-radius, @skeleton-text-height-small, calc(100% - var(--spacing-300)));
+}
+
+.skeleton__text::after {
+ height: @skeleton-text-height-small;
+ margin-top: calc(@skeleton-text-height-small + var(--spacing-100));
+}
+
+.skeleton__text--large {
+ .skeleton-base(@skeleton-text-border-radius, @skeleton-text-height-large, calc(100% - var(--spacing-300)));
+}
+
+.skeleton__text--large::after {
+ height: @skeleton-text-height-large;
+ margin-top: calc(@skeleton-text-height-large + var(--spacing-100));
+}
+
+.skeleton__text--multiline {
+ margin-bottom: var(--spacing-300);
+ position: relative;
+ width: calc(100% - var(--spacing-300));
+}
+
+.skeleton__text--multiline::after {
+ background: inherit;
+ content: "";
+ position: absolute;
+ width: calc(100% - var(--spacing-700));
+}
+
+.skeleton__text--large.skeleton__text--multiline {
+ margin-bottom: var(--spacing-400);
+}
+
+.skeleton__textbox {
+ .skeleton-base(8px, 48px);
+}
+
+.skeleton__image {
+ .skeleton-base(8px, 100%);
+ max-width: initial;
+}
+
+// TODO: Use aspect-ratio : 1 / 1 to set as square when we have browser support, till then
+// using pseudo element to set as square
+.skeleton__image::after {
+ bottom: 0;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 100%;
+}
+
+span.skeleton__avatar,
+span.skeleton__button,
+span.skeleton__text,
+span.skeleton__image,
+span.skeleton__textbox {
+ display: inline-block;
+}
+
+span.skeleton__avatar + span,
+span.skeleton__button + span,
+span.skeleton__text + span,
+span.skeleton__image + span,
+span.skeleton__textbox + span {
+ margin-inline-start: var(--spacing-100);
+}
+
+div.skeleton__avatar,
+div.skeleton__button,
+div.skeleton__text,
+div.skeleton__image,
+div.skeleton__textbox {
+ margin-block-start: var(--spacing-150);
+}
+
+.skeleton--elevated {
+ --skeleton-background: var(--color-loading-fill-elevated);
+}
+
+@media screen and (max-width: @_screen-size-SM) {
+ .skeleton {
+ --skeleton-background: var(--color-loading-shimmer);
+ }
+ .skeleton--elevated {
+ --skeleton-background: var(--color-loading-shimmer-elevated);
+ }
+}
+
+.skeleton--purple {
+ --skeleton-background: var(--color-loading-ai-gradient-purple-subtle);
+}
+
+.skeleton--green {
+ --skeleton-background: var(--color-loading-ai-gradient-green-subtle);
+}
+
+.skeleton--blue {
+ --skeleton-background: var(--color-loading-ai-gradient-blue-subtle);
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ @keyframes loading-frames {
+ 0% {
+ background-position: 0% 0%;
+ }
+ 50% {
+ background-position: 45% 0%;
+ }
+ 100% {
+ background-position: 90% 0%;
+ }
+ }
+
+ @keyframes fade-in {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+ }
+
+ .skeleton__avatar,
+ .skeleton__button,
+ .skeleton__text,
+ .skeleton__image,
+ .skeleton__textbox {
+ /* setting animation-iteration-count to 6 (5000/833ms) */
+ /* so it does not exceed 5s per WCAG 2.2.2 */
+ animation:
+ fade-in 500ms forwards,
+ loading-frames 833ms 667ms linear 6;
+ animation-fill-mode: both;
+ background-size: 200%;
+ }
+}
+
+// A progressive enhancement to make the skeleton image rounded
+@container skeleton-container (width > 79px) {
+ .skeleton__image {
+ border-radius: 16px;
+ }
+}
+
+[dir="rtl"] {
+ .skeleton__avatar,
+ .skeleton__button,
+ .skeleton__text,
+ .skeleton__image,
+ .skeleton__textbox {
+ animation-direction: normal, reverse;
+ }
+
+ .skeleton__text--multiline::after {
+ left: var(--spacing-700);
+ }
+}
diff --git a/src/less/skeleton/stories/base.stories.js b/src/less/skeleton/stories/base.stories.js
new file mode 100644
index 000000000..012ec316b
--- /dev/null
+++ b/src/less/skeleton/stories/base.stories.js
@@ -0,0 +1,56 @@
+export default { title: "Skin/Skeleton/Base" };
+
+export const avatar = () =>
+ ``;
+
+export const button = () =>
+ ``;
+
+export const buttonSmall = () =>
+ ``;
+
+export const buttonLarge = () =>
+ ``;
+
+export const textSmall = () =>
+ ``;
+
+export const textLarge = () =>
+ ``;
+
+export const textSmallMultiLine = () =>
+ ``;
+
+export const textLargeMultiLine = () =>
+ ``;
+
+export const textBox = () =>
+ ``;
+
+export const smallImage = () =>
+ ``;
+
+export const image = () =>
+ ``;
diff --git a/src/less/skeleton/stories/composite.stories.js b/src/less/skeleton/stories/composite.stories.js
new file mode 100644
index 000000000..a9800f6a8
--- /dev/null
+++ b/src/less/skeleton/stories/composite.stories.js
@@ -0,0 +1,36 @@
+export default { title: "Skin/Skeleton/Composite" };
+
+export const tile = () =>
+ ``;
+
+export const inlineTiles = () =>
+ `
+
+
+
+
+
+
+
+
+
+
+
+
+
`;
+
+export const inlineSkeletons = () =>
+ `
+
+
+
`;
+
+export const blockSkeletons = () =>
+ ``;
diff --git a/src/less/skeleton/stories/rtl.stories.js b/src/less/skeleton/stories/rtl.stories.js
new file mode 100644
index 000000000..581f54a42
--- /dev/null
+++ b/src/less/skeleton/stories/rtl.stories.js
@@ -0,0 +1,7 @@
+export default { title: "Skin/Skeleton/RTL" };
+
+export const rtl = () =>
+ ``;
diff --git a/src/less/variables/variables.less b/src/less/variables/variables.less
index af14c8f8d..0faf8c987 100644
--- a/src/less/variables/variables.less
+++ b/src/less/variables/variables.less
@@ -57,6 +57,7 @@
@spacing-400: @spacing-100 * 4;
@spacing-450: @spacing-100 * 4.5;
@spacing-600: @spacing-100 * 6;
+@spacing-700: @spacing-100 * 7;
@spacing-800: @spacing-100 * 8;
@font-size-giant-3: @font-size-46;
diff --git a/src/tokens/evo-core.css b/src/tokens/evo-core.css
index 15638a4fb..974c20ccf 100644
--- a/src/tokens/evo-core.css
+++ b/src/tokens/evo-core.css
@@ -121,5 +121,6 @@
--spacing-400: 32px;
--spacing-450: 36px;
--spacing-600: 48px;
+ --spacing-700: 56px;
--spacing-800: 64px;
}
diff --git a/src/tokens/evo-dark.css b/src/tokens/evo-dark.css
index 4a1065606..c41e2eb16 100644
--- a/src/tokens/evo-dark.css
+++ b/src/tokens/evo-dark.css
@@ -136,5 +136,47 @@
var(--color-ai-solid-green-subtle) 0%,
var(--color-ai-solid-blue-subtle) 154.5%
);
+ --color-loading-fill: #1b1b1b;
+ --color-loading-shimmer: linear-gradient(
+ 270deg,
+ var(--color-loading-fill) 0%,
+ var(--color-loading-fill) 34%,
+ #0e0e0e 50%,
+ var(--color-loading-fill) 66%,
+ var(--color-loading-fill) 100%
+ );
+ --color-loading-fill-elevated: #222;
+ --color-loading-shimmer-elevated: linear-gradient(
+ 270deg,
+ var(--color-loading-fill-elevated) 0%,
+ var(--color-loading-fill-elevated) 34%,
+ #1c1c1c 50%,
+ var(--color-loading-fill-elevated) 66%,
+ var(--color-loading-fill-elevated) 100%
+ );
+ --color-loading-ai-gradient-purple-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-red-subtle-dark) 0%,
+ var(--color-ai-solid-red-subtle-dark) 34%,
+ var(--color-ai-solid-purple-subtle-dark) 50%,
+ var(--color-ai-solid-red-subtle-dark) 66%,
+ var(--color-ai-solid-red-subtle-dark) 100%
+ );
+ --color-loading-ai-gradient-blue-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-blue-subtle-dark) 0%,
+ var(--color-ai-solid-blue-subtle-dark) 34%,
+ var(--color-ai-solid-purple-subtle-dark) 50%,
+ var(--color-ai-solid-blue-subtle-dark) 66%,
+ var(--color-ai-solid-blue-subtle-dark) 100%
+ );
+ --color-loading-ai-gradient-green-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-green-subtle-dark) 0%,
+ var(--color-ai-solid-green-subtle-dark) 34%,
+ var(--color-ai-solid-blue-subtle-dark) 50%,
+ var(--color-ai-solid-green-subtle-dark) 66%,
+ var(--color-ai-solid-green-subtle-dark) 100%
+ );
}
}
diff --git a/src/tokens/evo-light.css b/src/tokens/evo-light.css
index 063f94702..8562c292d 100644
--- a/src/tokens/evo-light.css
+++ b/src/tokens/evo-light.css
@@ -134,4 +134,39 @@
var(--color-ai-solid-green-subtle) 0%,
var(--color-ai-solid-blue-subtle) 154.5%
);
+ --color-loading-fill: #f2f2f2;
+ --color-loading-shimmer: linear-gradient(
+ 270deg,
+ var(--color-loading-fill) 0%,
+ var(--color-loading-fill) 34%,
+ #f8f8f8 50%,
+ var(--color-loading-fill) 66%,
+ var(--color-loading-fill) 100%
+ );
+ --color-loading-fill-elevated: var(--color-loading-fill);
+ --color-loading-shimmer-elevated: var(--color-loading-shimmer);
+ --color-loading-ai-gradient-purple-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-red-subtle) 0%,
+ var(--color-ai-solid-red-subtle) 34%,
+ var(--color-ai-solid-purple-subtle) 50%,
+ var(--color-ai-solid-red-subtle) 66%,
+ var(--color-ai-solid-red-subtle) 100%
+ );
+ --color-loading-ai-gradient-blue-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-blue-subtle) 0%,
+ var(--color-ai-solid-blue-subtle) 34%,
+ var(--color-ai-solid-purple-subtle) 50%,
+ var(--color-ai-solid-blue-subtle) 66%,
+ var(--color-ai-solid-blue-subtle) 100%
+ );
+ --color-loading-ai-gradient-green-subtle: linear-gradient(
+ 270deg,
+ var(--color-ai-solid-green-subtle) 0%,
+ var(--color-ai-solid-green-subtle) 34%,
+ var(--color-ai-solid-blue-subtle) 50%,
+ var(--color-ai-solid-green-subtle) 66%,
+ var(--color-ai-solid-green-subtle) 100%
+ );
}