mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-27 09:35:56 -05:00
Merge pull request #2073 from LiFaytheGoblin/2005/animate-add-to-studio-buttons
Animate add-to-studio-buttons on preview project page
This commit is contained in:
commit
42f0ed16e5
16 changed files with 184 additions and 169 deletions
|
@ -75,7 +75,10 @@ class Login extends React.Component {
|
||||||
key="submitButton"
|
key="submitButton"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
<Spinner />
|
<Spinner
|
||||||
|
className="spinner"
|
||||||
|
color="blue"
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
] : [
|
] : [
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
.spinner {
|
.spinner {
|
||||||
margin: 0 .8rem;
|
margin: 0 .8rem;
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-button {
|
.submit-button {
|
||||||
|
|
48
src/components/modal/addtostudio/animate-hoc.jsx
Normal file
48
src/components/modal/addtostudio/animate-hoc.jsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Higher-order component for building an animated studio button
|
||||||
|
* it is used to decorate the onToggleStudio function with noticing
|
||||||
|
* when the button has first been clicked.
|
||||||
|
* This is needed so the buttons don't play the animation when they are
|
||||||
|
* first rendered but when they are first clicked.
|
||||||
|
* @param {React.Component} Component a studio button component
|
||||||
|
* @return {React.Component} a wrapped studio button component
|
||||||
|
*/
|
||||||
|
|
||||||
|
const AnimateHOC = Component => {
|
||||||
|
class WrappedComponent extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
wasClicked: false
|
||||||
|
};
|
||||||
|
|
||||||
|
this.handleClick = this.handleClick.bind(this);
|
||||||
|
}
|
||||||
|
handleClick () {
|
||||||
|
this.setState({ // else tell the state that the button has been clicked
|
||||||
|
wasClicked: true
|
||||||
|
}, () => this.props.onClick(this.props.id)); // callback after state has been updated
|
||||||
|
}
|
||||||
|
render () {
|
||||||
|
const {wasClicked} = this.state;
|
||||||
|
return (<Component
|
||||||
|
{...this.props}
|
||||||
|
wasClicked={wasClicked}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
/>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WrappedComponent.propTypes = {
|
||||||
|
id: PropTypes.number,
|
||||||
|
onClick: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
return WrappedComponent;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = AnimateHOC;
|
|
@ -89,10 +89,10 @@
|
||||||
pointer-events: none; /* pass clicks through to buttons underneath */
|
pointer-events: none; /* pass clicks through to buttons underneath */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.studio-selector-button {
|
.studio-selector-button {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
transition: all .5s;
|
||||||
margin: .21875rem .21875rem;
|
margin: .21875rem .21875rem;
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
background-color: $ui-white;
|
background-color: $ui-white;
|
||||||
|
@ -102,6 +102,7 @@
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.studio-selector-button-text {
|
.studio-selector-button-text {
|
||||||
|
@ -164,30 +165,30 @@
|
||||||
background-color: $ui-blue;
|
background-color: $ui-blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.studio-status-icon-plus-img {
|
.studio-status-icon-plus-img,
|
||||||
|
.studio-status-icon-checkmark-img {
|
||||||
|
animation-direction: normal;
|
||||||
width: 1.4rem;
|
width: 1.4rem;
|
||||||
height: 1.4rem;
|
height: 1.4rem;
|
||||||
|
transform-origin: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.studio-status-icon--img {
|
.studio-status-icon-with-animation {
|
||||||
width: 1.4rem;
|
animation-name: bump;
|
||||||
height: 1.4rem;
|
animation-duration: .25s;
|
||||||
|
animation-timing-function: cubic-bezier(.3, -3, .6, 3);
|
||||||
|
animation-iteration-count: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-button-text .spinner-smooth {
|
@keyframes bump {
|
||||||
margin: .2125rem auto;
|
0% {
|
||||||
width: 1.875rem;
|
transform: scale(0);
|
||||||
height: 1rem;
|
opacity: 0;
|
||||||
}
|
-webkit-transform: scale(0);
|
||||||
|
}
|
||||||
.studio-status-icon .spinner-smooth {
|
100% {
|
||||||
position: unset; /* don't understand why neither relative nor absolute work */
|
transform: scale(1);
|
||||||
}
|
opacity: 1;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
.studio-status-icon .spinner-smooth .circle {
|
}
|
||||||
/* overlay spinner on circle */
|
|
||||||
position: absolute;
|
|
||||||
margin: .1875rem; /* stay within boundaries of circle */
|
|
||||||
width: 75%; /* stay within boundaries of circle */
|
|
||||||
height: 75%; /* stay within boundaries of circle */
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ const AddToStudioModalPresentation = ({
|
||||||
includesProject={studio.includesProject}
|
includesProject={studio.includesProject}
|
||||||
key={studio.id}
|
key={studio.id}
|
||||||
title={studio.title}
|
title={studio.title}
|
||||||
onToggleStudio={onToggleStudio}
|
onClick={onToggleStudio}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ const AddToStudioModalPresentation = ({
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
<div className="action-button-text">
|
<div className="action-button-text">
|
||||||
<Spinner mode="smooth" />
|
<Spinner />
|
||||||
<FormattedMessage id="addToStudio.finishing" />
|
<FormattedMessage id="addToStudio.finishing" />
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -1,28 +1,36 @@
|
||||||
const PropTypes = require('prop-types');
|
const PropTypes = require('prop-types');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const classNames = require('classnames');
|
const classNames = require('classnames');
|
||||||
|
|
||||||
const Spinner = require('../../spinner/spinner.jsx');
|
const Spinner = require('../../spinner/spinner.jsx');
|
||||||
|
const AnimateHOC = require('./animate-hoc.jsx');
|
||||||
|
|
||||||
require('./modal.scss');
|
require('./modal.scss');
|
||||||
|
|
||||||
const StudioButton = ({
|
const StudioButton = ({
|
||||||
hasRequestOutstanding,
|
hasRequestOutstanding,
|
||||||
id,
|
|
||||||
includesProject,
|
includesProject,
|
||||||
title,
|
title,
|
||||||
onToggleStudio
|
onClick,
|
||||||
|
wasClicked
|
||||||
}) => {
|
}) => {
|
||||||
const checkmark = (
|
const checkmark = (
|
||||||
<img
|
<img
|
||||||
alt="checkmark-icon"
|
alt="checkmark-icon"
|
||||||
className="studio-status-icon-checkmark-img"
|
className={classNames(
|
||||||
|
'studio-status-icon-checkmark-img',
|
||||||
|
{'studio-status-icon-with-animation': wasClicked}
|
||||||
|
)}
|
||||||
src="/svgs/modal/confirm.svg"
|
src="/svgs/modal/confirm.svg"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
const plus = (
|
const plus = (
|
||||||
<img
|
<img
|
||||||
alt="plus-icon"
|
alt="plus-icon"
|
||||||
className="studio-status-icon-plus-img"
|
className={classNames(
|
||||||
|
'studio-status-icon-plus-img',
|
||||||
|
{'studio-status-icon-with-animation': wasClicked}
|
||||||
|
)}
|
||||||
src="/svgs/modal/add.svg"
|
src="/svgs/modal/add.svg"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -34,8 +42,7 @@ const StudioButton = ({
|
||||||
{'studio-selector-button-selected':
|
{'studio-selector-button-selected':
|
||||||
includesProject && !hasRequestOutstanding}
|
includesProject && !hasRequestOutstanding}
|
||||||
)}
|
)}
|
||||||
data-id={id}
|
onClick={onClick}
|
||||||
onClick={onToggleStudio}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
@ -50,11 +57,11 @@ const StudioButton = ({
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'studio-status-icon',
|
'studio-status-icon',
|
||||||
{'studio-status-icon-unselected': !includesProject}
|
{'studio-status-icon-unselected': !includesProject && !hasRequestOutstanding}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{(hasRequestOutstanding ?
|
{(hasRequestOutstanding ?
|
||||||
(<Spinner mode="smooth" />) :
|
<Spinner /> :
|
||||||
(includesProject ? checkmark : plus))}
|
(includesProject ? checkmark : plus))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -63,10 +70,10 @@ const StudioButton = ({
|
||||||
|
|
||||||
StudioButton.propTypes = {
|
StudioButton.propTypes = {
|
||||||
hasRequestOutstanding: PropTypes.bool,
|
hasRequestOutstanding: PropTypes.bool,
|
||||||
id: PropTypes.number,
|
|
||||||
includesProject: PropTypes.bool,
|
includesProject: PropTypes.bool,
|
||||||
onToggleStudio: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
title: PropTypes.string
|
title: PropTypes.string,
|
||||||
|
wasClicked: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = StudioButton;
|
module.exports = AnimateHOC(StudioButton);
|
||||||
|
|
|
@ -224,7 +224,7 @@ class ReportModal extends React.Component {
|
||||||
>
|
>
|
||||||
{isWaiting ? (
|
{isWaiting ? (
|
||||||
<div className="action-button-text">
|
<div className="action-button-text">
|
||||||
<Spinner mode="smooth" />
|
<Spinner />
|
||||||
<FormattedMessage id="report.sending" />
|
<FormattedMessage id="report.sending" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -1,29 +1,28 @@
|
||||||
const range = require('lodash.range');
|
|
||||||
const PropTypes = require('prop-types');
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const classNames = require('classnames');
|
||||||
|
|
||||||
require('./spinner.scss');
|
require('./spinner.scss');
|
||||||
|
|
||||||
// Adapted from http://tobiasahlin.com/spinkit/
|
// Adapted from http://tobiasahlin.com/spinkit/
|
||||||
const Spinner = ({
|
const Spinner = ({
|
||||||
mode
|
className,
|
||||||
}) => {
|
color
|
||||||
const spinnerClassName = (mode === 'smooth' ? 'spinner-smooth' : 'spinner');
|
}) => (
|
||||||
const spinnerDivCount = (mode === 'smooth' ? 24 : 12);
|
<img
|
||||||
return (
|
alt="loading animation"
|
||||||
<div className={spinnerClassName}>
|
className={classNames('studio-status-icon-spinner', className)}
|
||||||
{range(1, spinnerDivCount + 1).map(id => (
|
src={`/svgs/modal/spinner-${color}.svg`}
|
||||||
<div
|
/>
|
||||||
className={`circle${id} circle`}
|
);
|
||||||
key={`circle${id}`}
|
|
||||||
/>
|
Spinner.defaultProps = {
|
||||||
))}
|
color: 'white'
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Spinner.propTypes = {
|
Spinner.propTypes = {
|
||||||
mode: PropTypes.string
|
className: PropTypes.string,
|
||||||
|
color: PropTypes.oneOf(['white', 'blue', 'transparent-gray'])
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Spinner;
|
module.exports = Spinner;
|
||||||
|
|
|
@ -1,118 +1,44 @@
|
||||||
@import "../../colors";
|
.studio-status-icon-spinner {
|
||||||
|
/* This class can be used on an icon that should spin.
|
||||||
.spinner {
|
It first plays the intro animation, then spins forever. */
|
||||||
position: relative;
|
animation-name: intro, spin;
|
||||||
margin: 0 auto;
|
animation-duration: .25s, .5s;
|
||||||
width: 20px;
|
animation-timing-function: cubic-bezier(.3, -3, .6, 3), linear;
|
||||||
height: 20px;
|
animation-delay: 0s, .25s;
|
||||||
|
animation-iteration-count: 1, infinite;
|
||||||
.circle {
|
animation-direction: normal;
|
||||||
position: absolute;
|
width: 1.4rem; /* standard is 1.4 rem but can be overwritten by parent */
|
||||||
top: 0;
|
height: 1.4rem;
|
||||||
left: 0;
|
-webkit-animation-name: intro, spin;
|
||||||
width: 100%;
|
-webkit-animation-duration: .25s, .5s;
|
||||||
height: 100%;
|
-webkit-animation-iteration-count: 1, infinite;
|
||||||
|
-webkit-animation-delay: 0s, .25s;
|
||||||
&:before {
|
-webkit-animation-timing-function: cubic-bezier(.3, -3, .6, 3), linear;
|
||||||
display: block;
|
transform-origin: center;
|
||||||
animation: circleFadeDelay 1.2s infinite ease-in-out both;
|
|
||||||
margin: 0 auto;
|
|
||||||
border-radius: 100%;
|
|
||||||
background-color: $ui-gray;
|
|
||||||
width: 15%;
|
|
||||||
height: 15%;
|
|
||||||
content: "";
|
|
||||||
|
|
||||||
.white & {
|
|
||||||
background-color: $ui-blue-dark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@for $i from 1 through 12 {
|
|
||||||
$rotation: 30deg * ($i - 1);
|
|
||||||
$delay: -1.3s + $i * .1;
|
|
||||||
|
|
||||||
.circle#{$i} {
|
|
||||||
transform: rotate($rotation);
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
animation-delay: $delay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes circleFadeDelay {
|
@keyframes intro {
|
||||||
0%,
|
0% {
|
||||||
39%,
|
transform: scale(0);
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity: 0;
|
transform: scale(1);
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
-webkit-transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
/*********************/
|
0% {
|
||||||
/* type === "smooth" */
|
transform: rotate(0);
|
||||||
/*********************/
|
-webkit-transform: rotate(0);
|
||||||
|
|
||||||
.spinner-smooth {
|
|
||||||
position: relative;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
|
|
||||||
.circle {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
display: block;
|
|
||||||
animation: circleFadeDelaySmooth 1.8s infinite ease-in-out both;
|
|
||||||
margin: 0 auto;
|
|
||||||
border-radius: 100%;
|
|
||||||
background-color: $ui-white;
|
|
||||||
width: 30%;
|
|
||||||
height: 20%;
|
|
||||||
content: "";
|
|
||||||
|
|
||||||
.white & {
|
|
||||||
background-color: darken($ui-blue, 8%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@for $i from 1 through 24 {
|
100% {
|
||||||
$rotation: 15deg * ($i - 1);
|
transform: rotate(359deg);
|
||||||
$delay: -1.9s + $i * .075;
|
-webkit-transform: rotate(359deg);
|
||||||
|
|
||||||
.circle#{$i} {
|
|
||||||
transform: rotate($rotation);
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
animation-delay: $delay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes circleFadeDelaySmooth {
|
|
||||||
0%,
|
|
||||||
35% {
|
|
||||||
opacity: 0;
|
|
||||||
},
|
|
||||||
40% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,10 @@ const Components = () => (
|
||||||
<Box title="Carousel component in a box!">
|
<Box title="Carousel component in a box!">
|
||||||
<Carousel />
|
<Carousel />
|
||||||
</Box>
|
</Box>
|
||||||
<h1>This is a Spinner</h1>
|
<h1>This is a blue Spinner</h1>
|
||||||
<Spinner />
|
<Spinner
|
||||||
|
color="blue"
|
||||||
|
/>
|
||||||
<h1>Colors</h1>
|
<h1>Colors</h1>
|
||||||
<div className="colors">
|
<div className="colors">
|
||||||
<span className="ui-blue">$ui-blue</span>
|
<span className="ui-blue">$ui-blue</span>
|
||||||
|
|
|
@ -208,8 +208,8 @@ class Preview extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleToggleStudio (event) {
|
handleToggleStudio (id) {
|
||||||
const studioId = parseInt(event.currentTarget.dataset.id, 10);
|
const studioId = parseInt(id, 10);
|
||||||
if (isNaN(studioId)) { // sanity check in case event had no integer data-id
|
if (isNaN(studioId)) { // sanity check in case event had no integer data-id
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
10
static/svgs/modal/spinner-blue.svg
Normal file
10
static/svgs/modal/spinner-blue.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>spinner-blue</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="spinner-blue" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M15,10 C15,7.23857625 12.7614237,5 10,5 C7.23857625,5 5,7.23857625 5,10 C5,12.7614237 7.23857625,15 10,15" id="Oval-2" stroke="#4D97FF" stroke-width="2.5"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 686 B |
10
static/svgs/modal/spinner-transparent-gray.svg
Normal file
10
static/svgs/modal/spinner-transparent-gray.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>spinner-transparent-gray</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="spinner-transparent-gray" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.15">
|
||||||
|
<path d="M15,10 C15,7.23857625 12.7614237,5 10,5 C7.23857625,5 5,7.23857625 5,10 C5,12.7614237 7.23857625,15 10,15" id="Oval-2" stroke="#000000" stroke-width="2.5"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 732 B |
10
static/svgs/modal/spinner-white.svg
Normal file
10
static/svgs/modal/spinner-white.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>spinner-white</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="spinner-white" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M15,10 C15,7.23857625 12.7614237,5 10,5 C7.23857625,5 5,7.23857625 5,10 C5,12.7614237 7.23857625,15 10,15" id="Oval-2" stroke="#FFFFFF" stroke-width="2.5"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 688 B |
|
@ -1 +0,0 @@
|
||||||
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M15 10a5 5 0 1 0-5 5" stroke="#FFF" stroke-width="2.5" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
Before Width: | Height: | Size: 213 B |
Loading…
Reference in a new issue