0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

🎨 first pass at animated icons for save-state buttons (#637)

refs https://github.com/TryGhost/Ghost/issues/7515
- adds animated spinner and check SVG icons
- improves SVG sizing/alignment in buttons
- disables old technique of fixing button size because it doesn't work now that buttons have more than a single spinner when running/saved/failed
- fixes broken spinner in `gh-spin-button` components
This commit is contained in:
Kevin Ansfield 2017-04-11 16:44:37 +01:00 committed by Hannah Wolfe
parent 10653fbca6
commit 2f767bef1e
8 changed files with 62 additions and 13 deletions

View file

@ -94,11 +94,11 @@ const GhTaskButton = Component.extend({
setSize: observer('isRunning', function () { setSize: observer('isRunning', function () {
if (this.get('isRunning')) { if (this.get('isRunning')) {
this.set('hasRun', true); this.set('hasRun', true);
this.$().width(this.$().width()); // this.$().width(this.$().width());
this.$().height(this.$().height()); // this.$().height(this.$().height());
} else { } else {
this.$().width(''); // this.$().width('');
this.$().height(''); // this.$().height('');
} }
}) })
}); });

View file

@ -292,23 +292,51 @@ fieldset[disabled] .gh-btn {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.gh-btn-icon svg { .gh-btn-icon svg,
margin-right: 10px; .gh-btn-block svg {
height: 13px; width: 1em;
height: 1em;
margin-right: 0.5em;
fill: #fff; fill: #fff;
} }
.gh-btn-icon-right svg { .gh-btn-icon-right svg {
margin-left: 10px; margin-left: 0.5em;
margin-right: 0; margin-right: 0;
} }
.gh-btn-block svg {
margin-right: 0;
}
.gh-btn-icon svg path { .gh-btn-icon svg path {
stroke: #fff; stroke: #fff;
} }
/*
/* Animated button icons
/* ---------------------------------------------------------- */
path.animated-check-circle {
stroke: white;
stroke-dashoffset: 300;
stroke-dasharray: 300;
animation: dash 4s ease-out forwards;
}
@keyframes dash {
0% {
stroke-dashoffset: 300;
}
100% {
stroke-dashoffset: 0;
}
}
/* /*
/* Loading Button Spinner /* Loading Button Spinner

View file

@ -1,3 +1,19 @@
path.animated-check-circle {
stroke: white;
stroke-dashoffset: 300;
stroke-dasharray: 300;
animation: dash 4s ease-out forwards;
}
@keyframes dash {
0% {
stroke-dashoffset: 300;
}
100% {
stroke-dashoffset: 0;
}
}
/* Icons /* Icons
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
/* CUSTOM GENERATED FILE */ /* CUSTOM GENERATED FILE */

View file

@ -1,5 +1,5 @@
{{#if showSpinner}} {{#if showSpinner}}
<span class="spinner"></span> <span>{{inline-svg "spinner"}}</span>
{{else}} {{else}}
{{#if buttonText}} {{#if buttonText}}
{{buttonText}} {{buttonText}}

View file

@ -7,7 +7,7 @@
)}} )}}
{{else}} {{else}}
<span> <span>
{{#if isRunning}}<span class="spinner"></span>{{/if}} {{#if isRunning}}{{inline-svg "spinner"}}{{/if}}
{{if (or isIdle isRunning) buttonText}} {{if (or isIdle isRunning) buttonText}}
{{#if isSuccess}}{{inline-svg "check-circle"}} {{successText}}{{/if}} {{#if isSuccess}}{{inline-svg "check-circle"}} {{successText}}{{/if}}
{{#if isFailure}}{{inline-svg "close"}} {{failureText}}{{/if}} {{#if isFailure}}{{inline-svg "close"}} {{failureText}}{{/if}}

View file

@ -1 +1,5 @@
<svg version="1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g><path d="M16.659 8.134l-7.146 6.67-2.159-2.158c-.195-.195-.512-.195-.707 0s-.195.512 0 .707l2.5 2.5c.097.098.225.147.353.147.123 0 .245-.045.341-.134l7.5-7c.202-.188.212-.505.024-.707-.188-.202-.503-.213-.706-.025zM12 0c-6.617 0-12 5.383-12 12s5.383 12 12 12 12-5.383 12-12-5.383-12-12-12zm0 23c-6.065 0-11-4.935-11-11s4.935-11 11-11 11 4.935 11 11-4.935 11-11 11z"/></g></svg> <svg width="26px" height="26px" viewBox="-1 -1 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="check-circle" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path class="animated-check-circle" d="M19.6004116,2.71490714 C17.5353801,1.0196018 14.8927356,0 12,0 C5.38938053,0 0,5.38938053 0,12 C0,18.6106195 5.38938053,24 12,24 C18.6106195,24 24,18.6106195 24,12 C24,9.71681416 23.3628319,7.59292035 22.2743363,5.78761062 L11.0442478,17.0442478 L5.49557522,11.4955752" id="Shape" stroke="#000000" stroke-width="2"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 475 B

After

Width:  |  Height:  |  Size: 622 B

View file

@ -0,0 +1 @@
<svg width='24px' height='24px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-default"><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(0 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(30 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.08333333333333333s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(60 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.16666666666666666s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(90 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.25s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(120 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.3333333333333333s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(150 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.4166666666666667s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(180 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.5s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(210 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.5833333333333334s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(240 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.6666666666666666s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(270 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.75s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(300 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.8333333333333334s' repeatCount='indefinite'/></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#fefefe' transform='rotate(330 50 50) translate(0 -40)'> <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.9166666666666666s' repeatCount='indefinite'/></rect></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -49,7 +49,7 @@ describe('Integration: Component: gh-task-button', function() {
this.get('myTask').perform(); this.get('myTask').perform();
run.later(this, function () { run.later(this, function () {
expect(this.$('button')).to.have.descendants('span.spinner'); expect(this.$('button')).to.have.descendants('svg');
}, 20); }, 20);
wait().then(done); wait().then(done);
@ -189,7 +189,7 @@ describe('Integration: Component: gh-task-button', function() {
}); });
}); });
it('keeps button size when showing spinner', function (done) { it.skip('keeps button size when showing spinner', function (done) {
this.set('myTask', task(function* () { this.set('myTask', task(function* () {
yield timeout(50); yield timeout(50);
})); }));