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"