Publish modal updates (#20817)

The new modal for the updated publishing flow has an entirely new
layout, based on feedback previously received. In addition, this PR
includes a few tweaks to the underlying logic.
This commit is contained in:
Daniël van der Winden 2024-08-22 16:49:29 +02:00 committed by GitHub
parent cd7c27d3ad
commit 7c992825ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 328 additions and 128 deletions

View File

@ -96,10 +96,14 @@ export default class PublishFlowOptions extends Component {
if (this.feature.publishFlowEndScreen) { if (this.feature.publishFlowEndScreen) {
if (this.args.publishOptions.isScheduled) { if (this.args.publishOptions.isScheduled) {
localStorage.setItem('ghost-last-scheduled-post', this.args.publishOptions.post.id); localStorage.setItem('ghost-last-scheduled-post', this.args.publishOptions.post.id);
this.router.transitionTo('posts', {queryParams: {type: 'scheduled'}}); this.router.transitionTo('posts');
} else { } else {
localStorage.setItem('ghost-last-published-post', this.args.publishOptions.post.id); localStorage.setItem('ghost-last-published-post', this.args.publishOptions.post.id);
this.router.transitionTo('posts.analytics', this.args.publishOptions.post.id); if (this.args.publishOptions.post.emailOnly) {
this.router.transitionTo('posts.analytics', this.args.publishOptions.post.id);
} else {
this.router.transitionTo('posts');
}
} }
} }
} catch (e) { } catch (e) {

View File

@ -6,8 +6,41 @@
isFailure=this.isFailure isFailure=this.isFailure
)}} )}}
{{else}} {{else}}
{{#if this.isRunning}}<span data-test-task-button-state="running">{{#if this.showIcon}}{{svg-jar "spinner" class="gh-icon-spinner"}} {{/if}}{{this.runningText}}</span>{{/if}} {{#if this.isRunning}}
{{#if this.isIdle}}<span data-test-task-button-state="idle">{{this.buttonText}}</span>{{/if}} <span data-test-task-button-state="running">
{{#if this.isSuccess}}<span {{did-insert this.handleReset}} data-test-task-button-state="success">{{#if this.showIcon}}{{svg-jar "check-circle"}} {{/if}}{{this.successText}}</span>{{/if}} {{#if this.showIcon}}
{{#if this.isFailure}}<span data-test-task-button-state="failure">{{#if this.showIcon}}{{svg-jar "retry"}} {{/if}}{{this.failureText}}</span>{{/if}} {{svg-jar "spinner" class="gh-icon-spinner"}}
{{/if}}
{{this.runningText}}
</span>
{{/if}}
{{#if (and this.isIdle (not (or this.isRunning this.isSuccess this.isFailure)))}}
<span data-test-task-button-state="idle">
{{#if this.showIcon}}
{{#if this.idleIcon}}
{{svg-jar this.idleIcon}}
{{/if}}
{{/if}}
{{this.buttonText}}
</span>
{{/if}}
{{#if this.isSuccess}}
<span {{did-insert this.handleReset}} data-test-task-button-state="success">
{{#if this.showIcon}}
{{svg-jar "check-circle"}}
{{/if}}
{{this.successText}}
</span>
{{/if}}
{{#if this.isFailure}}
<span data-test-task-button-state="failure">
{{#if this.showIcon}}
{{svg-jar "retry"}}
{{/if}}
{{this.failureText}}
</span>
{{/if}}
{{/if}} {{/if}}

View File

@ -33,6 +33,7 @@ const GhTaskButton = Component.extend({
defaultClick: false, defaultClick: false,
buttonText: 'Save', buttonText: 'Save',
idleClass: '', idleClass: '',
idleIcon: '',
runningClass: '', runningClass: '',
showIcon: true, showIcon: true,
showSuccess: true, // set to false if you want the spinner to show until a transition occurs showSuccess: true, // set to false if you want the spinner to show until a transition occurs

View File

@ -1,18 +1,4 @@
<div class="modal-content"> <div class="modal-content">
{{#if this.post.featureImage}}
<figure class="modal-image">
<img src="{{this.post.featureImage}}" alt="{{this.post.title}}">
</figure>
{{else if this.post.twitterImage}}
<figure class="modal-image">
<img src="{{this.post.twitterImage}}" alt="{{this.post.title}}">
</figure>
{{else if this.post.ogImage}}
<figure class="modal-image">
<img src="{{this.post.ogImage}}" alt="{{this.post.title}}">
</figure>
{{/if}}
<header class="modal-header"> <header class="modal-header">
<h1> <h1>
{{#if this.post.isScheduled}} {{#if this.post.isScheduled}}
@ -22,7 +8,7 @@
{{#if this.showPostCount}} {{#if this.showPostCount}}
Boom! It's out there. Boom! It's out there.
{{else}} {{else}}
Your post is out there. Your post is published.
{{/if}} {{/if}}
</span> </span>
<span> <span>
@ -32,7 +18,7 @@
{{#if this.showPostCount}} {{#if this.showPostCount}}
That's {{format-number this.postCount}} {{gh-pluralize this.postCount "post" without-count=true}} published. That's {{format-number this.postCount}} {{gh-pluralize this.postCount "post" without-count=true}} published.
{{else}} {{else}}
Share it with the world! Spread the word!
{{/if}} {{/if}}
{{/if}} {{/if}}
</span> </span>
@ -40,93 +26,156 @@
</h1> </h1>
</header> </header>
<button type="button" class="close" title="Close" {{on "click" @close}}>{{svg-jar "close"}}<span class="hidden">Close</span></button> {{#if (and this.post.isPublished (not this.post.emailOnly))}}
{{else}}
<div class="modal-body"> <div class="modal-body email">
{{#if (and this.post.isPublished (not this.post.emailOnly))}} {{#if this.post.isSent}}
{{#if this.showPostCount}} It
Keep up the good work. Now, share your post with the world!
{{else}}
Spread the word to your audience and increase your reach.
{{/if}}
{{else}} {{else}}
{{#if this.post.isSent}} {{if this.post.emailOnly "Your email" "Your post"}}
It {{/if}}
{{else}} {{if this.post.isScheduled "will be" "was"}}
{{if this.post.emailOnly "Your email" "Your post"}} {{#if this.post.emailOnly}}
{{/if}} sent to
{{if this.post.isScheduled "will be" "was"}} {{else if this.post.willEmail}}
{{#if this.post.emailOnly}} published on your site, and sent to
sent to {{else}}
{{else if this.post.willEmail}} published on your site
published on your site, and sent to {{/if}}
{{else}}
published on your site
{{/if}}
{{#if (or this.post.hasEmail this.post.willEmail)}} {{#if (or this.post.hasEmail this.post.willEmail)}}
{{#let (members-count-fetcher query=(hash filter=this.post.fullRecipientFilter)) as |countFetcher|}} {{#let (members-count-fetcher query=(hash filter=this.post.fullRecipientFilter)) as |countFetcher|}}
<strong class="nowrap"> <strong class="nowrap">
{{if (eq @recipientType "all") "all"}} {{if (eq @recipientType "all") "all"}}
{{format-number countFetcher.count}} {{format-number countFetcher.count}}
{{!-- @recipientType = free/paid/all/specific --}} {{!-- @recipientType = free/paid/all/specific --}}
{{if (not-eq @recipientType "all") @recipientType}} {{if (not-eq @recipientType "all") @recipientType}}
{{gh-pluralize countFetcher.count "subscriber" without-count=true}} {{gh-pluralize countFetcher.count "subscriber" without-count=true}}
</strong> </strong>
of <strong>{{this.post.newsletter.name}}</strong> of <strong>{{this.post.newsletter.name}}</strong>
{{/let}}
{{/if}}
{{#let (moment-site-tz this.post.publishedAtUTC) as |publishedAt|}}
on
{{moment-format publishedAt "D MMM YYYY"}}
at
{{moment-format publishedAt "HH:mm"}}.
{{/let}} {{/let}}
{{/if}} {{/if}}
{{#let (moment-site-tz this.post.publishedAtUTC) as |publishedAt|}}
on
<strong>{{moment-format publishedAt "D MMM YYYY"}}</strong>
at
<strong>{{moment-format publishedAt "HH:mm"}}</strong>.
{{/let}}
</div> </div>
<footer class="modal-footer"> {{#if this.post.emailOnly}}
{{#if (and this.post.isPublished (not this.post.emailOnly))}} <footer class="modal-footer-email">
<a href="https://twitter.com/intent/tweet?text={{this.encodedTitle}}&url={{this.encodedUrl}}" class="gh-btn twitter" target="_blank" rel="noopener noreferrer">
<span>{{svg-jar "social-x"}}</span>
</a>
<a href="https://threads.net/intent/post?text={{this.encodedTitleAndUrl}}" class="gh-btn threads" target="_blank" rel="noopener noreferrer">
<span>{{svg-jar "social-threads"}}</span>
</a>
<a href="https://www.facebook.com/sharer/sharer.php?u={{this.encodedUrl}}" class="gh-btn facebook" target="_blank" rel="noopener noreferrer">
<span>{{svg-jar "social-facebook"}}</span>
</a>
<a href="http://www.linkedin.com/shareArticle?mini=true&title={{this.encodedTitle}}&url={{this.encodedUrl}}" class="gh-btn linkedin" target="_blank" rel="noopener noreferrer">
<span>{{svg-jar "social-linkedin"}}</span>
</a>
<GhTaskButton
@buttonText="Copy link"
@task={{this.handleCopyLink}}
@showIcon={{true}}
@successText="Link copied"
@class="gh-btn gh-btn-primary gh-btn-icon copy-link" />
{{else}}
{{#if (and this.post.isScheduled (not this.post.emailOnly))}}
<GhTaskButton
@buttonText="Copy preview link"
@task={{this.handleCopyPreviewLink}}
@successText="Link copied"
@class="gh-btn gh-btn-icon copy-preview-link" />
{{/if}}
<button <button
class="gh-btn gh-btn-primary dismiss" class="gh-btn gh-btn-primary dismiss"
type="button" type="button"
{{on "click" @close}} {{on "click" @close}}
{{on "mousedown" (optional this.noop)}} {{on "mousedown" (optional this.noop)}}
> >
<span>OK</span> <span>Close</span>
</button> </button>
</footer>
{{/if}}
{{/if}}
<button type="button" class="close" title="Close" {{on "click" @close}}>{{svg-jar "close"}}<span class="hidden">Close</span></button>
{{#unless this.post.emailOnly}}
<div class="gh-post-card">
{{#if this.post.featureImage}}
<figure class="modal-image">
<img src="{{this.post.featureImage}}" alt="{{this.post.title}}">
</figure>
{{else if this.post.twitterImage}}
<figure class="modal-image">
<img src="{{this.post.twitterImage}}" alt="{{this.post.title}}">
</figure>
{{else if this.post.ogImage}}
<figure class="modal-image">
<img src="{{this.post.ogImage}}" alt="{{this.post.title}}">
</figure>
{{/if}} {{/if}}
</footer>
<div class="modal-body">
<h2>{{this.post.title}}</h2>
{{#if this.post.excerpt}}
<p class="post-excerpt">{{this.post.excerpt}}</p>
{{/if}}
<div class="gh-post-details">
{{#if (get-setting "icon")}}
<div class="gh-post-bookmark-site-icon">
<img src={{get-setting "icon"}} alt="" role="presentation" />
</div>
{{/if}}
{{#if (get-setting "title")}}
<div class="gh-post-bookmark-site-name">{{get-setting "title"}}</div>
{{/if}}
<div class="gh-post-bookmark-authors">{{this.authorNames}}</div>
</div>
</div>
<footer class="modal-footer">
{{#if (and this.post.isPublished (not this.post.emailOnly))}}
<div class="share-buttons">
<a href="https://twitter.com/intent/tweet?text={{this.encodedTitle}}&url={{this.encodedUrl}}" class="gh-btn twitter" target="_blank" rel="noopener noreferrer" title="Share on Twitter">
<span>{{svg-jar "social-x"}}</span>
</a>
<a href="https://threads.net/intent/post?text={{this.encodedTitleAndUrl}}" class="gh-btn threads" target="_blank" rel="noopener noreferrer" title="Share on Threads">
<span>{{svg-jar "social-threads"}}</span>
</a>
<a href="https://www.facebook.com/sharer/sharer.php?u={{this.encodedUrl}}" class="gh-btn facebook" target="_blank" rel="noopener noreferrer" title="Share on Facebook">
<span>{{svg-jar "social-facebook"}}</span>
</a>
<a href="http://www.linkedin.com/shareArticle?mini=true&title={{this.encodedTitle}}&url={{this.encodedUrl}}" class="gh-btn linkedin" target="_blank" rel="noopener noreferrer" title="Share on LinkedIn">
<span>{{svg-jar "social-linkedin"}}</span>
</a>
</div>
<GhTaskButton
@showIcon={{true}}
@idleIcon="link"
@buttonText="Copy link"
@title="Copy link"
@task={{this.handleCopyLink}}
@successText="Link copied"
@class="gh-btn gh-btn-primary gh-btn-icon copy-link" />
{{else}}
{{#if (and this.post.isScheduled (not this.post.emailOnly))}}
<GhTaskButton
@buttonText="Copy preview link"
@task={{this.handleCopyPreviewLink}}
@showIcon={{true}}
@idleIcon="link"
@successText="Preview link copied"
@class="gh-btn gh-btn-icon copy-preview-link" />
<button
class="gh-btn gh-btn-primary dismiss"
type="button"
{{on "click" @close}}
{{on "mousedown" (optional this.noop)}}
>
<span>Close</span>
</button>
{{else}}
<button
class="gh-btn gh-btn-primary dismiss"
type="button"
{{on "click" @close}}
{{on "mousedown" (optional this.noop)}}
>
<span>Close</span>
</button>
{{/if}}
{{/if}}
</footer>
</div>
{{/unless}}
</div> </div>

View File

@ -1,5 +1,6 @@
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import copyTextToClipboard from 'ghost-admin/utils/copy-text-to-clipboard'; import copyTextToClipboard from 'ghost-admin/utils/copy-text-to-clipboard';
import {authorNames} from '../helpers/author-names';
import {capitalize} from '@ember/string'; import {capitalize} from '@ember/string';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
import {task, timeout} from 'ember-concurrency'; import {task, timeout} from 'ember-concurrency';
@ -38,6 +39,10 @@ export default class PostSuccessModal extends Component {
return encodeURIComponent(`${this.post.title} ${this.post.url}`); return encodeURIComponent(`${this.post.title} ${this.post.url}`);
} }
get authorNames() {
return authorNames([this.post.authors]);
}
@task @task
*handleCopyLink() { *handleCopyLink() {
copyTextToClipboard(this.post.url); copyTextToClipboard(this.post.url);

View File

@ -2,13 +2,17 @@ import Component from '@glimmer/component';
import PostSuccessModal from '../modal-post-success'; import PostSuccessModal from '../modal-post-success';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency'; import {task} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';
export default class PostsList extends Component { export default class PostsList extends Component {
@service store; @service store;
@service modals; @service modals;
@service feature; @service feature;
@tracked postCount = 0;
latestScheduledPost = null; latestScheduledPost = null;
latestPublishedPost = null;
constructor() { constructor() {
super(...arguments); super(...arguments);
@ -25,6 +29,17 @@ export default class PostsList extends Component {
}); });
localStorage.removeItem('ghost-last-scheduled-post'); localStorage.removeItem('ghost-last-scheduled-post');
} }
if (localStorage.getItem('ghost-last-published-post')) {
await this.getlatestPublishedPost.perform();
await this.getPostCount.perform();
this.modals.open(PostSuccessModal, {
post: this.latestPublishedPost,
postCount: this.postCount,
showPostCount: true
});
localStorage.removeItem('ghost-last-published-post');
}
} }
get list() { get list() {
@ -36,4 +51,16 @@ export default class PostsList extends Component {
const result = yield this.store.query('post', {filter: `id:${localStorage.getItem('ghost-last-scheduled-post')}`, limit: 1}); const result = yield this.store.query('post', {filter: `id:${localStorage.getItem('ghost-last-scheduled-post')}`, limit: 1});
this.latestScheduledPost = result.toArray()[0]; this.latestScheduledPost = result.toArray()[0];
} }
}
@task
*getlatestPublishedPost() {
const result = yield this.store.query('post', {filter: `id:${localStorage.getItem('ghost-last-published-post')}`, limit: 1});
this.latestPublishedPost = result.toArray()[0];
}
@task
*getPostCount() {
const result = yield this.store.query('post', {filter: 'status:published', limit: 1, page: 1});
this.postCount = result.meta.pagination.total;
}
}

View File

@ -895,10 +895,16 @@
border-radius: var(--radius); border-radius: var(--radius);
} }
.modal-post-success .gh-post-card {
border-radius: 8px;
border: 1px solid var(--lightgrey-l1);
box-sizing: border-box;
margin: 24px 0 0 0;
}
.modal-post-success .modal-image { .modal-post-success .modal-image {
aspect-ratio: 16 / 7.55; aspect-ratio: 16 / 7.55;
overflow: hidden; overflow: hidden;
margin: calc(var(--padding) * -1) calc(var(--padding) * -1) var(--padding);
} }
.modal-post-success .modal-image img { .modal-post-success .modal-image img {
@ -906,7 +912,8 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
border-radius: var(--radius) var(--radius) 0 0; border-radius: 7px 7px 0 0;
box-sizing: border-box;
} }
.modal-post-success .modal-header { .modal-post-success .modal-header {
@ -932,6 +939,48 @@
line-height: 1.4; line-height: 1.4;
letter-spacing: -0.01em; letter-spacing: -0.01em;
text-wrap: pretty; text-wrap: pretty;
padding: 16px 24px;
}
.modal-post-success .modal-body p {
font-size: 1.6rem;
line-height: 1.5em;
}
.modal-post-success .modal-body p.post-excerpt {
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
margin: 0 0 16px 0;
}
.modal-post-success .email {
font-size: 1.6rem;
padding: 0;
}
.modal-post-success .modal-body .gh-post-details {
display: flex;
align-items: center;
gap: 4px;
margin-bottom: 16px;
font-size: 1.4rem;
}
.modal-post-success .modal-body .gh-post-details .gh-post-bookmark-site-name {
font-weight: 600;
flex-shrink: 0;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.modal-post-success .modal-body .gh-post-bookmark-site-icon {
width: 24px;
height: 24px;
} }
.modal-post-success .modal-body strong.nowrap { .modal-post-success .modal-body strong.nowrap {
@ -939,17 +988,44 @@
} }
.modal-post-success .modal-footer { .modal-post-success .modal-footer {
background: var(--whitegrey-l2);
margin-top: 0;
gap: 16px;
padding: 16px 24px;
border-top: 1px solid var(--lightgrey-l1);
border-radius: 0 0 8px 8px;
}
.modal-post-success .modal-footer-email {
background: var(--white);
margin-top: 36px;
gap: 16px;
padding: 0;
border: none;
border-radius: 0;
text-align: right;
}
.modal-post-success .modal-footer .share-buttons {
display: flex;
justify-content: space-evenly;
align-items: center;
gap: 16px; gap: 16px;
margin-top: var(--padding);
} }
.modal-post-success .modal-footer .gh-btn { .modal-post-success .modal-footer .gh-btn {
display: flex;
justify-content: center;
align-items: center;
min-width: 64px; min-width: 64px;
height: 40px; height: 40px;
border-radius: 4px; border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
}
.modal-post-success .modal-footer .copy-preview-link {
background: var(--white);
border: 1px solid var(--lightgrey-l1);
} }
.modal-post-success .modal-footer .gh-btn:not(:first-child) { .modal-post-success .modal-footer .gh-btn:not(:first-child) {
@ -959,6 +1035,8 @@
.modal-post-success .modal-footer .gh-btn span { .modal-post-success .modal-footer .gh-btn span {
padding-inline: 18px; padding-inline: 18px;
font-size: 1.4rem; font-size: 1.4rem;
height: 100%;
align-content: center;
} }
.modal-post-success .modal-footer .gh-btn-primary { .modal-post-success .modal-footer .gh-btn-primary {
@ -971,6 +1049,12 @@
.modal-post-success .modal-footer .gh-btn:is(.twitter, .threads, .facebook, .linkedin) { .modal-post-success .modal-footer .gh-btn:is(.twitter, .threads, .facebook, .linkedin) {
width: 56px; width: 56px;
background: var(--white);
border: 1px solid var(--lightgrey-l1);
}
.modal-post-success .modal-footer .gh-btn:is(.twitter, .threads, .facebook, .linkedin, .copy-link, .copy-preview-link):hover {
background: var(--whitegrey-l1);
} }
.modal-post-success .modal-footer .gh-btn:is(.twitter, .threads, .facebook, .linkedin) span { .modal-post-success .modal-footer .gh-btn:is(.twitter, .threads, .facebook, .linkedin) span {
@ -991,27 +1075,18 @@
right: 24px; right: 24px;
} }
.modal-post-success:has(.modal-image) .close { @media (max-width: 500px) {
display: flex; .modal-post-success .modal-header h1 {
justify-content: center; font-size: 2.4rem;
align-items: center; }
width: 32px;
height: 32px; .modal-post-success .modal-footer {
top: 16px; display: flex;
right: 16px; flex-direction: column;
background-color: rgba(0, 0, 0, 0.4); }
border-radius: 50%;
}
.modal-post-success:has(.modal-image) .close:hover { .modal-post-success .modal-footer .copy-link,
background-color: rgba(0, 0, 0, 0.3); .modal-post-success .modal-footer .copy-preview-link {
} width: 100%!important;
}
.modal-post-success:has(.modal-image) .close svg { }
width: 14px;
height: 14px;
}
.modal-post-success:has(.modal-image) .close svg path {
fill: white;
}

View File

@ -725,7 +725,7 @@
.gh-canvas-title.gh-post-title { .gh-canvas-title.gh-post-title {
max-width: 880px; max-width: 880px;
padding: 20px 0 12px; padding: 20px 0 0 0;
font-size: 3.2rem; font-size: 3.2rem;
line-height: 1.2em; line-height: 1.2em;
overflow: inherit; overflow: inherit;
@ -1481,6 +1481,11 @@
transition: all .1s linear; transition: all .1s linear;
} }
.gh-post-list-cta:hover {
border-color: var(--lightgrey-l2);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}
.gh-list-data .gh-post-list-cta { .gh-list-data .gh-post-list-cta {
justify-content: center; justify-content: center;
width: 56px; width: 56px;
@ -1491,6 +1496,10 @@
margin-right: 0; margin-right: 0;
} }
.gh-post-analytics-header .share svg {
margin-top: -2px;
}
.gh-post-list-cta.is-hovered { .gh-post-list-cta.is-hovered {
border-color: var(--whitegrey-d2); border-color: var(--whitegrey-d2);
} }

View File

@ -1,4 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="Hyperlink-3--Streamline-Ultimate.svg" height="24" width="24"><desc>Hyperlink 3 Streamline Icon: https://streamlinehq.com</desc><path d="m9.364 18.5 -0.932 0.932a4.5 4.5 0 0 1 -6.364 -6.364l4.773 -4.774a4.5 4.5 0 0 1 6.825 5.825" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="m14.818 5.567 0.75 -0.75a4.5 4.5 0 0 1 6.364 6.364l-4.773 4.773a4.5 4.5 0 0 1 -6.824 -5.826" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></svg>
<title>link</title>
<path stroke="currentColor" d="m14.5 12.5.086.086a2 2 0 0 0 2.828 0l3.965-3.964a3.01 3.01 0 0 0 0-4.243l-1.758-1.757a3.008 3.008 0 0 0-4.242 0l-3.965 3.964a2 2 0 0 0 0 2.829l.086.085m-2 2-.086-.085a2 2 0 0 0-2.828 0l-3.965 3.964a3.01 3.01 0 0 0 0 4.243l1.758 1.757a3.008 3.008 0 0 0 4.242 0l3.965-3.964a2 2 0 0 0 0-2.829L12.5 14.5m-4.389 1.389 7.778-7.778" fill="none"/>
</svg>

Before

Width:  |  Height:  |  Size: 485 B

After

Width:  |  Height:  |  Size: 615 B