Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EHN Implement the new logo on the loading animation #1546

Merged
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
Binary file modified client/dist/fonts/silverstripe.eot
Binary file not shown.
3 changes: 2 additions & 1 deletion client/dist/fonts/silverstripe.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/dist/fonts/silverstripe.ttf
Binary file not shown.
Binary file modified client/dist/fonts/silverstripe.woff
Binary file not shown.
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/styles/bundle.css

Large diffs are not rendered by default.

80 changes: 0 additions & 80 deletions client/src/components/BrowserWarning/BrowserWarning.scss

This file was deleted.

129 changes: 78 additions & 51 deletions client/src/components/Loading/Loading.js
Original file line number Diff line number Diff line change
@@ -1,62 +1,89 @@
/* global window */
import React, { PureComponent } from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { v4 as uuid } from 'uuid';

/**
* Renders a Silverstripe loading animation styled after the Silverstripe logo
*
* `spinner__animation__outline_right` and `spinner__animation__outline_left`
* They form the two halves of the logo. They are transparent and are used
* as masks to clip the things that are animated.
*
* spinner__animation__fill-left and spinner__animation__fill-right
* Those are two plain lines with heavy strokes. The lines mostly follow the
* middle of the two shapes. The strokes are dashed with a dash length long
* enough to cover the full length of the two paths. SVG allow you to control
* the dash offset. That's what's actually animated to create the illusion
* that the paths are being "drawn".
*/
class Loading extends PureComponent {
render() {
const { containerClass } = this.props;
function Loading({ containerClass }) {
// If we are displaying many loading indicators at the same time, we need to
const [id] = useState(uuid());

return (
<div className={containerClass}>
<div key="overlay" className="cms-content-loading-overlay ui-widget-overlay-light" />
<div key="spinner" className="cms-content-loading-spinner">
<div className="spinner">
{/* window.location is neccessary for Safari which otherwise prepends the base tag */}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've decided to throw Safari under the bus here. Basically, forcing us to use absolute URL to find those SVGs introduce a bug where sometime if you've updated the URL with react route or added some extra parameter, the SVG path clipping doesn't work.

Using the IDs directly instead of the full URL seems to mitigate this problem.

Basically, I think that having this work consistently in all other browser is better than adding a hack so that Safari users get it looking at it's best some of the time.

Safari user should still get a reasonable animation in most cases. It just won't have the nice curvy bit. Given that those loading animation are only shown for a fleeting second and are pretty small, I doubt anyone will even notice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Safari will probably look something like this.

image

<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox="0 0 30 30"
width="30"
height="30"
className="spinner__animation"
>
<g>
<defs>
<path
id="spinner__animation__outline"
d="M17.6,9.8c-2.3,1.7-2.8,5-1.1,7.3l4.2-3.1
c1.1-0.8,2.7-0.6,3.6,0.5c0.8,1.1,0.6,2.7-0.5,3.6l-6.2,4.6
c-2.3,1.7-2.8,5-1.1,7.3l10.4-7.7c3.4-2.6,4.1-7.4,1.6-10.8
C25.9,8,21.1,7.3,17.6,9.8z M13.4,12.9L9.3,16c-1.1,0.8-2.7,0.6-3.6-0.5
s-0.6-2.7,0.5-3.6l6.2-4.6c2.3-1.7,2.8-5,1.1-7.3L3.1,7.7
c-3.4,2.6-4.1,7.4-1.6,10.8c2.6,3.4,7.4,4.1,10.8,1.6
C14.7,18.4,15.1,15.2,13.4,12.9z"
/>
<clipPath id="spinner__animation__mask">
<use xlinkHref={`${window.location}#spinner__animation__outline`} />
</clipPath>
</defs>
<use
className="spinner__animation__empty"
xlinkHref={`${window.location}#spinner__animation__outline`}
/>
<path
className="spinner__animation__fill"
clipPath={`url(${window.location}#spinner__animation__mask)`}
d="M15,2.1L4.7,9.8c-2.3,1.7-2.8,4.9-1.1,7.2
s4.9,2.8,7.2,1.1l8.3-6.1c2.3-1.7,5.5-1.2,7.2,1.1
s1.2,5.5-1.1,7.2L15,27.9"
/>
</g>
</svg>
</div>
return (
<div className={containerClass}>
<div key="overlay" className="cms-content-loading-overlay ui-widget-overlay-light" />
<div key="spinner" className="cms-content-loading-spinner">
<div className="spinner">
<svg
fill="none"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
width="512"
height="297"
viewBox="0 0 512 297"
className="spinner__animation"
>
<defs>
<path
id={`spinner__animation__outline_right_${id}`}
d="M253 29L145 105C130 115 126 136 137 150C147 165 168 169 183
159L291 83C335 52 397 63 428 107C459 152 448 214 404 245L370
268C398 316 461 296 490 245C520 191 519 123 482 70C430 -4 327
-22 253 29Z"
/>
<path
id={`spinner__animation__outline_left_${id}`}
d="M258 266L366 191C381 180 385 160 374 145C364 130 343 127 328
137L220 212C176 244 114 233 83 188C52 144 63 82 107 51L141 27C113
-20 50 -0 21 51C-8 104 -7 172 29 226C81 300 184 318 258 266V266Z"
/>
<clipPath id={`spinner__animation__mask_right_${id}`}>
<use href={`#spinner__animation__outline_right_${id}`} />
</clipPath>
<clipPath id={`spinner__animation__mask_left_${id}`}>
<use href={`#spinner__animation__outline_left_${id}`} />
</clipPath>
</defs>
<use
className="spinner__animation__empty"
href={`#spinner__animation__outline_left_${id}`}
/>
<use
className="spinner__animation__empty"
href={`#spinner__animation__outline_right_${id}`}
/>
<path
d="M 379,145 236,242 C 179,282 102,273 62,216 22,159 19,77 76,37 L 135,7"
className="spinner__animation__fill-left"
clipPath={`url(#spinner__animation__mask_left_${id})`}
/>
<path
d="M 138,148 281,50 c 57,-39 129,-30 169,26 39,56 41,136 -14,178 l -47,40"
className="spinner__animation__fill-right"
clipPath={`url(#spinner__animation__mask_right_${id})`}
/>
<path
d="M253 29L145 105C130 115 126 136 137 150C147 165 168 169 183
159L291 83C335 52 397 63 428 107C459 152 448 214 404 245L370
268C398 316 461 296 490 245C520 191 519 123 482 70C430 -4 327
-22 253 29Z"
/>
</svg>
</div>
</div>
);
}
</div>
);
}

Loading.propTypes = {
Expand Down
111 changes: 111 additions & 0 deletions client/src/components/Loading/Loading.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
$dash: 750;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've moved this bit from _style.scss so it lives next to the actual component its meant to style.


.cms-content-loading-overlay {
position: absolute; // z-index doesn't apply properly without that
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9998;
// Further styling by .ui-widget-overlay-light which is usually applied at the same time
}

.cms-content-loading-spinner {
position: absolute; // z-index doesn't apply properly without that
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;

.spinner {
width: 3rem;
height: 3rem;
padding: .5rem;

background-color: $white;
border-radius: $border-radius-sm;

.ss-loading-screen & {
width: 9rem;
height: 9rem;
background-color: transparent;
}

&__animation {
width: 100%;
height: 100%;

&__empty {
fill: transparent;
}

&__fill-left,
&__fill-right {
fill: none;
stroke: $blue;
stroke-width: 70;
stroke-dasharray: $dash;
transform: translateZ(0);
}

&__fill-left {

animation: spinner__animation__keyframes-left 3s infinite cubic-bezier(.445, .05, .55, .95)
forwards;

@keyframes spinner__animation__keyframes-left {
0% {
stroke-dashoffset: 0;
}

25% {
stroke-dashoffset: $dash;
}

50% {
stroke-dashoffset: $dash;
}

75% {
stroke-dashoffset: $dash*2;
}

100% {
stroke-dashoffset: $dash*2;
}
}
}

&__fill-right {
animation: spinner__animation__keyframes-right 3s infinite cubic-bezier(.445, .05, .55, .95)
forwards;

@keyframes spinner__animation__keyframes-right {
0% {
stroke-dashoffset: $dash*2;
}

25% {
stroke-dashoffset: $dash*2;
}

50% {
stroke-dashoffset: $dash;
}

75% {
stroke-dashoffset: $dash;
}

100% {
stroke-dashoffset: 0;
}
}
}
}
}
}
Binary file modified client/src/font/fonts/silverstripe.eot
Binary file not shown.
Loading