Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@

#### Loader
- `Spinner` component replaced with new `Loader` component
- `xs` and `xl` sized have been removed, leaving only the default, `sm`, and `lg` sizes

#### Menu

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { runA11yTests } from "../../test/a11y-test-utils";
import "../../index";

describe("loading", () => {
describe("loader", () => {
runA11yTests({
baseClass: "s-loading",
baseClass: "s-loader",
modifiers: {
primary: ["sm", "lg"],
},
Expand Down
119 changes: 68 additions & 51 deletions packages/stacks-classic/lib/components/loader/loader.less
Original file line number Diff line number Diff line change
@@ -1,61 +1,78 @@
.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);
.s-loader {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spoke to Caro because the Figma called it Loader but the story said Loading, she confirmed it is Loader. I forgot to update the ticket sorry! I've changed it back to loader

--_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: var(--su-static16);
--_ld-gap: var(--su-static2);
--_ld-start-offset: calc(var(--su-static2) + var(--su-static1));
&__sm {
--_ld-size: calc(calc(var(--su8) - var(--su1)) / 2); // 3.5px
margin-left: var(--su1);
margin-right: var(--su1);
}
&&__lg {
--_ld-size: var(--su-static48);
--_ld-block-size: calc(var(--su-static4) + var(--su-static4));
--_ld-start-offset: var(--su-static1);

&__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: loader-animation .8s cubic-bezier(1, 1, 0, 1) infinite;
}

& &--block {
animation-delay: .25s;
}

&:after {
animation-delay: .5s;
}

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);
}
gap: var(--_ld-gap);
margin-top: var(--_ld-gap);
}

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);
@media (prefers-reduced-motion:reduce){
.s-loader {
& &--block,
&:before,
&:after {
animation: loader-animation-reduced-motion 2s ease-in-out infinite;
}
}

// Inherit text color when inside a button
.s-btn & {
color: var(--_bu-fc);
.svg-spot {
rect {
fill: var(--_bu-fc) !important;
}
}
}

@keyframes loader-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 loader-animation-reduced-motion {
0%,to{
opacity: 0.3;
transform: none;
}
50%{
opacity: 1;
transform: none;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import "../../index";
const template = ({ component, testid }: any) => html`
<div class="d-inline-block p8" data-testid="${testid}">${component}</div>
`;
describe("loading", () => {
describe("loader", () => {
// default, sizes
runVisualTests({
baseClass: "s-loading",
baseClass: "s-loader",
modifiers: {
primary: ["sm", "lg"],
},
Expand All @@ -20,7 +20,7 @@ describe("loading", () => {
});
// applied font color
runVisualTests({
baseClass: "s-loading",
baseClass: "s-loader",
modifiers: {
global: ["fc-theme-primary"],
},
Expand Down
26 changes: 16 additions & 10 deletions packages/stacks-docs/_data/loader.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
{
"loader": [
"classes": [
{
"class": ".s-loader--block",
"class": ".s-loader",
"applies": "N/A",
"description": "Base block loading style that displays three animated squares"
"description": "Base class for the loader component"
},
{
"class": ".s-loader--block",
"applies": ".s-loader",
"description": "Child necessary to render the center loader block"
},
{
"class": ".s-loader--block__sm",
"applies": ".s-loader--block",
"description": "A small style for compact layouts"
"class": ".s-loader__sm",
"applies": ".s-loader",
"description": "A small variant of the loader component"
},
{
"class": ".s-loader--block__lg",
"applies": ".s-loader--block",
"description": "A large style for the largest layouts"
"class": ".s-loader__lg",
"applies": ".s-loader",
"description": "A large variant of the loader component"
}
]
],
"sizes": ["s-loader__sm", "", "s-loader__lg"]
}
3 changes: 2 additions & 1 deletion packages/stacks-docs/_data/site-navigation.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@
},
{
"title": "Loader",
"url": "/product/components/loader/"
"url": "/product/components/loader/",
"new": true
},
{
"title": "Menus",
Expand Down
9 changes: 5 additions & 4 deletions packages/stacks-docs/product/components/buttons.html
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,13 @@

<section class="docs-section">
{% header "h2", "Loading" %}
<p class="docs-copy">Any button can have a loading state applied by adding the <code class="docs-code">.s-loader--block .s-loader--block__sm</code> state class.</p>
<p class="docs-copy">Indicate a loading state by adding a <a href="/product/components/loader/"><code class="docs-code">.s-loader</code></a> component to a button.</p>
<div class="docs-preview">
{% highlight html %}
<button class="s-btn .s-loader--block .s-loader--block__sm" type="button"
<div class="s-loader--block s-loader--block__sm">
<button class="s-btn" type="button">
<div class="s-loader s-loader__sm">
<div class="s-loader--block"></div>
<div class="v-visible-sr">Loading…</div>
@Svg.Spot.Loading.With("native")
</div>
Ask question
</button>
Expand All @@ -291,6 +291,7 @@
</tr>
</thead>
<tbody>
<!-- TODO SHINE add loading state to buttons -->
{% for btn in buttons.variants %}
<tr>
<th scope="row" class="va-middle">{{ btn.title }}</th>
Expand Down
83 changes: 52 additions & 31 deletions packages/stacks-docs/product/components/loader.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
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."
description: "The loader component indicates an active wait state for a page, section, or interactive element."
tags: components
---
<section class="docs-section">
Expand All @@ -17,7 +17,7 @@
</tr>
</thead>
<tbody class="fs-caption">
{% for item in loader.loader %}
{% for item in loader.classes %}
<tr>
<td><code class="docs-code ws-nowrap">{{ item.class }}</code></td>
<td>{% if item.applies == "N/A" %}<em class="fc-black-350">{{ item.applies }}</em>{% else %}<code class="docs-code">{{ item.applies }}</code>{% endif %}</td>
Expand All @@ -30,44 +30,65 @@
</section>
<section class="docs-section">
{% header "h2", "Examples" %}
{% header "h3", "Blocks" %}
<p class="docs-copy">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.</p>
{% header "h3", "Base" %}
<p class="docs-copy">The base loader component displays three animated squares.</p>
<div class="docs-preview">
{% highlight html %}
<div class="s-loader--block s-loader--block__sm">
<div class="s-loader">
<div class="s-loader--block"></div>
<div class="v-visible-sr">Loading…</div>
@Svg.Spot.Loading.With("native")
</div>
<div class="s-loader--block">
<div class="v-visible-sr">Loading…</div>
@Svg.Spot.Loading.With("native")
</div>
<div class="s-loader--block s-loader--block__lg fc-theme-primary">
<div class="v-visible-sr">Loading…</div>
@Svg.Spot.Loading.With("native")
</div>
{% endhighlight %}
<div class="docs-preview--example">
<div class="d-flex g16 fw-wrap ai-center">
<div>
<div class="s-loader--block s-loader--block__sm">
<div class="v-visible-sr">Loading…</div>
{% spot "Loading", "native" %}
</div>
</div>
<div>
<div class="s-loader--block">
<div class="v-visible-sr">Loading…</div>
{% spot "Loading", "native" %}
</div>
</div>
<div>
<div class="s-loader--block s-loader--block__lg">
<div class="v-visible-sr">Loading…</div>
{% spot "Loading", "native" %}
</div>
<div class="s-loader">
<div class="s-loader--block"></div>
<div class="v-visible-sr">Loading…</div>
</div>
</div>
</div>
</div>
</section>

<section class="docs-section">
{% header "h3", "Sizes" %}
<table class="s-table s-table__bx-simple">
<thead>
<tr>
<th class="s-table--cell3" scope="col">Class</th>
<th class="s-table--cell3" scope="col">Applied to</th>
<th scope="col">Example</th>
</tr>
</thead>
<tbody class="fs-caption">
{% for size in loader.sizes %}
<tr>
<th scope="row">
<code class="docs-code">
{% if size == "" %}
.s-loader
{% else %}
.{{ size }}
{% endif %}
</code>
</th>
<td>
<code class="docs-code bg-white">
{% if size == "" %}
<em class="fc-black-400">N/A</em>
{% else %}
.s-loader
{% endif %}
</code>
</td>
<td class="p8">
<div class="s-loader {{ size }}">
<div class="s-loader--block"></div>
<div class="v-visible-sr">Loading…</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
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";

const ButtonBrands: Brand[] = ["", "facebook", "github", "google"];
const ButtonSizes: Size[] = ["", "xs", "sm", "lg"];
Expand Down Expand Up @@ -115,9 +114,6 @@
{#each ButtonVariants as variant (variant)}
{#each ButtonWeights as weight (weight)}
{#if !(weight === "clear" && (variant === "featured" || variant === "tonal"))}
{#snippet loader()}
<Loader variant="block" size="sm" />
{/snippet}
<tr>
<th scope="row" class="va-middle">
{titleCase(variant || "secondary")}
Expand All @@ -128,7 +124,7 @@
{#each [null, "selected", "disabled"] as state (state)}
<td class="va-middle ta-center px4">
<Button
{loader}
loading={true}
{weight}
selected={state === "selected"}
disabled={state === "disabled"}
Expand Down
Loading