diff --git a/README.md b/README.md
index b677a5611..89166e622 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,7 @@ Each layer does its bit to enforce and enhance accessibility. We consider this l
- [`ebay-segmented-buttons`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-segmented-buttons)
- [`ebay-select`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-select)
- [`ebay-signal`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-signal)
+- [`ebay-skeleton`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-skeleton)
- [`ebay-snackbar-dialog`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-snackbar-dialog)
- [`ebay-split-button`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-split-button)
- [`ebay-star-rating`](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-star-rating)
diff --git a/src/components/ebay-skeleton/README.md b/src/components/ebay-skeleton/README.md
new file mode 100644
index 000000000..af866ed32
--- /dev/null
+++ b/src/components/ebay-skeleton/README.md
@@ -0,0 +1,15 @@
+
+
+ ebay-skeleton
+
+
+ DS v1.0.0 [BETA]
+
+
+
+The Skeletons are simplified versions of layouts to indicate that information has not been fully loaded to improve the perceived performance.
+
+## Examples and Documentation
+
+- [Storybook](https://ebay.github.io/ebayui-core/?path=/docs/building-blocks-ebay-skeleton--documentation)
+- [Code Examples](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-skeleton/examples)
diff --git a/src/components/ebay-skeleton/components/ebay-skeleton-avatar/index.marko b/src/components/ebay-skeleton/components/ebay-skeleton-avatar/index.marko
new file mode 100644
index 000000000..3dfb37aeb
--- /dev/null
+++ b/src/components/ebay-skeleton/components/ebay-skeleton-avatar/index.marko
@@ -0,0 +1,15 @@
+import { processHtmlAttributes } from "../../../../common/html-attributes";
+import type { AttrClass } from "marko/tags-html";
+static var ignoredAttributes = ["as", "class"];
+
+static interface SkeletonAvatarInput extends Omit, `on${string}`> {
+ as?: Marko.NativeTags;
+ class?: AttrClass;
+}
+
+export interface Input extends WithNormalizedProps {}
+
+<${input.as || 'div'}
+ class=["skeleton__avatar", input.class]
+ ...processHtmlAttributes(input, ignoredAttributes)
+/>
diff --git a/src/components/ebay-skeleton/components/ebay-skeleton-button/index.marko b/src/components/ebay-skeleton/components/ebay-skeleton-button/index.marko
new file mode 100644
index 000000000..97a6bec66
--- /dev/null
+++ b/src/components/ebay-skeleton/components/ebay-skeleton-button/index.marko
@@ -0,0 +1,18 @@
+import { processHtmlAttributes } from "../../../../common/html-attributes";
+import type { AttrClass } from "marko/tags-html";
+static var ignoredAttributes = ["as", "class", "size"];
+
+static interface SkeletonButtonInput extends Omit, `on${string}`> {
+ as?: Marko.NativeTags;
+ class?: AttrClass;
+ size?: "small" | "large";
+}
+
+export interface Input extends WithNormalizedProps {}
+
+$ let sizeClass = input.size ? `skeleton__button--${input.size}` : "";
+
+<${input.as || "div"}
+ class=["skeleton__button", sizeClass, input.class]
+ ...processHtmlAttributes(input, ignoredAttributes)
+/>
diff --git a/src/components/ebay-skeleton/components/ebay-skeleton-image/index.marko b/src/components/ebay-skeleton/components/ebay-skeleton-image/index.marko
new file mode 100644
index 000000000..0367327be
--- /dev/null
+++ b/src/components/ebay-skeleton/components/ebay-skeleton-image/index.marko
@@ -0,0 +1,15 @@
+import { processHtmlAttributes } from "../../../../common/html-attributes";
+import type { AttrClass } from "marko/tags-html";
+static var ignoredAttributes = ["as", "class"];
+
+static interface SkeletonImageInput extends Omit, `on${string}`> {
+ as?: Marko.NativeTags;
+ class?: AttrClass;
+}
+
+export interface Input extends WithNormalizedProps {}
+
+<${input.as || 'div'}
+ class=["skeleton__image", input.class]
+ ...processHtmlAttributes(input, ignoredAttributes)
+/>
diff --git a/src/components/ebay-skeleton/components/ebay-skeleton-text/index.marko b/src/components/ebay-skeleton/components/ebay-skeleton-text/index.marko
new file mode 100644
index 000000000..616d2ec93
--- /dev/null
+++ b/src/components/ebay-skeleton/components/ebay-skeleton-text/index.marko
@@ -0,0 +1,24 @@
+import { processHtmlAttributes } from "../../../../common/html-attributes";
+import type { AttrClass } from "marko/tags-html";
+static var ignoredAttributes = ["as", "class", "size", "multiline"];
+
+static interface SkeletonTextInput extends Omit, `on${string}`> {
+ as?: Marko.NativeTags;
+ class?: AttrClass;
+ size?: "small" | "large";
+ multiline?: boolean;
+}
+
+export interface Input extends WithNormalizedProps {}
+
+$ const { size, multiline } = input;
+
+<${input.as || "div"}
+ class=[
+ "skeleton__text",
+ multiline && "skeleton__text--multiline",
+ size && size === "large" && `skeleton__text--large`,
+ input.class,
+ ]
+ ...processHtmlAttributes(input, ignoredAttributes)
+/>
diff --git a/src/components/ebay-skeleton/components/ebay-skeleton-textbox/index.marko b/src/components/ebay-skeleton/components/ebay-skeleton-textbox/index.marko
new file mode 100644
index 000000000..1356e9205
--- /dev/null
+++ b/src/components/ebay-skeleton/components/ebay-skeleton-textbox/index.marko
@@ -0,0 +1,15 @@
+import { processHtmlAttributes } from "../../../../common/html-attributes";
+import type { AttrClass } from "marko/tags-html";
+static var ignoredAttributes = ["as", "class"];
+
+static interface SkeletonTextBoxInput extends Omit, `on${string}`> {
+ as?: Marko.NativeTags;
+ class?: AttrClass;
+}
+
+export interface Input extends WithNormalizedProps {}
+
+<${input.as || 'div'}
+ class=["skeleton__textbox", input.class]
+ ...processHtmlAttributes(input, ignoredAttributes)
+/>
diff --git a/src/components/ebay-skeleton/examples/avatar.marko b/src/components/ebay-skeleton/examples/avatar.marko
new file mode 100644
index 000000000..0a3a683da
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/avatar.marko
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/components/ebay-skeleton/examples/button-small.marko b/src/components/ebay-skeleton/examples/button-small.marko
new file mode 100644
index 000000000..77d361d5b
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/button-small.marko
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/button.marko b/src/components/ebay-skeleton/examples/button.marko
new file mode 100644
index 000000000..0e75ceebc
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/button.marko
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/composite.marko b/src/components/ebay-skeleton/examples/composite.marko
new file mode 100644
index 000000000..e9340c14a
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/composite.marko
@@ -0,0 +1,19 @@
+
+
diff --git a/src/components/ebay-skeleton/examples/image.marko b/src/components/ebay-skeleton/examples/image.marko
new file mode 100644
index 000000000..25154beec
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/image.marko
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/text-multiline.marko b/src/components/ebay-skeleton/examples/text-multiline.marko
new file mode 100644
index 000000000..ac6acb90e
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/text-multiline.marko
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/text.marko b/src/components/ebay-skeleton/examples/text.marko
new file mode 100644
index 000000000..34c8f703f
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/text.marko
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/textbox.marko b/src/components/ebay-skeleton/examples/textbox.marko
new file mode 100644
index 000000000..8285b3a89
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/textbox.marko
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/tile.marko b/src/components/ebay-skeleton/examples/tile.marko
new file mode 100644
index 000000000..747630fc1
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/tile.marko
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/ebay-skeleton/examples/withContent.marko b/src/components/ebay-skeleton/examples/withContent.marko
new file mode 100644
index 000000000..1e0cfb7e4
--- /dev/null
+++ b/src/components/ebay-skeleton/examples/withContent.marko
@@ -0,0 +1,38 @@
+class {
+ onCreate() {
+ this.state = {
+ isLoading: true,
+ data: null,
+ };
+ }
+ async getData() {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => resolve("Button"), 2000);
+ });
+ }
+ async onMount() {
+ try {
+ this.state.data = await this.getData();
+ } catch (err) {
+ this.state.error = err;
+ } finally {
+ this.state.isLoading = false;
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+ ${state.data}
+
+
diff --git a/src/components/ebay-skeleton/index.marko b/src/components/ebay-skeleton/index.marko
new file mode 100644
index 000000000..042eaf55d
--- /dev/null
+++ b/src/components/ebay-skeleton/index.marko
@@ -0,0 +1,17 @@
+import { processHtmlAttributes } from "../../common/html-attributes";
+static var ignoredAttributes = ["a11yText", "class"];
+
+static interface SkeletonInput extends Omit, `on${string}`> {
+ "a11y-text"?: string;
+}
+
+export interface Input extends WithNormalizedProps {}
+
+
+ <${input.renderBody}/>
+
diff --git a/src/components/ebay-skeleton/marko-tag.json b/src/components/ebay-skeleton/marko-tag.json
new file mode 100644
index 000000000..5343b269a
--- /dev/null
+++ b/src/components/ebay-skeleton/marko-tag.json
@@ -0,0 +1,14 @@
+{
+ "attribute-groups": ["html-attributes"],
+ "@*": {
+ "targetProperty": null,
+ "type": "expression"
+ },
+ "@html-attributes": "expression",
+ "@role": "never",
+ "@size": {
+ "enum": ["small", "large"]
+ },
+ "@multiline": "boolean",
+ "@a11yText": "string"
+}
diff --git a/src/components/ebay-skeleton/skeleton.stories.ts b/src/components/ebay-skeleton/skeleton.stories.ts
new file mode 100644
index 000000000..ec9f998f6
--- /dev/null
+++ b/src/components/ebay-skeleton/skeleton.stories.ts
@@ -0,0 +1,125 @@
+import { tagToString } from "../../../.storybook/storybook-code-source";
+import {
+ addRenderBodies,
+ buildExtensionTemplate,
+} from "../../../.storybook/utils";
+import Component from "./index.marko";
+import Readme from "./README.md";
+import avatarTemplate from "./examples/avatar.marko";
+import avatarCode from "./examples/avatar.marko?raw";
+import buttonTemplate from "./examples/button.marko";
+import buttonCode from "./examples/button.marko?raw";
+import buttonSmallTemplate from "./examples/button-small.marko";
+import buttonSmallCode from "./examples/button-small.marko?raw";
+import textTemplate from "./examples/text.marko";
+import textCode from "./examples/text.marko?raw";
+import textMultilineTemplate from "./examples/text-multiline.marko";
+import textMultilineCode from "./examples/text-multiline.marko?raw";
+import textboxTemplate from "./examples/textbox.marko";
+import textboxCode from "./examples/textbox.marko?raw";
+import imageTemplate from "./examples/image.marko";
+import imageCode from "./examples/image.marko?raw";
+import tileTemplate from "./examples/tile.marko";
+import tileCode from "./examples/tile.marko?raw";
+import withContentTemplate from "./examples/withContent.marko";
+import withContentCode from "./examples/withContent.marko?raw";
+import compositeTemplate from "./examples/composite.marko";
+import compositeCode from "./examples/composite.marko?raw";
+
+const Template = (args) => ({
+ input: addRenderBodies(args),
+});
+
+export default {
+ title: "building blocks/ebay-skeleton",
+ component: Component,
+ parameters: {
+ docs: {
+ description: {
+ component: Readme,
+ },
+ },
+ },
+
+ argTypes: {
+ renderBody: {
+ control: { type: "text" },
+ },
+ a11yText: {
+ control: { type: "text" },
+ description:
+ "The localized accessibility text for the component. By default for english, Loading is used.",
+ table: {
+ defaultValue: {
+ summary: "Loading",
+ },
+ },
+ },
+ size: {
+ control: { type: "select" },
+ options: ["small", "large"],
+ table: {
+ defaultValue: {
+ summary: "default",
+ },
+ },
+ description:
+ "The Size of the component to render. Applicable for `ebay-skeleton-button` and `ebay-skeleton-text` only",
+ },
+ multiline: {
+ control: { type: "boolean" },
+ table: {
+ defaultValue: {
+ summary: false,
+ },
+ },
+ description:
+ "Boolean flag to make `ebay-skeleton-text` render more than one line",
+ },
+ },
+};
+
+export const Default = Template.bind({});
+Default.args = {
+ style: "width: 220px",
+ renderBody: ``,
+};
+Default.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-skeleton", Default.args),
+ },
+ },
+};
+
+export const Avatar = buildExtensionTemplate(avatarTemplate, avatarCode);
+
+export const Button = buildExtensionTemplate(buttonTemplate, buttonCode);
+
+export const ButtonSmall = buildExtensionTemplate(
+ buttonSmallTemplate,
+ buttonSmallCode,
+);
+
+export const Text = buildExtensionTemplate(textTemplate, textCode);
+
+export const TextMultiLine = buildExtensionTemplate(
+ textMultilineTemplate,
+ textMultilineCode,
+);
+
+export const TextBox = buildExtensionTemplate(textboxTemplate, textboxCode);
+
+export const Image = buildExtensionTemplate(imageTemplate, imageCode);
+
+export const Tile = buildExtensionTemplate(tileTemplate, tileCode);
+
+export const composite = buildExtensionTemplate(
+ compositeTemplate,
+ compositeCode,
+);
+
+export const withContent = buildExtensionTemplate(
+ withContentTemplate,
+ withContentCode,
+);
diff --git a/src/components/ebay-skeleton/style.ts b/src/components/ebay-skeleton/style.ts
new file mode 100644
index 000000000..32adaa1c5
--- /dev/null
+++ b/src/components/ebay-skeleton/style.ts
@@ -0,0 +1 @@
+import "@ebay/skin/skeleton";
diff --git a/src/components/ebay-skeleton/test/test.server.js b/src/components/ebay-skeleton/test/test.server.js
new file mode 100644
index 000000000..15f6fb810
--- /dev/null
+++ b/src/components/ebay-skeleton/test/test.server.js
@@ -0,0 +1,31 @@
+import { use } from "chai";
+import { composeStories } from "@storybook/marko";
+import { snapshotHTML } from "../../../common/test-utils/snapshots";
+import * as stories from "../skeleton.stories";
+
+const { Default, Avatar, Tile, Text, TextMultiLine } = composeStories(stories);
+const htmlSnap = snapshotHTML(__dirname);
+
+use(require("chai-dom"));
+
+describe("skeleton", () => {
+ it("renders default skeleton", async () => {
+ await htmlSnap(Default);
+ });
+
+ it("renders avatar", async () => {
+ await htmlSnap(Avatar);
+ });
+
+ it("renders tile", async () => {
+ await htmlSnap(Tile);
+ });
+
+ it("renders text", async () => {
+ await htmlSnap(Text);
+ });
+
+ it("renders text multiLine", async () => {
+ await htmlSnap(TextMultiLine);
+ });
+});