From 06746ec5f28379d05580bac36d64b8c7852910e0 Mon Sep 17 00:00:00 2001 From: Dan Cormier Date: Tue, 27 Jan 2026 13:33:31 -0500 Subject: [PATCH 1/7] Refactor loader to loading, match styles to spec --- .changeset/nine-gifts-learn.md | 4 +- MIGRATION_GUIDE.md | 4 +- .../lib/components/loader/loader.less | 61 ------------ .../loading.a11y.test.ts} | 0 .../lib/components/loading/loading.less | 78 +++++++++++++++ .../loading.visual.test.ts} | 0 .../stacks-classic/lib/stacks-static.less | 2 +- packages/stacks-docs/_data/loader.json | 19 ---- packages/stacks-docs/_data/loading.json | 25 +++++ .../stacks-docs/_data/site-navigation.json | 5 +- .../product/components/buttons.html | 9 +- .../product/components/loader.html | 73 -------------- .../product/components/loading.html | 94 +++++++++++++++++++ .../components/Button/Button.stories.svelte | 8 +- .../src/components/Button/Button.svelte | 16 ++-- .../src/components/Button/Button.test.ts | 13 ++- .../components/Loader/Loader.stories.svelte | 80 ---------------- .../src/components/Loader/Loader.test.ts | 44 --------- .../components/Loading/Loading.stories.svelte | 47 ++++++++++ .../Loader.svelte => Loading/Loading.svelte} | 19 +--- .../src/components/Loading/Loading.test.ts | 36 +++++++ .../stacks-svelte/src/components/index.ts | 2 +- 22 files changed, 319 insertions(+), 320 deletions(-) delete mode 100644 packages/stacks-classic/lib/components/loader/loader.less rename packages/stacks-classic/lib/components/{loader/loader.a11y.test.ts => loading/loading.a11y.test.ts} (100%) create mode 100644 packages/stacks-classic/lib/components/loading/loading.less rename packages/stacks-classic/lib/components/{loader/loader.visual.test.ts => loading/loading.visual.test.ts} (100%) delete mode 100644 packages/stacks-docs/_data/loader.json create mode 100644 packages/stacks-docs/_data/loading.json delete mode 100644 packages/stacks-docs/product/components/loader.html create mode 100644 packages/stacks-docs/product/components/loading.html delete mode 100644 packages/stacks-svelte/src/components/Loader/Loader.stories.svelte delete mode 100644 packages/stacks-svelte/src/components/Loader/Loader.test.ts create mode 100644 packages/stacks-svelte/src/components/Loading/Loading.stories.svelte rename packages/stacks-svelte/src/components/{Loader/Loader.svelte => Loading/Loading.svelte} (62%) create mode 100644 packages/stacks-svelte/src/components/Loading/Loading.test.ts diff --git a/.changeset/nine-gifts-learn.md b/.changeset/nine-gifts-learn.md index 6e364509a9..fef308563c 100644 --- a/.changeset/nine-gifts-learn.md +++ b/.changeset/nine-gifts-learn.md @@ -3,8 +3,8 @@ "@stackoverflow/stacks-svelte": minor --- -Update Loader (formerly known as Spinner) component to SHINE designs +Update Loading (formerly known as Spinner) component to SHINE designs BREAKING CHANGES: -- Spinner component has been replace with the Loader component \ No newline at end of file +- Spinner component has been replace with the Loading component \ No newline at end of file diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 55da23ce4c..fcf5ab0510 100755 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -67,8 +67,8 @@ - `s-input__xl` removed - **Nested inputs** html will require slight tweaking on consumers' side -#### Loader -- `Spinner` component replaced with new `Loader` component +#### Loading +- `Spinner` component replaced with new `Loading` component #### Menu diff --git a/packages/stacks-classic/lib/components/loader/loader.less b/packages/stacks-classic/lib/components/loader/loader.less deleted file mode 100644 index c39109cc46..0000000000 --- a/packages/stacks-classic/lib/components/loader/loader.less +++ /dev/null @@ -1,61 +0,0 @@ -.s-loader--block { - // BASE COMPONENT-SPECIFIC CUSTOM PROPERTIES - --_ld-size: var(--su-static24); - --_ld-block-size: calc(var(--su-static8) - var(--su-static1)); - --_ld-gap: calc(var(--su-static2) + var(--su-static1)); - --_ld-start-offset: var(--su-static2); - - // MODIFIERS - &&__sm { - --_ld-size: var(--su-static16); - --_ld-gap: var(--su-static2); - --_ld-start-offset: calc(var(--su-static2) + var(--su-static1)); - } - &&__lg { - --_ld-size: var(--su-static48); - --_ld-block-size: calc(var(--su-static4) + var(--su-static4)); - --_ld-start-offset: var(--su-static1); - } - - align-items: center; - display: flex; - height: var(--_ld-size); - justify-content: center; - position: relative; - width: var(--_ld-size); - - // Style the spot loading SVG to match container size - .svg-spot { - height: auto; - max-height: 100%; - max-width: 100%; - width: auto; - - rect { - height: var(--_ld-block-size); - width: var(--_ld-block-size); - } - - rect:nth-child(2) { - x: var(--_ld-start-offset); - } - - rect:nth-child(3) { - x: calc(var(--_ld-start-offset) + var(--_ld-block-size) + var(--_ld-gap)); - } - - rect:nth-child(4) { - x: calc(var(--_ld-start-offset) + var(--_ld-block-size) * 2 + var(--_ld-gap) * 2); - } - } - - // Inherit text color when inside a button - .s-btn & { - color: var(--_bu-fc); - .svg-spot { - rect { - fill: var(--_bu-fc) !important; - } - } - } -} \ No newline at end of file diff --git a/packages/stacks-classic/lib/components/loader/loader.a11y.test.ts b/packages/stacks-classic/lib/components/loading/loading.a11y.test.ts similarity index 100% rename from packages/stacks-classic/lib/components/loader/loader.a11y.test.ts rename to packages/stacks-classic/lib/components/loading/loading.a11y.test.ts diff --git a/packages/stacks-classic/lib/components/loading/loading.less b/packages/stacks-classic/lib/components/loading/loading.less new file mode 100644 index 0000000000..0650c04015 --- /dev/null +++ b/packages/stacks-classic/lib/components/loading/loading.less @@ -0,0 +1,78 @@ +.s-loading { + --_ld-color: var(--black-600); + --_ld-gap: calc(var(--_ld-size) / 2); + --_ld-size: calc(var(--su4) + var(--su1)); // 5px + --_ld-offset: calc(calc(var(--_ld-size) / 8) * -5); // -5/8ths of the size + + // MODIFIERS + &__sm { + --_ld-size: calc(calc(var(--su8) - var(--su1)) / 2); // 3.5px + margin-left: var(--su1); + margin-right: var(--su1); + } + + &__lg { + --_ld-size: var(--su8); + } + + // CHILD ELEMENTS + & &--block, + &:before, + &:after { + background-color: currentColor; + content: ""; + display: block; + height: var(--_ld-size); + width: var(--_ld-size); + + animation: loading-animation .8s cubic-bezier(1, 1, 0, 1) infinite; + } + + & &--block { + animation-delay: .25s; + } + + &:after { + animation-delay: .5s; + } + + display: flex; + gap: var(--_ld-gap); + margin-top: var(--_ld-gap); +} + +@media (prefers-reduced-motion:reduce){ + .s-loading { + & &--block, + &:before, + &:after { + animation: loading-animation-reduced-motion 2s ease-in-out infinite; + } + } +} + +@keyframes loading-animation { + 0%,1%,99%,to{ + opacity: 0.2; + transform: translateY(0); + } + 49%,50%{ + opacity: 1; + transform: translateY(var(--_ld-offset)); + } + 51%{ + opacity: 0.2; + transform: translateY(var(--_ld-offset)); + } +} + +@keyframes loading-animation-reduced-motion { + 0%,to{ + opacity: 0.3; + transform: none; + } + 50%{ + opacity: 1; + transform: none; + } +} \ No newline at end of file diff --git a/packages/stacks-classic/lib/components/loader/loader.visual.test.ts b/packages/stacks-classic/lib/components/loading/loading.visual.test.ts similarity index 100% rename from packages/stacks-classic/lib/components/loader/loader.visual.test.ts rename to packages/stacks-classic/lib/components/loading/loading.visual.test.ts diff --git a/packages/stacks-classic/lib/stacks-static.less b/packages/stacks-classic/lib/stacks-static.less index 0ec3510d8a..8dd7f44de7 100644 --- a/packages/stacks-classic/lib/stacks-static.less +++ b/packages/stacks-classic/lib/stacks-static.less @@ -42,7 +42,7 @@ @import "components/prose/prose.less"; @import "components/select/select.less"; @import "components/sidebar-widget/sidebar-widget.less"; -@import "components/loader/loader.less"; +@import "components/loading/loading.less"; @import "components/table/table.less"; @import "components/table-container/table-container.less"; @import "components/tag/tag.less"; diff --git a/packages/stacks-docs/_data/loader.json b/packages/stacks-docs/_data/loader.json deleted file mode 100644 index 2381db5a31..0000000000 --- a/packages/stacks-docs/_data/loader.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "loader": [ - { - "class": ".s-loader--block", - "applies": "N/A", - "description": "Base block loading style that displays three animated squares" - }, - { - "class": ".s-loader--block__sm", - "applies": ".s-loader--block", - "description": "A small style for compact layouts" - }, - { - "class": ".s-loader--block__lg", - "applies": ".s-loader--block", - "description": "A large style for the largest layouts" - } - ] -} diff --git a/packages/stacks-docs/_data/loading.json b/packages/stacks-docs/_data/loading.json new file mode 100644 index 0000000000..c496a27caa --- /dev/null +++ b/packages/stacks-docs/_data/loading.json @@ -0,0 +1,25 @@ +{ + "classes": [ + { + "class": ".s-loading", + "applies": "N/A", + "description": "Base class for the loading component" + }, + { + "class": ".s-loading--block", + "applies": ".s-loading", + "description": "Child necessary to render the center loading block" + }, + { + "class": ".s-loading__sm", + "applies": ".s-loading", + "description": "A small variant of the loading component" + }, + { + "class": ".s-loading__lg", + "applies": ".s-loading", + "description": "A large variant of the loading component" + } + ], + "sizes": ["s-loading__sm", "", "s-loading__lg"] +} diff --git a/packages/stacks-docs/_data/site-navigation.json b/packages/stacks-docs/_data/site-navigation.json index 84ca8c3f3c..e906ff7bab 100644 --- a/packages/stacks-docs/_data/site-navigation.json +++ b/packages/stacks-docs/_data/site-navigation.json @@ -287,8 +287,9 @@ "url": "/product/components/link-previews/" }, { - "title": "Loader", - "url": "/product/components/loader/" + "title": "Loading", + "url": "/product/components/loading/", + "new": true }, { "title": "Menus", diff --git a/packages/stacks-docs/product/components/buttons.html b/packages/stacks-docs/product/components/buttons.html index 77fa04c86b..5ecfcdc240 100644 --- a/packages/stacks-docs/product/components/buttons.html +++ b/packages/stacks-docs/product/components/buttons.html @@ -268,13 +268,13 @@
{% header "h2", "Loading" %} -

