diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss
index 6f28edf69..5096ecd6a 100644
--- a/frontend/resources/styles/common/refactor/basic-rules.scss
+++ b/frontend/resources/styles/common/refactor/basic-rules.scss
@@ -659,22 +659,6 @@
color: var(--modal-button-foreground-color-error);
}
-.loader-base {
- @include flexCenter;
- position: fixed;
- top: 0;
- left: 0;
- height: 100vh;
- width: 100vw;
- z-index: $z-index-alert;
- background-color: var(--loader-background);
- :global(svg#loader-pencil) {
- height: $s-100;
- width: $s-100;
- animation: loaderColor 5s infinite ease;
- fill: var(--icon-foreground);
- }
-}
// UI ELEMENTS
.asset-element {
@include bodySmallTypography;
diff --git a/frontend/resources/styles/main-default.scss b/frontend/resources/styles/main-default.scss
index 769e9a6d8..15d5f2c84 100644
--- a/frontend/resources/styles/main-default.scss
+++ b/frontend/resources/styles/main-default.scss
@@ -29,11 +29,3 @@
// TODO: remove this stylesheet once the new text editor is in place
// https: //tree.taiga.io/project/penpot/us/8165
@import "main/partials/texts";
-
-//#################################################
-// Partials
-//#################################################
-
-// TODO: encapsulate pencil loader into its own component
-// https: //tree.taiga.io/project/penpot/task/8217
-@import "main/partials/loader";
diff --git a/frontend/resources/styles/main/partials/loader.scss b/frontend/resources/styles/main/partials/loader.scss
deleted file mode 100644
index 14154849d..000000000
--- a/frontend/resources/styles/main/partials/loader.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-// btn pencil loader
-svg#loader-pencil {
- fill: var(--color-accent-tertiary);
- width: 60px;
-}
-
-#loader-line {
- animation: linePencil 0.8s infinite linear;
-}
diff --git a/frontend/src/app/main/ui/auth/verify_token.cljs b/frontend/src/app/main/ui/auth/verify_token.cljs
index c2925b429..81d92ede5 100644
--- a/frontend/src/app/main/ui/auth/verify_token.cljs
+++ b/frontend/src/app/main/ui/auth/verify_token.cljs
@@ -5,13 +5,12 @@
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.auth.verify-token
- (:require-macros [app.main.style :as stl])
(:require
[app.main.data.messages :as msg]
[app.main.data.users :as du]
[app.main.repo :as rp]
[app.main.store :as st]
- [app.main.ui.icons :as i]
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.static :as static]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -95,5 +94,5 @@
(if @bad-token
[:> static/invalid-token {}]
- [:div {:class (stl/css :verify-token)}
- i/loader-pencil])))
+ [:> loader* {:title (tr "labels.loading")
+ :overlay true}])))
diff --git a/frontend/src/app/main/ui/auth/verify_token.scss b/frontend/src/app/main/ui/auth/verify_token.scss
deleted file mode 100644
index df815d4f4..000000000
--- a/frontend/src/app/main/ui/auth/verify_token.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-@use "./common.scss";
-
-.verify-token {
- @extend .loader-base;
-}
diff --git a/frontend/src/app/main/ui/dashboard.scss b/frontend/src/app/main/ui/dashboard.scss
index bad41ea11..26d4f051a 100644
--- a/frontend/src/app/main/ui/dashboard.scss
+++ b/frontend/src/app/main/ui/dashboard.scss
@@ -13,11 +13,6 @@
grid-template-columns: $s-40 $s-256 1fr;
grid-template-rows: $s-52 1fr;
height: 100vh;
-
- :global(svg#loader-pencil) {
- fill: $df-secondary;
- width: $s-32;
- }
}
.dashboard-content {
diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs
index dfffc9c66..e5550d943 100644
--- a/frontend/src/app/main/ui/dashboard/grid.cljs
+++ b/frontend/src/app/main/ui/dashboard/grid.cljs
@@ -25,6 +25,7 @@
[app.main.ui.dashboard.import :refer [use-import-file]]
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.placeholder :refer [empty-placeholder loading-placeholder]]
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.worker :as wrk]
@@ -95,7 +96,8 @@
:src thumbnail-uri
:loading "lazy"
:decoding "async"}]
- i/loader-pencil))]))
+ [:> loader* {:class (stl/css :grid-loader)
+ :title (tr "labels.loading")}]))]))
;; --- Grid Item Library
@@ -113,7 +115,8 @@
[:div {:class (stl/css :grid-item-th :library)}
(if (nil? file)
- i/loader-pencil
+ [:> loader* {:class (stl/css :grid-loader)
+ :title (tr "labels.loading")}]
(let [summary (:library-summary file)
components (:components summary)
colors (:colors summary)
@@ -458,7 +461,6 @@
:on-drag-leave on-drag-leave
:on-drop on-drop
:ref node-ref}
-
(cond
(nil? files)
[:& loading-placeholder]
diff --git a/frontend/src/app/main/ui/dashboard/grid.scss b/frontend/src/app/main/ui/dashboard/grid.scss
index 3853c71f7..996957ae1 100644
--- a/frontend/src/app/main/ui/dashboard/grid.scss
+++ b/frontend/src/app/main/ui/dashboard/grid.scss
@@ -278,16 +278,6 @@ $thumbnail-default-height: $s-168; // Default width
height: auto;
width: 100%;
}
-
- svg {
- height: 100%;
- width: 100%;
- }
-
- :global(svg#loader-pencil) {
- stroke: $db-quaternary;
- width: calc(var(--th-width, #{$thumbnail-default-width}) * 0.25);
- }
}
// LIBRARY VIEW
@@ -381,3 +371,9 @@ $thumbnail-default-height: $s-168; // Default width
grid-template-columns: auto 1fr;
gap: $s-8;
}
+
+.grid-loader {
+ width: calc(var(--th-width, #{$thumbnail-default-width}) * 0.25);
+ height: 100%;
+ align-self: center;
+}
diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs
index 51b437116..79aca61cc 100644
--- a/frontend/src/app/main/ui/dashboard/import.cljs
+++ b/frontend/src/app/main/ui/dashboard/import.cljs
@@ -18,6 +18,7 @@
[app.main.features :as features]
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader]]
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.icons :as i]
[app.main.ui.notifications.context-notification :refer [context-notification]]
[app.main.worker :as uw]
@@ -266,14 +267,18 @@
:editable (and ready? (not editing?)))}
[:div {:class (stl/css :file-name)}
- [:div {:class (stl/css-case :file-icon true
- :icon-fill ready?)}
- (cond loading? i/loader-pencil
- ready? i/logo-icon
- import-warn? i/msg-warning
- import-error? i/close
- import-finish? i/tick
- analyze-error? i/close)]
+ (if loading?
+ [:> loader* {:width "16px"
+ :height "24px"
+ :title (tr "labels.loading")}]
+ [:div {:class (stl/css-case :file-icon true
+ :icon-fill ready?)}
+ (cond ready? i/logo-icon
+ import-warn? i/msg-warning
+ import-error? i/close
+ import-finish? i/tick
+ analyze-error? i/close)])
+
(if editing?
[:div {:class (stl/css :file-name-edit)}
diff --git a/frontend/src/app/main/ui/dashboard/import.scss b/frontend/src/app/main/ui/dashboard/import.scss
index b32a1338d..50083f3df 100644
--- a/frontend/src/app/main/ui/dashboard/import.scss
+++ b/frontend/src/app/main/ui/dashboard/import.scss
@@ -143,13 +143,6 @@
&.loading {
.file-name {
color: var(--modal-text-foreground-color);
- .file-icon {
- :global(#loader-pencil) {
- color: var(--modal-text-foreground-color);
- stroke: var(--modal-text-foreground-color);
- fill: var(--modal-text-foreground-color);
- }
- }
}
}
&.warning {
diff --git a/frontend/src/app/main/ui/dashboard/placeholder.cljs b/frontend/src/app/main/ui/dashboard/placeholder.cljs
index 41cd3eac2..ee87f4f5d 100644
--- a/frontend/src/app/main/ui/dashboard/placeholder.cljs
+++ b/frontend/src/app/main/ui/dashboard/placeholder.cljs
@@ -7,6 +7,7 @@
(ns app.main.ui.dashboard.placeholder
(:require-macros [app.main.style :as stl])
(:require
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.icons :as i]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
@@ -40,6 +41,9 @@
(mf/defc loading-placeholder
[]
- [:div {:class (stl/css :grid-empty-placeholder :loader)}
- [:div {:class (stl/css :icon)} i/loader-pencil]
- [:div {:class (stl/css :text)} (tr "dashboard.loading-files")]])
+ [:> loader* {:width "64px"
+ :height "64px"
+ :title (tr "labels.loading")
+ :overlay true
+ :class (stl/css :placeholder-loader)}
+ [:div {:class (stl/css :placeholder-text)} (tr "dashboard.loading-files")]])
diff --git a/frontend/src/app/main/ui/dashboard/placeholder.scss b/frontend/src/app/main/ui/dashboard/placeholder.scss
index 6f05ba000..6aab79276 100644
--- a/frontend/src/app/main/ui/dashboard/placeholder.scss
+++ b/frontend/src/app/main/ui/dashboard/placeholder.scss
@@ -12,21 +12,6 @@
display: grid;
padding: $s-12 0;
- &.loader {
- justify-items: center;
- }
-
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- svg {
- width: $s-64;
- height: $s-64;
- fill: $df-secondary;
- }
- }
-
&.libs {
background-image: url(/images/ph-left.svg), url(/images/ph-right.svg);
background-position:
@@ -90,3 +75,23 @@
font-size: $fs-16;
}
}
+
+.loader-wrapper {
+ display: grid;
+ justify-items: center;
+ height: 100%;
+ width: 100%;
+ padding: $s-12 0;
+ border-radius: $br-12;
+}
+
+.placeholder-loader {
+ align-self: end;
+}
+
+.placeholder-text {
+ margin-top: $s-12;
+ color: $df-secondary;
+ font-size: $fs-16;
+ align-self: start;
+}
diff --git a/frontend/src/app/main/ui/ds/product/loader.cljs b/frontend/src/app/main/ui/ds/product/loader.cljs
index 8c6ad6ce9..316d9d6ba 100644
--- a/frontend/src/app/main/ui/ds/product/loader.cljs
+++ b/frontend/src/app/main/ui/ds/product/loader.cljs
@@ -11,23 +11,18 @@
(:require
[rumext.v2 :as mf]))
-(mf/defc loader*
- {::mf/props :obj}
+(mf/defc loader-icon*
+ {::mf/props :obj
+ ::mf/private true}
[{:keys [class width height title] :rest props}]
(let [class (dm/str (or class "") " " (stl/css :loader))
- both-provided (and width height)
- neither-provided (and (nil? width) (nil? height))
+
props (mf/spread-props props {:viewBox "0 0 677.34762 182.15429"
:role "status"
:width (or width "100px")
:height (or height "27px")
:class class})]
- (assert (or both-provided neither-provided)
- (dm/str "Invalid props: both 'width' and 'height' must be provided or neither. "
- "Received width: " width ", height: " height))
- ;; TODO: Add a translated label insted of the title prop.
- (assert title
- (dm/str "You must provide an accesible name for the component"))
+
[:> "svg" props
[:title title]
[:g
@@ -36,3 +31,26 @@
[:path {:class (stl/css :loader-line)
:d
"M134.482 157.147v25l518.57.008.002-25-518.572-.008z"}]]]))
+
+(mf/defc loader*
+ {::mf/props :obj}
+ [{:keys [class wrapperclass width height title overlay children] :rest props}]
+
+ (let [both-provided (and width height)
+ neither-provided (and (nil? width) (nil? height))
+ wrapperclass (dm/str (or wrapperclass "") " " (stl/css-case :loader-wrapper true
+ :loader-wrapper-overlay overlay))
+ props (mf/spread-props props {:class wrapperclass})]
+
+ (assert title
+ (dm/str "You must provide an accesible name for the component"))
+
+ (assert (or both-provided neither-provided)
+ (dm/str "Invalid props: both 'width' and 'height' must be provided or neither. "
+ "Received width: " width ", height: " height))
+ [:> "div" props
+ [:> loader-icon* {:title title
+ :width width
+ :class class
+ :height height}]
+ children]))
\ No newline at end of file
diff --git a/frontend/src/app/main/ui/ds/product/loader.scss b/frontend/src/app/main/ui/ds/product/loader.scss
index 67564586e..e54192dfb 100644
--- a/frontend/src/app/main/ui/ds/product/loader.scss
+++ b/frontend/src/app/main/ui/ds/product/loader.scss
@@ -14,12 +14,25 @@
}
}
-.loader {
+.loader-wrapper {
--color-loader-foreground: var(--color-foreground-secondary);
- fill: var(--color-loader-foreground);
+ color: var(--color-loader-foreground);
+ display: flex;
+ column-gap: var(--sp-s);
+}
+
+.loader-wrapper-overlay {
+ display: grid;
+ place-items: center;
+ height: 100%;
+ width: 100%;
+}
+
+.loader {
+ fill: currentColor;
}
.loader-line {
- fill: var(--color-loader-foreground);
+ fill: currentColor;
animation: line-pencil 0.8s infinite linear;
}
diff --git a/frontend/src/app/main/ui/ds/product/loader.stories.jsx b/frontend/src/app/main/ui/ds/product/loader.stories.jsx
index 5e6d0558d..d00a7199e 100644
--- a/frontend/src/app/main/ui/ds/product/loader.stories.jsx
+++ b/frontend/src/app/main/ui/ds/product/loader.stories.jsx
@@ -5,9 +5,30 @@ const { Loader } = Components;
export default {
title: "Product/Loader",
- component: Components.Loader,
+ component: Loader,
+ args: {
+ title: "Loading",
+ overlay: false,
+ },
+ parameters: {
+ controls: { exclude: ["theme", "style", "title", "overlay"] },
+ },
+ render: ({ children, ...args }) => {children},
};
-export const Default = {
- render: () => ,
+export const Default = {};
+
+export const Overlay = {
+ args: {
+ overlay: true,
+ style: { height: "100vh" },
+ },
+};
+
+export const Inline = {
+ args: {
+ children: "Loading...",
+ width: "16px",
+ height: "24px",
+ },
};
diff --git a/frontend/src/app/main/ui/export.cljs b/frontend/src/app/main/ui/export.cljs
index f1c0a004b..3d3f258d4 100644
--- a/frontend/src/app/main/ui/export.cljs
+++ b/frontend/src/app/main/ui/export.cljs
@@ -15,6 +15,7 @@
[app.main.data.modal :as modal]
[app.main.refs :as refs]
[app.main.store :as st]
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.shapes :refer [shape-wrapper]]
[app.main.worker :as uw]
@@ -317,10 +318,13 @@
:error (:export-error? file))}
[:div {:class (stl/css :file-name)}
- [:span {:class (stl/css :file-icon)}
- (cond (:export-success? file) i/tick
- (:export-error? file) i/close
- (:loading? file) i/loader-pencil)]
+ (if (:loading? file)
+ [:> loader* {:width "16px"
+ :height "24px"
+ :title (tr "labels.loading")}]
+ [:span {:class (stl/css :file-icon)}
+ (cond (:export-success? file) i/tick
+ (:export-error? file) i/close)])
[:div {:class (stl/css :file-name-label)}
(:name file)]]])
diff --git a/frontend/src/app/main/ui/export.scss b/frontend/src/app/main/ui/export.scss
index 479d714a3..d9873cd61 100644
--- a/frontend/src/app/main/ui/export.scss
+++ b/frontend/src/app/main/ui/export.scss
@@ -309,11 +309,6 @@
&.loading {
.file-name {
color: var(--modal-text-foreground-color);
- .file-icon svg:global(#loader-pencil) {
- color: var(--modal-text-foreground-color);
- stroke: var(--modal-text-foreground-color);
- fill: var(--modal-text-foreground-color);
- }
}
}
&.error {
diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs
index 9de4037cb..df8f1bf3a 100644
--- a/frontend/src/app/main/ui/icons.cljs
+++ b/frontend/src/app/main/ui/icons.cljs
@@ -9,8 +9,7 @@
(:require-macros [app.main.ui.icons :refer [icon-xref collect-icons]])
(:require
[app.common.data :as d]
- [cuerdas.core :as str]
- [rumext.v2 :as mf]))
+ [cuerdas.core :as str]))
;; Keep the list of icons sorted
(def ^:icon icon-verify (icon-xref :icon-verify))
@@ -263,23 +262,6 @@
(def ^:icon view-as-list (icon-xref :view-as-list))
(def ^:icon wrap (icon-xref :wrap))
-(def ^:icon loader-pencil
- (mf/html
- [:svg
- {:viewBox "0 0 677.34762 182.15429"
- :height "182"
- :width "667"
- :id "loader-pencil"}
- [:g
- [:path
- {:id "body-body"
- :d
- "M128.273 0l-3.9 2.77L0 91.078l128.273 91.076 549.075-.006V.008L128.273 0zm20.852 30l498.223.006V152.15l-498.223.007V30zm-25 9.74v102.678l-49.033-34.813-.578-32.64 49.61-35.225z"}]
- [:path
- {:id "loader-line"
- :d
- "M134.482 157.147v25l518.57.008.002-25-518.572-.008z"}]]]))
-
(def default
"A collection of all icons"
(collect-icons))
diff --git a/frontend/src/app/main/ui/loader.cljs b/frontend/src/app/main/ui/loader.cljs
deleted file mode 100644
index 43a790181..000000000
--- a/frontend/src/app/main/ui/loader.cljs
+++ /dev/null
@@ -1,20 +0,0 @@
-;; This Source Code Form is subject to the terms of the Mozilla Public
-;; License, v. 2.0. If a copy of the MPL was not distributed with this
-;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-;;
-;; Copyright (c) KALEIDOS INC
-
-(ns app.main.ui.loader
- (:require-macros [app.main.style :as stl])
- (:require
- [app.main.store :as st]
- [app.main.ui.icons :as i]
- [rumext.v2 :as mf]))
-
-;; --- Component
-
-(mf/defc loader
- []
- (when (mf/deref st/loader)
- [:div {:class (stl/css :loader-content)}
- i/loader-pencil]))
diff --git a/frontend/src/app/main/ui/loader.scss b/frontend/src/app/main/ui/loader.scss
deleted file mode 100644
index 71121f51d..000000000
--- a/frontend/src/app/main/ui/loader.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-// Copyright (c) KALEIDOS INC
-
-@import "refactor/common-refactor.scss";
-
-.loader-content {
- @extend .loader-base;
-}
diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs
index 6883a6d24..2fe373491 100644
--- a/frontend/src/app/main/ui/viewer.cljs
+++ b/frontend/src/app/main/ui/viewer.cljs
@@ -22,6 +22,7 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar]]
@@ -628,11 +629,10 @@
(st/emit! (dv/initialize params))
(fn []
(st/emit! (dv/finalize params)))))
-
(if-let [data (mf/deref refs/viewer-data)]
(let [props (obj/merge props #js {:data data :key (dm/str file-id)})]
[:> viewer-content props])
- [:div {:class (stl/css :loader-content)}
- i/loader-pencil]))
+ [:> loader* {:title (tr "labels.loading")
+ :overlay true}]))
diff --git a/frontend/src/app/main/ui/viewer.scss b/frontend/src/app/main/ui/viewer.scss
index 14dabe4c2..9deb4378d 100644
--- a/frontend/src/app/main/ui/viewer.scss
+++ b/frontend/src/app/main/ui/viewer.scss
@@ -189,10 +189,6 @@
}
}
-.loader-content {
- @extend .loader-base;
-}
-
/** FULLSCREEN */
[data-fullscreen="true"] .viewer-bottom {
transform: translateY($s-40);
diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs
index 6e22292f9..b902faf62 100644
--- a/frontend/src/app/main/ui/workspace.cljs
+++ b/frontend/src/app/main/ui/workspace.cljs
@@ -17,9 +17,9 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
+ [app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.hooks :as hooks]
[app.main.ui.hooks.resize :refer [use-resize-observer]]
- [app.main.ui.icons :as i]
[app.main.ui.workspace.colorpicker]
[app.main.ui.workspace.context-menu :refer [context-menu]]
[app.main.ui.workspace.coordinates :as coordinates]
@@ -124,8 +124,8 @@
(mf/defc workspace-loader
[]
- [:div {:class (stl/css :workspace-loader)}
- i/loader-pencil])
+ [:> loader* {:title (tr "labels.loading")
+ :overlay true}])
(mf/defc workspace-page
{::mf/wrap-props false}
@@ -147,7 +147,6 @@
(fn []
(when (some? page-id)
(st/emit! (dw/finalize-page page-id)))))
-
(if ^boolean page-ready?
[:& workspace-content {:page-id page-id
:file file
diff --git a/frontend/src/app/main/ui/workspace.scss b/frontend/src/app/main/ui/workspace.scss
index 53ab9e778..ed25a0c0b 100644
--- a/frontend/src/app/main/ui/workspace.scss
+++ b/frontend/src/app/main/ui/workspace.scss
@@ -18,15 +18,12 @@
grid-template-rows: 1fr;
grid-template-columns: auto 1fr auto;
overflow: hidden;
+}
- .workspace-loader {
- @include flexCenter;
- grid-area: viewport;
- background-color: var(--loader-background);
- :global(svg#loader-pencil) {
- fill: var(--icon-foreground);
- }
- }
+.workspace-loader {
+ @include flexCenter;
+ grid-area: viewport;
+ background-color: var(--loader-background);
}
.workspace-content {
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index ad9d8328f..43158cec6 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -1713,6 +1713,9 @@ msgstr "Upload custom fonts"
msgid "labels.uploading"
msgstr "Uploading…"
+msgid "labels.loading"
+msgstr "Loading…"
+
msgid "labels.view-only"
msgstr "View only"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 05f208ae0..6a590077c 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -1770,6 +1770,9 @@ msgstr "Cargar fuente"
msgid "labels.uploading"
msgstr "Subiendo…"
+msgid "labels.loading"
+msgstr "Cargando…"
+
msgid "labels.view-only"
msgstr "Solo lectura"