mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 03:21:26 -05:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
78c2840b22
11 changed files with 556 additions and 56 deletions
|
@ -55,7 +55,9 @@
|
|||
- Fix problem with constraints when creating group [Taiga #10455](https://tree.taiga.io/project/penpot/issue/10455)
|
||||
- Fix opening pen with shortcut multiple times breaks toolbar [Taiga #10566](https://tree.taiga.io/project/penpot/issue/10566)
|
||||
- Fix actions when workspace is visited first time [Taiga #10548](https://tree.taiga.io/project/penpot/issue/10548)
|
||||
- Chat icon overlaps "Show" button in carrousel section [Taiga #10542](https://tree.taiga.io/project/penpot/issue/10542)
|
||||
- Fix chat icon overlaps "Show" button in carrousel section [Taiga #10542](https://tree.taiga.io/project/penpot/issue/10542)
|
||||
- Fix incorrect handling of background task result (now task rows are properly marked as completed)
|
||||
|
||||
|
||||
## 2.5.4
|
||||
|
||||
|
|
|
@ -24,6 +24,33 @@
|
|||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(def schema:task
|
||||
[:map {:title "Task"}
|
||||
[:id ::sm/uuid]
|
||||
[:queue :string]
|
||||
[:name :string]
|
||||
[:created-at ::sm/inst]
|
||||
[:modified-at ::sm/inst]
|
||||
[:scheduled-at {:optional true} ::sm/inst]
|
||||
[:completed-at {:optional true} ::sm/inst]
|
||||
[:error {:optional true} :string]
|
||||
[:max-retries :int]
|
||||
[:retry-num :int]
|
||||
[:priority :int]
|
||||
[:status [:enum "scheduled" "completed" "new" "retry" "failed"]]
|
||||
[:label {:optional true} :string]
|
||||
[:props :map]])
|
||||
|
||||
(def schema:result
|
||||
[:map {:title "TaskResult"}
|
||||
[:status [:enum "retry" "failed" "completed"]]
|
||||
[:error {:optional true} [:fn ex/exception?]]
|
||||
[:inc-by {:optional true} :int]
|
||||
[:delay {:optional true} :int]])
|
||||
|
||||
(def valid-task-result?
|
||||
(sm/validator schema:result))
|
||||
|
||||
(defn- decode-task-row
|
||||
[{:keys [props] :as row}]
|
||||
(cond-> row
|
||||
|
@ -51,10 +78,11 @@
|
|||
:retry (:retry-num task))
|
||||
(let [tpoint (dt/tpoint)
|
||||
task-fn (wrk/get-task registry (:name task))
|
||||
result (if task-fn
|
||||
(task-fn task)
|
||||
{:status :completed :task task})
|
||||
elapsed (dt/format-duration (tpoint))]
|
||||
result (when task-fn (task-fn task))
|
||||
elapsed (dt/format-duration (tpoint))
|
||||
result (if (valid-task-result? result)
|
||||
result
|
||||
{:status "completed"})]
|
||||
|
||||
(when-not task-fn
|
||||
(l/wrn :hint "no task handler found" :name (:name task)))
|
||||
|
@ -76,7 +104,7 @@
|
|||
(if (and (< (:retry-num task)
|
||||
(:max-retries task))
|
||||
(= ::retry (:type edata)))
|
||||
(cond-> {:status :retry :task task :error cause}
|
||||
(cond-> {:status "retry" :error cause}
|
||||
(dt/duration? (:delay edata))
|
||||
(assoc :delay (:delay edata))
|
||||
|
||||
|
@ -87,8 +115,8 @@
|
|||
::l/context (get-error-context cause task)
|
||||
:cause cause)
|
||||
(if (>= (:retry-num task) (:max-retries task))
|
||||
{:status :failed :task task :error cause}
|
||||
{:status :retry :task task :error cause})))))))
|
||||
{:status "failed" :error cause}
|
||||
{:status "retry" :error cause})))))))
|
||||
|
||||
(defn- run-task!
|
||||
[{:keys [::id ::timeout] :as cfg} task-id]
|
||||
|
@ -116,12 +144,17 @@
|
|||
:task-id task-id)
|
||||
|
||||
:else
|
||||
(run-task cfg task))))
|
||||
(let [result (run-task cfg task)]
|
||||
(with-meta result
|
||||
{::task task})))))
|
||||
|
||||
(defn- run-worker-loop!
|
||||
[{:keys [::db/pool ::rds/rconn ::timeout ::queue] :as cfg}]
|
||||
(letfn [(handle-task-retry [{:keys [task error inc-by delay] :or {inc-by 1 delay 1000}}]
|
||||
(let [explain (ex-message error)
|
||||
(letfn [(handle-task-retry [{:keys [error inc-by delay] :or {inc-by 1 delay 1000} :as result}]
|
||||
(let [explain (if (ex/exception? error)
|
||||
(ex-message error)
|
||||
(str error))
|
||||
task (-> result meta ::task)
|
||||
nretry (+ (:retry-num task) inc-by)
|
||||
now (dt/now)
|
||||
delay (->> (iterate #(* % 2) delay) (take nretry) (last))]
|
||||
|
@ -134,8 +167,9 @@
|
|||
{:id (:id task)})
|
||||
nil))
|
||||
|
||||
(handle-task-failure [{:keys [task error]}]
|
||||
(let [explain (ex-message error)]
|
||||
(handle-task-failure [{:keys [error] :as result}]
|
||||
(let [task (-> result meta ::task)
|
||||
explain (ex-message error)]
|
||||
(db/update! pool :task
|
||||
{:error explain
|
||||
:modified-at (dt/now)
|
||||
|
@ -143,8 +177,9 @@
|
|||
{:id (:id task)})
|
||||
nil))
|
||||
|
||||
(handle-task-completion [{:keys [task]}]
|
||||
(let [now (dt/now)]
|
||||
(handle-task-completion [result]
|
||||
(let [task (-> result meta ::task)
|
||||
now (dt/now)]
|
||||
(db/update! pool :task
|
||||
{:completed-at now
|
||||
:modified-at now
|
||||
|
@ -168,10 +203,11 @@
|
|||
(process-result [{:keys [status] :as result}]
|
||||
(ex/try!
|
||||
(case status
|
||||
:retry (handle-task-retry result)
|
||||
:failed (handle-task-failure result)
|
||||
:completed (handle-task-completion result)
|
||||
nil)))
|
||||
"retry" (handle-task-retry result)
|
||||
"failed" (handle-task-failure result)
|
||||
"completed" (handle-task-completion result)
|
||||
(throw (IllegalArgumentException.
|
||||
(str "invalid status received: " status))))))
|
||||
|
||||
(run-task-loop [task-id]
|
||||
(loop [result (run-task! cfg task-id)]
|
||||
|
|
|
@ -1227,18 +1227,15 @@ Will return a value that matches this schema:
|
|||
:none)))
|
||||
|
||||
(get-active-themes-set-tokens [this]
|
||||
(let [sets-order (get-ordered-set-names this)
|
||||
active-themes (get-active-themes this)
|
||||
order-theme-set (fn [theme]
|
||||
(filter #(contains? (set (:sets theme)) %) sets-order))]
|
||||
(reduce
|
||||
(fn [tokens theme]
|
||||
(reduce
|
||||
(fn [tokens' cur]
|
||||
(merge tokens' (:tokens (get-set this cur))))
|
||||
tokens (order-theme-set theme)))
|
||||
(d/ordered-map)
|
||||
active-themes)))
|
||||
(let [theme-set-names (get-active-themes-set-names this)
|
||||
all-set-names (get-ordered-set-names this)
|
||||
active-set-names (filter theme-set-names all-set-names)
|
||||
tokens (reduce (fn [tokens set-name]
|
||||
(let [set (get-set this set-name)]
|
||||
(merge tokens (:tokens set))))
|
||||
(d/ordered-map)
|
||||
active-set-names)]
|
||||
tokens))
|
||||
|
||||
(encode-dtcg [this]
|
||||
(let [themes-xform
|
||||
|
|
|
@ -441,32 +441,225 @@
|
|||
(t/is (nil? token'))
|
||||
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-in-order
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-theme (ctob/make-token-theme :name "out-of-order-theme"
|
||||
;; Out of order sets in theme
|
||||
:sets ["unknown-set" "set-b" "set-a"]))
|
||||
(ctob/set-active-themes #{"/out-of-order-theme"})
|
||||
(t/deftest get-ordered-sets
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "group-1/set-a"))
|
||||
(ctob/add-set (ctob/make-token-set :name "group-1/set-b"))
|
||||
(ctob/add-set (ctob/make-token-set :name "group-2/set-a"))
|
||||
(ctob/add-set (ctob/make-token-set :name "group-1/set-c")))
|
||||
|
||||
(ctob/add-set (ctob/make-token-set :name "set-a"))
|
||||
(ctob/add-token-in-set "set-a" (ctob/make-token :name "set-a-token"
|
||||
:type :boolean
|
||||
:value true))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-b"))
|
||||
(ctob/add-token-in-set "set-b" (ctob/make-token :name "set-b-token"
|
||||
:type :boolean
|
||||
:value true))
|
||||
;; Ignore this set
|
||||
(ctob/add-set (ctob/make-token-set :name "inactive-set"))
|
||||
(ctob/add-token-in-set "inactive-set" (ctob/make-token :name "inactive-set-token"
|
||||
:type :boolean
|
||||
:value true)))
|
||||
ordered-sets (ctob/get-ordered-set-names tokens-lib)]
|
||||
|
||||
expected-order (ctob/get-ordered-set-names tokens-lib)
|
||||
expected-tokens (ctob/get-active-themes-set-tokens tokens-lib)
|
||||
expected-token-names (mapv key expected-tokens)]
|
||||
(t/is (= '("set-a" "set-b" "inactive-set") expected-order))
|
||||
(t/is (= ["set-a-token" "set-b-token"] expected-token-names))))
|
||||
(t/is (= ordered-sets '("group-1/set-a"
|
||||
"group-1/set-b"
|
||||
"group-1/set-c"
|
||||
"group-2/set-a")))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-no-theme
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "set-a"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 10)
|
||||
"token-2"
|
||||
(ctob/make-token :name "token-2"
|
||||
:type :border-radius
|
||||
:value 20)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-b"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 100)
|
||||
"token-3"
|
||||
(ctob/make-token :name "token-3"
|
||||
:type :border-radius
|
||||
:value 300)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-c"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 1000)
|
||||
"token-2"
|
||||
(ctob/make-token :name "token-2"
|
||||
:type :border-radius
|
||||
:value 2000)
|
||||
"token-3"
|
||||
(ctob/make-token :name "token-3"
|
||||
:type :border-radius
|
||||
:value 3000)
|
||||
"token-4"
|
||||
(ctob/make-token :name "token-4"
|
||||
:type :border-radius
|
||||
:value 4000)}))
|
||||
(ctob/update-theme ctob/hidden-token-theme-group ctob/hidden-token-theme-name
|
||||
#(ctob/enable-sets % #{"set-a" "set-b"})))
|
||||
|
||||
tokens (ctob/get-active-themes-set-tokens tokens-lib)]
|
||||
|
||||
(t/is (= (mapv key tokens) ["token-1" "token-2" "token-3"]))
|
||||
(t/is (= (get-in tokens ["token-1" :value]) 100))
|
||||
(t/is (= (get-in tokens ["token-2" :value]) 20))
|
||||
(t/is (= (get-in tokens ["token-3" :value]) 300))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-one-theme
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "set-a"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 10)
|
||||
"token-2"
|
||||
(ctob/make-token :name "token-2"
|
||||
:type :border-radius
|
||||
:value 20)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-b"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 100)
|
||||
"token-3"
|
||||
(ctob/make-token :name "token-3"
|
||||
:type :border-radius
|
||||
:value 300)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-c"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 1000)
|
||||
"token-2"
|
||||
(ctob/make-token :name "token-2"
|
||||
:type :border-radius
|
||||
:value 2000)
|
||||
"token-3"
|
||||
(ctob/make-token :name "token-3"
|
||||
:type :border-radius
|
||||
:value 3000)
|
||||
"token-4"
|
||||
(ctob/make-token :name "token-4"
|
||||
:type :border-radius
|
||||
:value 4000)}))
|
||||
(ctob/add-theme (ctob/make-token-theme :name "single-theme"
|
||||
:sets #{"set-b" "set-c" "set-a"}))
|
||||
(ctob/set-active-themes #{"/single-theme"}))
|
||||
|
||||
tokens (ctob/get-active-themes-set-tokens tokens-lib)]
|
||||
|
||||
;; Note that sets order inside the theme is undefined. What matters is order in that the
|
||||
;; sets have been added to the library.
|
||||
(t/is (= (mapv key tokens) ["token-1" "token-2" "token-3" "token-4"]))
|
||||
(t/is (= (get-in tokens ["token-1" :value]) 1000))
|
||||
(t/is (= (get-in tokens ["token-2" :value]) 2000))
|
||||
(t/is (= (get-in tokens ["token-3" :value]) 3000))
|
||||
(t/is (= (get-in tokens ["token-4" :value]) 4000))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-two-themes
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "set-a"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 10)
|
||||
"token-2"
|
||||
(ctob/make-token :name "token-2"
|
||||
:type :border-radius
|
||||
:value 20)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-b"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 100)
|
||||
"token-3"
|
||||
(ctob/make-token :name "token-3"
|
||||
:type :border-radius
|
||||
:value 300)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-c"
|
||||
:tokens {"token-1"
|
||||
(ctob/make-token :name "token-1"
|
||||
:type :border-radius
|
||||
:value 1000)
|
||||
"token-2"
|
||||
(ctob/make-token :name "token-2"
|
||||
:type :border-radius
|
||||
:value 2000)
|
||||
"token-3"
|
||||
(ctob/make-token :name "token-3"
|
||||
:type :border-radius
|
||||
:value 3000)
|
||||
"token-4"
|
||||
(ctob/make-token :name "token-4"
|
||||
:type :border-radius
|
||||
:value 4000)}))
|
||||
(ctob/add-theme (ctob/make-token-theme :name "theme-1"
|
||||
:sets #{"set-b"}))
|
||||
(ctob/add-theme (ctob/make-token-theme :name "theme-2"
|
||||
:sets #{"set-b" "set-a"}))
|
||||
(ctob/set-active-themes #{"/theme-1" "/theme-2"}))
|
||||
|
||||
tokens (ctob/get-active-themes-set-tokens tokens-lib)]
|
||||
|
||||
;; Note that themes order is irrelevant. What matters is the union of the active sets
|
||||
;; and the order of the sets in the library.
|
||||
(t/is (= (mapv key tokens) ["token-1" "token-2" "token-3"]))
|
||||
(t/is (= (get-in tokens ["token-1" :value]) 100))
|
||||
(t/is (= (get-in tokens ["token-2" :value]) 20))
|
||||
(t/is (= (get-in tokens ["token-3" :value]) 300))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-bug-taiga-10617
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "Mode / Dark"
|
||||
:tokens {"red"
|
||||
(ctob/make-token :name "red"
|
||||
:type :color
|
||||
:value "#700000")}))
|
||||
(ctob/add-set (ctob/make-token-set :name "Mode / Light"
|
||||
:tokens {"red"
|
||||
(ctob/make-token :name "red"
|
||||
:type :color
|
||||
:value "#ff0000")}))
|
||||
(ctob/add-set (ctob/make-token-set :name "Device / Desktop"
|
||||
:tokens {"border1"
|
||||
(ctob/make-token :name "border1"
|
||||
:type :border-radius
|
||||
:value 30)}))
|
||||
(ctob/add-set (ctob/make-token-set :name "Device / Mobile"
|
||||
:tokens {"border1"
|
||||
(ctob/make-token :name "border1"
|
||||
:type :border-radius
|
||||
:value 50)}))
|
||||
(ctob/add-theme (ctob/make-token-theme :group "App"
|
||||
:name "Mobile"
|
||||
:sets #{"Mode / Dark" "Device / Mobile"}))
|
||||
(ctob/add-theme (ctob/make-token-theme :group "App"
|
||||
:name "Web"
|
||||
:sets #{"Mode / Dark" "Mode / Light" "Device / Desktop"}))
|
||||
(ctob/add-theme (ctob/make-token-theme :group "Brand"
|
||||
:name "Brand A"
|
||||
:sets #{"Mode / Dark" "Mode / Light" "Device / Desktop" "Device / Mobile"}))
|
||||
(ctob/add-theme (ctob/make-token-theme :group "Brand"
|
||||
:name "Brand B"
|
||||
:sets #{}))
|
||||
(ctob/set-active-themes #{"App/Web" "Brand/Brand A"}))
|
||||
|
||||
tokens (ctob/get-active-themes-set-tokens tokens-lib)]
|
||||
|
||||
(t/is (= (mapv key tokens) ["red" "border1"]))
|
||||
(t/is (= (get-in tokens ["red" :value]) "#ff0000"))
|
||||
(t/is (= (get-in tokens ["border1" :value]) 50))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-no-tokens
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "set-a")))
|
||||
|
||||
tokens (ctob/get-active-themes-set-tokens tokens-lib)]
|
||||
|
||||
(t/is (empty? tokens))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-no-sets
|
||||
(let [tokens-lib (ctob/make-tokens-lib)
|
||||
tokens (ctob/get-active-themes-set-tokens tokens-lib)]
|
||||
|
||||
(t/is (empty? tokens))))
|
||||
|
||||
(t/deftest sets-at-path-active-state
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
|
|
BIN
frontend/resources/images/features/2.6-bubbles.gif
Normal file
BIN
frontend/resources/images/features/2.6-bubbles.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 589 KiB |
BIN
frontend/resources/images/features/2.6-slide-0.png
Normal file
BIN
frontend/resources/images/features/2.6-slide-0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 137 KiB |
BIN
frontend/resources/images/features/2.6-tokens-1.gif
Normal file
BIN
frontend/resources/images/features/2.6-tokens-1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 451 KiB |
BIN
frontend/resources/images/features/2.6-tokens-2.gif
Normal file
BIN
frontend/resources/images/features/2.6-tokens-2.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -32,6 +32,7 @@
|
|||
[app.main.ui.releases.v2-3]
|
||||
[app.main.ui.releases.v2-4]
|
||||
[app.main.ui.releases.v2-5]
|
||||
[app.main.ui.releases.v2-6]
|
||||
[app.util.object :as obj]
|
||||
[app.util.timers :as tm]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -96,4 +97,4 @@
|
|||
|
||||
(defmethod rc/render-release-notes "0.0"
|
||||
[params]
|
||||
(rc/render-release-notes (assoc params :version "2.5")))
|
||||
(rc/render-release-notes (assoc params :version "2.6")))
|
||||
|
|
169
frontend/src/app/main/ui/releases/v2_6.cljs
Normal file
169
frontend/src/app/main/ui/releases/v2_6.cljs
Normal file
|
@ -0,0 +1,169 @@
|
|||
;; 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.releases.v2-6
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.releases.common :as c]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defmethod c/render-release-notes "2.6"
|
||||
[{:keys [slide klass next finish navigate version]}]
|
||||
(mf/html
|
||||
(case slide
|
||||
:start
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.6-slide-0.png"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Design Tokens make their debut in Penpot!"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"What’s new in Penpot?"]
|
||||
|
||||
[:div {:class (stl/css :version-tag)}
|
||||
(dm/str "Version " version)]]
|
||||
|
||||
[:div {:class (stl/css :features-block)}
|
||||
[:span {:class (stl/css :feature-title)}
|
||||
"Design Tokens make their debut in Penpot!"]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Penpot is the first design tool to integrate native design
|
||||
tokens—a single source of truth to improve efficiency and
|
||||
collaboration between product design and development."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"But that’s not all—we’ve also tackled improvements, bug fixes and optimizations."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Let’s dive in!"]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:button {:class (stl/css :next-btn)
|
||||
:on-click next} "Continue"]]]]]]
|
||||
|
||||
0
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.6-tokens-1.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Manage brands and themes across your design systems"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"Manage brands and themes across your design systems"]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Create and manage different token types—Color, Opacity,
|
||||
Border Radius, Dimension, Sizing, Spacing, Rotation, and
|
||||
Stroke. And this is just the beginning—more token types are
|
||||
on the way!"]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Add values to your tokens, including references to other
|
||||
tokens (aliases) and even math operations to keep things
|
||||
dynamic and flexible."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Use Themes and Sets for an efficient way to manage your
|
||||
design system across multiple dimensions—whether it’s
|
||||
brand, color schemes, devices, density, or anything else
|
||||
your product needs."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click next
|
||||
:class (stl/css :next-btn)} "Continue"]]]]]]
|
||||
|
||||
1
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.6-tokens-2.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Open Source design tokens format"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"Open Source design tokens format"]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Penpot adopts the W3C Design Tokens Community Group (DTCG)
|
||||
standard, ensuring maximum compatibility with a wide range
|
||||
of tools and technologies."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"With Penpot’s standardized design tokens format, you can
|
||||
easily reuse and sync tokens across different platforms,
|
||||
workflows, and disciplines. Import your existing tokens
|
||||
into Penpot—or export them for use anywhere else. Seamless
|
||||
interoperability by design through Open Source."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click next
|
||||
:class (stl/css :next-btn)} "Continue"]]]]]]
|
||||
|
||||
2
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.6-bubbles.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Comments grouped by zoom level"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"Comments grouped by zoom level"]]
|
||||
[:div {:class (stl/css :feature)}
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"When collaborating on files, feedback can quickly become
|
||||
dense and overwhelming, turning what should be information
|
||||
into visual noise. Now, comments are grouped based on your
|
||||
zoom level, giving the right level of visibility and making
|
||||
navigating feedback easier."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"When you’re zoomed out, comments are grouped to reduce
|
||||
clutter and keep your workspace clean. As you zoom in, the
|
||||
groups expand, revealing individual comments in
|
||||
context. This makes navigating feedback much smoother,
|
||||
especially in complex designs with lots of discussion."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click finish
|
||||
:class (stl/css :next-btn)} "Let's go"]]]]]])))
|
||||
|
102
frontend/src/app/main/ui/releases/v2_6.scss
Normal file
102
frontend/src/app/main/ui/releases/v2_6.scss
Normal file
|
@ -0,0 +1,102 @@
|
|||
// 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";
|
||||
|
||||
.modal-overlay {
|
||||
@extend .modal-overlay-base;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
display: grid;
|
||||
grid-template-columns: $s-324 1fr;
|
||||
height: $s-500;
|
||||
width: $s-888;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--modal-background-color);
|
||||
border: $s-2 solid var(--modal-border-color);
|
||||
}
|
||||
|
||||
.start-image {
|
||||
width: $s-324;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: $s-40;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr $s-32;
|
||||
gap: $s-24;
|
||||
|
||||
a {
|
||||
color: var(--button-primary-background-color-rest);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: grid;
|
||||
gap: $s-8;
|
||||
}
|
||||
|
||||
.version-tag {
|
||||
@include flexCenter;
|
||||
@include headlineSmallTypography;
|
||||
height: $s-32;
|
||||
width: $s-96;
|
||||
background-color: var(--communication-tag-background-color);
|
||||
color: var(--communication-tag-foreground-color);
|
||||
border-radius: $br-8;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
@include headlineLargeTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.features-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-16;
|
||||
width: $s-440;
|
||||
}
|
||||
|
||||
.feature {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-8;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
@include bodyLargeTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.feature-content {
|
||||
@include bodyMediumTypography;
|
||||
margin: 0;
|
||||
color: var(--modal-text-foreground-color);
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
@include bodyMediumTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
list-style: disc;
|
||||
display: grid;
|
||||
gap: $s-8;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-areas: "bullets button";
|
||||
}
|
||||
|
||||
.next-btn {
|
||||
@extend .button-primary;
|
||||
width: $s-100;
|
||||
justify-self: flex-end;
|
||||
grid-area: button;
|
||||
}
|
Loading…
Add table
Reference in a new issue