Any button can have a loading state applied by adding the .s-loader--block .s-loader--block__sm state class.

+

Indicate a loading state by adding a .s-loading component to a button.

{% highlight html %} - @@ -291,6 +291,7 @@ + {% for btn in buttons.variants %} {{ btn.title }} diff --git a/packages/stacks-docs/product/components/loader.html b/packages/stacks-docs/product/components/loader.html deleted file mode 100644 index ea9bfad66e..0000000000 --- a/packages/stacks-docs/product/components/loader.html +++ /dev/null @@ -1,73 +0,0 @@ ---- -layout: page -title: Loader -svelte: https://beta.svelte.stackoverflow.design/?path=/docs/components-loader--docs -description: "The Loader indicates an active wait state for a page, section, or interactive element." -tags: components ---- -
- {% header "h2", "Classes" %} -
- - - - - - - - - - {% for item in loader.loader %} - - - - - - {% endfor %} - -
ClassApplied toDescription
{{ item.class }}{% if item.applies == "N/A" %}{{ item.applies }}{% else %}{{ item.applies }}{% endif %}{{ item.description }}
-
-
-
- {% header "h2", "Examples" %} - {% header "h3", "Blocks" %} -

Use the Blocks variant as the standard loader for general UI states. This is the most common style and utilizes a monochrome black and gray palette.

