diff --git a/CHANGES.md b/CHANGES.md index 64671a27ec..001577184c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,8 @@ ### :rocket: Epics and highlights +- Design Tokens + ### :boom: Breaking changes & Deprecations ### :heart: Community contributions (Thank you!) @@ -26,6 +28,15 @@ - [COMMENTS] "Mark All as Read" Functionality in Dashboard [Taiga #9235](https://tree.taiga.io/project/penpot/us/9235) - [COMMENTS] Bubble Groups [Taiga #9236](https://tree.taiga.io/project/penpot/us/9236) - Change templates carrousel [Taiga #9803](https://tree.taiga.io/project/penpot/us/9803) +- [DESIGN TOKENS] Tokens CRUD. Types added: Color, Opacity, Border radius, Dimension, Sizing, Spacing, Rotation and Stroke. +- [DESIGN TOKENS] Create references (alias) that point to other tokens. +- [DESIGN TOKENS] Math operations in token values. +- [DESIGN TOKENS] Sets CRUD, grouping and reordering. +- [DESIGN TOKENS] Multidimensional Themes and Sets management. +- [DESIGN TOKENS] Apply/Remove tokens to/from elements from the Tokens tab. +- [DESIGN TOKENS] Integration with components. +- [DESIGN TOKENS] Import and export tokens from a JSON file. +- [DESIGN TOKENS] Apply Themes and Sets at document level. ### :bug: Bugs fixed @@ -39,10 +50,11 @@ - Fix hovering over templates [Taiga #10545](https://tree.taiga.io/project/penpot/issue/10545) - Fix problem with default shadows value in plugins [Plugins #191](https://github.com/penpot/penpot-plugins/issues/191) - 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) ## 2.5.4 -### :sparkles: New features +### :heart: Community contributions (Thank you!) - Add support for WEBP format on shape export [Github #6053](https://github.com/penpot/penpot/pull/6053) and [Github #6074](https://github.com/penpot/penpot/pull/6074) diff --git a/frontend/src/app/main/data/workspace/path/drawing.cljs b/frontend/src/app/main/data/workspace/path/drawing.cljs index 631c28d323..be1bbfd2ff 100644 --- a/frontend/src/app/main/data/workspace/path/drawing.cljs +++ b/frontend/src/app/main/data/workspace/path/drawing.cljs @@ -324,7 +324,9 @@ (let [id (dm/get-in state [:workspace-local :edition]) objects (dsh/lookup-page-objects state) content (dm/get-in objects [id :content])] - (update-in state [:workspace-local :edit-path id] assoc :old-content content))) + (if content + (update-in state [:workspace-local :edit-path id] assoc :old-content content) + state))) ptk/WatchEvent (watch [_ state stream] diff --git a/frontend/src/app/main/ui/workspace/tokens/errors.cljs b/frontend/src/app/main/ui/workspace/tokens/errors.cljs index 5fd580a693..1d9213c4dc 100644 --- a/frontend/src/app/main/ui/workspace/tokens/errors.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/errors.cljs @@ -44,6 +44,10 @@ {:error/code :error.style-dictionary/invalid-token-value-opacity :error/fn #(str/join "\n" [(str (tr "workspace.token.invalid-value" %) ".") (tr "workspace.token.opacity-range")])} + :error.style-dictionary/invalid-token-value-stroke-width + {:error/code :error.style-dictionary/invalid-token-value-stroke-width + :error/fn #(str/join "\n" [(str (tr "workspace.token.invalid-value" %) ".") (tr "workspace.token.stroke-width-range")])} + :error/unknown {:error/code :error/unknown :error/fn #(tr "labels.unknown-error")}}) diff --git a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs index 2fc6de6168..029791d9db 100644 --- a/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/style_dictionary.cljs @@ -87,8 +87,34 @@ (and (not has-references?) out-of-scope) {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-opacity value)]} - (and has-references? out-of-scope) - (assoc parsed-value :warnings [(wtw/warning-with-value :warning.style-dictionary/invalid-referenced-token-value value)]) + (and has-references? out-of-scope parsed-value) + (assoc parsed-value :warnings [(wtw/warning-with-value :warning.style-dictionary/invalid-referenced-token-value-opacity value)]) + + :else {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]}))) + + +(defn- parse-sd-token-stroke-width-value + "Parses `value` of a dimensions `sd-token` into a map like `{:value 1 :unit \"px\"}`. + If the `value` is not parseable and/or has missing references returns a map with `:errors`. + If the `value` is parseable but is out of range returns a map with `warnings`." + [value has-references?] + + (let [parsed-value (wtt/parse-token-value value) + out-of-scope (< (:value parsed-value) 0) + references (seq (ctob/find-token-value-references value))] + (cond + (and parsed-value (not out-of-scope)) + parsed-value + + references + {:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)] + :references references} + + (and (not has-references?) out-of-scope) + {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-stroke-width value)]} + + (and has-references? out-of-scope parsed-value) + (assoc parsed-value :warnings [(wtw/warning-with-value :warning.style-dictionary/invalid-referenced-token-value-stroke-width value)]) :else {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]}))) @@ -132,6 +158,7 @@ parsed-token-value (case (:type origin-token) :color (parse-sd-token-color-value value) :opacity (parse-sd-token-opacity-value value has-references?) + :stroke-width (parse-sd-token-stroke-width-value value has-references?) (parse-sd-token-numeric-value value)) output-token (cond (:errors parsed-token-value) (merge origin-token parsed-token-value) diff --git a/frontend/src/app/main/ui/workspace/tokens/warnings.cljs b/frontend/src/app/main/ui/workspace/tokens/warnings.cljs index 7b84e4a214..b175d164aa 100644 --- a/frontend/src/app/main/ui/workspace/tokens/warnings.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/warnings.cljs @@ -1,11 +1,16 @@ (ns app.main.ui.workspace.tokens.warnings (:require + [app.util.i18n :refer [tr]] [cuerdas.core :as str])) (def warning-codes - {:warning.style-dictionary/invalid-referenced-token-value - {:warning/code :warning.style-dictionary/invalid-referenced-token-value - :warning/fn (fn [value] (str/join "\n" [(str "Resolved value " value ".") "Opacity must be between 0 and 100% or 0 and 1 (e.g. 50% or 0.5)"]))} + {:warning.style-dictionary/invalid-referenced-token-value-opacity + {:warning/code :warning.style-dictionary/invalid-referenced-token-value-opacity + :warning/fn (fn [value] (str/join "\n" [(str (tr "workspace.token.resolved-value" value) ".") (tr "workspace.token.opacity-range")]))} + + :warning.style-dictionary/invalid-referenced-token-value-stroke-width + {:warning/code :warning.style-dictionary/invalid-referenced-token-value-stroke-width + :warning/fn (fn [value] (str/join "\n" [(str (tr "workspace.token.resolved-value" value) ".") (tr "workspace.token.stroke-width-range")]))} :warning/unknown {:warning/code :warning/unknown diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 49345de1f2..5cab85d650 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -6737,6 +6737,14 @@ msgstr "Import Error: Invalid token data in JSON." msgid "workspace.token.invalid-value" msgstr "Invalid token value: %s" +#: src/app/main/ui/workspace/tokens/errors.cljs +msgid "workspace.token.opacity-range" +msgstr "Opacity must be between 0 and 100% or 0 and 1 (e.g. 50% or 0.5)." + +#: src/app/main/ui/workspace/tokens/errors.cljs +msgid "workspace.token.stroke-width-range" +msgstr "Stroke width must be between equal or bigger than 0." + #: src/app/main/ui/workspace/tokens/modals/themes.cljs:196 msgid "workspace.token.label.group" msgstr "Group" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 8edb844e6d..852e9ee707 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -6754,6 +6754,14 @@ msgstr "Error al importar: Datos de token no válidos en JSON." msgid "workspace.token.invalid-value" msgstr "Valor de token no válido: %s" +#: src/app/main/ui/workspace/tokens/errors.cljs +msgid "workspace.token.opacity-range" +msgstr "La opacidad debe estar entre 0 y 100% o 0 y 1 (p.e. 50% o 0.5)." + +#: src/app/main/ui/workspace/tokens/errors.cljs +msgid "workspace.token.stroke-width-range" +msgstr "Stroke width debe ser mayor o igual a 0." + #: src/app/main/ui/workspace/tokens/modals/themes.cljs:196 msgid "workspace.token.label.group" msgstr "Grupo"