Skip to content

Commit

Permalink
Loading buttons!!!
Browse files Browse the repository at this point in the history
  • Loading branch information
hannahiss committed Jan 6, 2025
1 parent 44318f1 commit f951497
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 157 deletions.
102 changes: 46 additions & 56 deletions scss/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
--#{$prefix}btn-disabled-opacity: #{$btn-disabled-opacity}; // TODO to check
--#{$prefix}btn-focus-box-shadow: 0 0 0 #{$btn-focus-width} var(--#{$prefix}btn-focus-shadow-rgb); // OUDS mod
--#{$prefix}icon-spacing: #{$btn-icon-padding-left}; // OUDS mod TODO to check, maybe $btn-icon-padding-x?
--#{$prefix}loading-indeterminate-icon: #{escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path d='M20 10C20 11.9778 19.4135 13.9112 18.3147 15.5557C17.2159 17.2002 15.6541 18.4819 13.8268 19.2388C11.9996 19.9957 9.98891 20.1937 8.0491 19.8079C6.10929 19.422 4.32746 18.4696 2.92893 17.0711C1.53041 15.6725 0.577999 13.8907 0.192147 11.9509C-0.193705 10.0111 0.00432836 8.00043 0.761205 6.17317C1.51808 4.3459 2.79981 2.78412 4.4443 1.6853C6.08879 0.58649 8.02219 -2.35852e-08 10 0V3C8.61553 3 7.26215 3.41054 6.11101 4.17971C4.95986 4.94888 4.06266 6.04213 3.53284 7.32122C3.00303 8.6003 2.86441 10.0078 3.1345 11.3656C3.4046 12.7235 4.07128 13.9708 5.05025 14.9497C6.02922 15.9287 7.2765 16.5954 8.63437 16.8655C9.99224 17.1356 11.3997 16.997 12.6788 16.4672C13.9579 15.9373 15.0511 15.0401 15.8203 13.889C16.5895 12.7378 17 11.3845 17 10H20Z'/></svg>"))}; // OUDS mod
--#{$prefix}btn-loading-time: 2s; // OUDS mod
--#{$prefix}btn-focus-bg: var(--#{$prefix}btn-hover-bg); // OUDS mod
--#{$prefix}btn-focus-border-color: var(--#{$prefix}btn-hover-border-color); // OUDS mod
--#{$prefix}btn-focus-color: var(--#{$prefix}btn-hover-color); // OUDs mod
Expand Down Expand Up @@ -106,7 +106,7 @@
// OUDS mod: selectors are slightly different to handle `.btn-check`
// TODO how to handle to disable links with aria-disabled only
.btn-check:disabled + &,
&:disabled:not(.loading-indeterminate):not(.loading-determinate):not(.skeleton):not(:has(.loader-indeterminate-span)),
&:disabled:not(.loading-indeterminate):not(.loading-determinate):not(.skeleton),
&.disabled,
fieldset:disabled & {
color: var(--#{$prefix}btn-disabled-color);
Expand Down Expand Up @@ -146,73 +146,31 @@
// End mod

// OUDS mod: loading buttons
&:has(.loader-indeterminate-span) {
color: transparent;
@keyframes rotate-determinate {
0% { stroke-dashoffset: 315 #{"/* rtl:ignore */"}; }
100% { stroke-dashoffset: 0 #{"/* rtl:ignore */"}; }
}

.loader-indeterminate-span {
position: absolute;
display: inline-block;
width: px-to-rem($ouds-button-size-loader);
height: px-to-rem($ouds-button-size-loader);
color: var(--#{$prefix}btn-color);
vertical-align: middle;
background-color: transparent;
border: 3px solid currentcolor;
border-right-color: transparent;
// stylelint-disable-next-line property-disallowed-list
border-radius: 50%;
animation: .75s linear infinite spinner-border;
@keyframes rotate1-indeterminate {
0%,
100% { stroke-dashoffset: -252 #{"/* rtl:ignore */"}; }
50% { stroke-dashoffset: -63 #{"/* rtl:ignore */"}; }
}

@keyframes spinner-border {
to { transform: rotate(360deg) #{"/* rtl:ignore */"}; }
@keyframes rotate2-indeterminate {
0% { transform: rotate(0deg) #{"/* rtl:ignore */"}; }
100% { transform: rotate(360deg) #{"/* rtl:ignore */"}; }
}


&.loading-indeterminate,
&.loading-determinate {
position: relative;
z-index: 0;
overflow: hidden;
color: transparent;
border-width: var(--#{$prefix}btn-interaction-border-width);

&:hover,
&:active,
&:focus-visible,
&:disabled {
color: transparent;
}

&::before {
position: absolute;
top: 0;
left: 0;
z-index: -1;
width: 100%;
height: 100%;
color: var(--#{$prefix}btn-color);
content: "";
background-color: currentcolor;
mask-image: var(--#{$prefix}loading-indeterminate-icon);
mask-repeat: no-repeat;
mask-position: 50% 50%;
mask-size: px-to-rem($ouds-button-size-loader);
animation: loading-indeterminate-rotate 2s linear infinite;
}
}

&.loading-determinate::before {
animation: none;
}

@keyframes loading-indeterminate-rotate {
100% {
transform: rotate(360deg);
}
}

&[class*="loading"],
&:has(.loader-indeterminate-span) {
&.btn-default {
--#{$prefix}btn-color: #{$ouds-button-color-content-default-loading};
--#{$prefix}btn-bg: #{$ouds-button-color-bg-default-loading};
Expand Down Expand Up @@ -254,6 +212,38 @@
--#{$prefix}btn-bg: #{$ouds-button-color-bg-minimal-loading-mono};
--#{$prefix}btn-border-color: #{$ouds-button-color-border-minimal-loading-mono};
}

&:hover,
&:active,
&:focus-visible,
&:disabled {
color: transparent;
}

.loader {
position: absolute;
top: 50%;
left: 50%;
margin: 0;
transform: translate(-50%, -50%) rotate(-90deg);
transform-origin: center;
}

.loader-inner {
fill: none;
stroke: var(--#{$prefix}btn-color);
stroke-dasharray: 315;
stroke-width: 20;
transform-origin: center;
}
}

&.loading-indeterminate .loader-inner {
animation: 1.75s infinite linear rotate1-indeterminate, 1s linear infinite rotate2-indeterminate;
}

&.loading-determinate .loader-inner {
animation: var(--#{$prefix}btn-loading-time) infinite linear rotate-determinate;
}

//&.skeleton {
Expand Down
110 changes: 96 additions & 14 deletions site/content/docs/0.0/components/buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,30 +307,112 @@ See the buttons un action in our [loading buttons live example]({{< docsref "/ex

{{< example class="p-none" >}}
<div class="p-tall">
<button type="button" class="btn btn-default" id="loading-btn0" disabled>
Download file 0
<span class="loader-indeterminate-span" aria-hidden="true"></span>
<span role="status" id="loading-btn-msg0" class="visually-hidden">Downloading file 0</span>
</button>
<button type="button" class="btn btn-default loading-indeterminate" id="loading-btn1" disabled>
<button type="button" class="btn btn-default loading-indeterminate" id="loading-btn-1" disabled>
Download file 1
<span role="status" id="loading-btn-msg1" class="visually-hidden">Downloading file 1</span>
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">

Check failure on line 312 in site/content/docs/0.0/components/buttons.md

View workflow job for this annotation

GitHub Actions / cspell

Unknown word (viewbox)
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-1" class="visually-hidden">Downloading file 1</span>
</button>
<button type="button" class="btn btn-default loading-determinate" id="loading-btn2" disabled>
<button type="button" class="btn btn-strong loading-indeterminate" id="loading-btn-2" disabled>
Download file 2
<span role="status" id="loading-btn-msg2" class="visually-hidden">Downloading file 2</span>
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">

Check failure on line 319 in site/content/docs/0.0/components/buttons.md

View workflow job for this annotation

GitHub Actions / cspell

Unknown word (viewbox)
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-2" class="visually-hidden">Downloading file 2</span>
</button>
<button type="button" class="btn btn-minimal loading-indeterminate" id="loading-btn-3" disabled>
Download file 3
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">

Check failure on line 326 in site/content/docs/0.0/components/buttons.md

View workflow job for this annotation

GitHub Actions / cspell

Unknown word (viewbox)
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-3" class="visually-hidden">Downloading file 3</span>
</button>
<button type="button" class="btn btn-negative loading-indeterminate" id="loading-btn-4" disabled>
Download file 4
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">

Check failure on line 333 in site/content/docs/0.0/components/buttons.md

View workflow job for this annotation

GitHub Actions / cspell

Unknown word (viewbox)
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-4" class="visually-hidden">Downloading file 4</span>
</button>
</div>
<div class="colored-bg p-tall">
<button type="button" class="btn btn-default btn-on-colored-bg loading-indeterminate" id="loading-btn3" disabled>
<div class="p-tall">
<button type="button" class="btn btn-default loading-determinate" id="loading-btn-1" disabled>
Download file 1
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">

Check failure on line 342 in site/content/docs/0.0/components/buttons.md

View workflow job for this annotation

GitHub Actions / cspell

Unknown word (viewbox)
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-1" class="visually-hidden">Downloading file 1</span>
</button>
<button type="button" class="btn btn-strong loading-determinate" id="loading-btn-2" disabled>
Download file 2
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-2" class="visually-hidden">Downloading file 2</span>
</button>
<button type="button" class="btn btn-minimal loading-determinate" id="loading-btn-3" disabled>
Download file 3
<span role="status" id="loading-btn-msg3" class="visually-hidden">Downloading file 3</span>
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-3" class="visually-hidden">Downloading file 3</span>
</button>
<button type="button" class="btn btn-default btn-on-colored-bg loading-determinate" id="loading-btn4" disabled>
<button type="button" class="btn btn-negative loading-determinate" id="loading-btn-4" disabled>
Download file 4
<span role="status" id="loading-btn-msg4" class="visually-hidden">Downloading file 4</span>
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-4" class="visually-hidden">Downloading file 4</span>
</button>
</div>
<div class="p-tall colored-bg">
<button type="button" class="btn btn-default btn-on-colored-bg loading-indeterminate" id="loading-btn-1" disabled>
Download file 1
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-1" class="visually-hidden">Downloading file 1</span>
</button>
<button type="button" class="btn btn-strong btn-on-colored-bg loading-indeterminate" id="loading-btn-2" disabled>
Download file 2
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-2" class="visually-hidden">Downloading file 2</span>
</button>
<button type="button" class="btn btn-minimal btn-on-colored-bg loading-indeterminate" id="loading-btn-3" disabled>
Download file 3
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-3" class="visually-hidden">Downloading file 3</span>
</button>
</div>
<div class="p-tall colored-bg">
<button type="button" class="btn btn-default btn-on-colored-bg loading-determinate" id="loading-btn-1" disabled>
Download file 1
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-1" class="visually-hidden">Downloading file 1</span>
</button>
<button type="button" class="btn btn-strong btn-on-colored-bg loading-determinate" id="loading-btn-2" disabled>
Download file 2
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-2" class="visually-hidden">Downloading file 2</span>
</button>
<button type="button" class="btn btn-minimal btn-on-colored-bg loading-determinate" id="loading-btn-3" disabled>
Download file 3
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-3" class="visually-hidden">Downloading file 3</span>
</button>
</div>

{{< /example >}}

## Block buttons
Expand Down
79 changes: 18 additions & 61 deletions site/content/docs/0.0/examples/loading-buttons/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,79 +9,36 @@
<div class="container-fluid container-max-width">
<h1 class="py-medium">Loading buttons</h1>

<h2 class="py-short">Loading buttons in an indeterminate time</h2>

<h2 class="py-short">Loading button in an indeterminate time</h2>
For this example, the time is set to 5 seconds by Javascript, but in a real project, you just need a callback when the action is finished.
An update to the status is done every second to let the user know the download is still ongoing.
Each time, a dot is added to the message to make sure it will change and then be vocalised by the screen readers.
<div class="row py-taller">
<div class="col-4">
<button type="button" class="btn btn-default" id="load1">
Download file 1 (indeterminate without span)
<span role="status" id="update1" class="visually-hidden"></span>
</button>
</div>
<div class="col-4">
<button type="button" class="btn btn-default" id="load3">
Download file 3 (indeterminate with span)
<span role="status" id="update3" class="visually-hidden"></span>
<button type="button" class="btn btn-default" id="loading-btn-1">
Download file 1
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader d-none">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-1" class="visually-hidden">Downloading file 1</span>
</button>
</div>

<!-- <div class="col-3">-->
<!-- <button type="button" class="btn btn-strong">-->
<!-- Strong-->
<!-- </button>-->
<!-- </div>-->
<!-- <div class="col-3">-->
<!-- <button type="button" class="btn btn-minimal">-->
<!-- Minimal-->
<!-- </button>-->
<!-- </div>-->
<!-- <div class="col-3">-->
<!-- <button type="button" class="btn btn-negative">-->
<!-- Negative-->
<!-- </button>-->
<!-- </div>-->
</div>
<!-- <div class="row py-taller bg-primary">-->
<!-- <div class="col-3">-->
<!-- <button type="button" class="btn btn-default-on-colored-bg">-->
<!-- Default-->
<!-- </button>-->
<!-- </div>-->
<!-- <div class="col-3">-->
<!-- <button type="button" class="btn btn-strong-on-colored-bg">-->
<!-- Strong-->
<!-- </button>-->
<!-- </div>-->
<!-- <div class="col-3">-->
<!-- <button type="button" class="btn btn-minimal-on-colored-bg">-->
<!-- Minimal-->
<!-- </button>-->
<!-- </div>-->
<!-- </div>-->

<h2 class="py-short">Loading buttons in a determinate time</h2>

The time must be set to through the CSS variable <code>--bs-button-loading-time</code> directly on the button.
In this example, it is set to 4 seconds.
An update to the status is done every second, giving the percentage of time that has elapsed.
<div class="row py-taller">
<div class="col-3">
<button type="button" class="btn btn-default" id="load2" style="--bs-button-loading-time: 10;">
<button type="button" class="btn btn-default" id="loading-btn-2" style="--bs-btn-loading-time: 4s;">
Download file 2
<span role="status" id="update2" class="visually-hidden"></span>
<svg viewbox='0 0 120 120' xmlns='http://www.w3.org/2000/svg' class="loader d-none">
<circle class="loader-inner" cx="60" cy="60" r="50"></circle>
</svg>
<span role="status" id="loading-btn-msg-2" class="visually-hidden">Downloading file 2</span>
</button>
</div>
</div>



<br><br>
<div class="example-hole">
<div class="btn btn-default">
<span class="loader-determinate">
<span class="fill"></span>
</span>
<span class="">
<span class="fill"></span>
</span>
</div>
</div>

</div>
Loading

0 comments on commit f951497

Please sign in to comment.