-
-{% highlight html %} -
-
Loading…
- @Svg.Spot.Loading.With("native") -
-
-
Loading…
- @Svg.Spot.Loading.With("native") -
-
-
Loading…
- @Svg.Spot.Loading.With("native") -
-{% endhighlight %} -
-
-
-
-
Loading…
- {% spot "Loading", "native" %} -
-
-
-
-
Loading…
- {% spot "Loading", "native" %} -
-
-
-
-
Loading…
- {% spot "Loading", "native" %} -
-
-
-
-
-
diff --git a/packages/stacks-docs/product/components/loading.html b/packages/stacks-docs/product/components/loading.html new file mode 100644 index 0000000000..5819c39fb6 --- /dev/null +++ b/packages/stacks-docs/product/components/loading.html @@ -0,0 +1,94 @@ +--- +layout: page +title: Loading +svelte: https://beta.svelte.stackoverflow.design/?path=/docs/components-loading--docs +description: "The loading component indicates an active wait state for a page, section, or interactive element." +tags: components +--- +
+ {% header "h2", "Classes" %} +
+ + + + + + + + + + {% for item in loading.classes %} + + + + + + {% endfor %} + +
ClassApplied toDescription
{{ item.class }}{% if item.applies == "N/A" %}{{ item.applies }}{% else %}{{ item.applies }}{% endif %}{{ item.description }}
+
+
+
+ {% header "h2", "Examples" %} + {% header "h3", "Base" %} +

The base loading component displays three animated squares.

+
+{% highlight html %} +
+
+
Loading…
+
+{% endhighlight %} +
+
+
+
+
Loading…
+
+
+
+
+
+ +
+ {% header "h3", "Sizes" %} + + + + + + + + + + {% for size in loading.sizes %} + + + + + + {% endfor %} + +
ClassApplied toExample
+ + {% if size == "" %} + .s-loading + {% else %} + .{{ size }} + {% endif %} + + + + {% if size == "" %} + N/A + {% else %} + .s-loading + {% endif %} + + +
+
+
Loading…
+
+
+
\ No newline at end of file diff --git a/packages/stacks-svelte/src/components/Button/Button.stories.svelte b/packages/stacks-svelte/src/components/Button/Button.stories.svelte index 8aafcd1e6f..2ac6f842e2 100644 --- a/packages/stacks-svelte/src/components/Button/Button.stories.svelte +++ b/packages/stacks-svelte/src/components/Button/Button.stories.svelte @@ -4,7 +4,7 @@ import type { Brand, Size, Variant, Weight } from "./Button.svelte"; import Icon from "../Icon/Icon.svelte"; import { IconTrash } from "@stackoverflow/stacks-icons/icons"; - import Loader from "../Loader/Loader.svelte"; + import Loading from "../Loading/Loading.svelte"; const ButtonBrands: Brand[] = ["", "facebook", "github", "google"]; const ButtonSizes: Size[] = ["", "xs", "sm", "lg"]; @@ -115,8 +115,8 @@ {#each ButtonVariants as variant (variant)} {#each ButtonWeights as weight (weight)} {#if !(weight === "clear" && (variant === "featured" || variant === "tonal"))} - {#snippet loader()} - + {#snippet loading()} + {/snippet} @@ -128,7 +128,7 @@ {#each [null, "selected", "disabled"] as state (state)}