0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

♻️ Review create and edit modal

This commit is contained in:
Eva Marco 2024-10-21 17:14:17 +02:00
parent 31b5f5cefa
commit 03ea5414be
12 changed files with 310 additions and 147 deletions

View file

@ -279,7 +279,6 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [data (get state :workspace-data) (let [data (get state :workspace-data)
_ (prn "paso por aquí")
changes (-> (pcb/empty-changes it) changes (-> (pcb/empty-changes it)
(pcb/with-library-data data) (pcb/with-library-data data)
(pcb/delete-token set-name token-name))] (pcb/delete-token set-name token-name))]

View file

@ -130,3 +130,21 @@
box-shadow: inset 0 0 #{px2rem(10)} #{px2rem(2)} rgba(0, 0, 0, 0.2); box-shadow: inset 0 0 #{px2rem(10)} #{px2rem(2)} rgba(0, 0, 0, 0.2);
} }
} }
%base-button-action {
--button-bg-color: transparent;
--button-fg-color: var(--color-foreground-secondary);
--button-hover-bg-color: transparent;
--button-hover-fg-color: var(--color-accent-primary);
--button-active-bg-color: var(--color-background-quaternary);
--button-disabled-bg-color: transparent;
--button-disabled-fg-color: var(--color-accent-primary-muted);
--button-focus-bg-color: transparent;
--button-focus-fg-color: var(--color-accent-primary);
--button-focus-inner-ring-color: transparent;
--button-focus-outer-ring-color: var(--color-accent-primary);
}

View file

@ -12,9 +12,6 @@
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]] [app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list]]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(def button-variants (set '("primary" "secondary" "ghost" "destructive")))
(def ^:private schema:icon-button (def ^:private schema:icon-button
[:map [:map
[:class {:optional true} :string] [:class {:optional true} :string]
@ -22,7 +19,7 @@
[:and :string [:fn #(contains? icon-list %)]]] [:and :string [:fn #(contains? icon-list %)]]]
[:aria-label :string] [:aria-label :string]
[:variant {:optional true} [:variant {:optional true}
[:maybe [:enum "primary" "secondary" "ghost" "destructive"]]]]) [:maybe [:enum "primary" "secondary" "ghost" "destructive" "action"]]]])
(mf/defc icon-button* (mf/defc icon-button*
{::mf/props :obj {::mf/props :obj
@ -33,6 +30,7 @@
:icon-button-primary (= variant "primary") :icon-button-primary (= variant "primary")
:icon-button-secondary (= variant "secondary") :icon-button-secondary (= variant "secondary")
:icon-button-ghost (= variant "ghost") :icon-button-ghost (= variant "ghost")
:icon-button-action (= variant "action")
:icon-button-destructive (= variant "destructive"))) :icon-button-destructive (= variant "destructive")))
props (mf/spread-props props {:class class :title aria-label})] props (mf/spread-props props {:class class :title aria-label})]
[:> "button" props [:> icon* {:id icon :aria-label aria-label}]])) [:> "button" props [:> icon* {:id icon :aria-label aria-label}]]))

View file

@ -31,3 +31,7 @@
.icon-button-destructive { .icon-button-destructive {
@extend %base-button-destructive; @extend %base-button-destructive;
} }
.icon-button-action {
@extend %base-button-action;
}

View file

@ -26,7 +26,7 @@ export default {
}, },
disabled: { control: "boolean" }, disabled: { control: "boolean" },
variant: { variant: {
options: ["primary", "secondary", "ghost", "destructive"], options: ["primary", "secondary", "ghost", "destructive", "action"],
control: { type: "select" }, control: { type: "select" },
}, },
}, },
@ -59,6 +59,12 @@ export const Ghost = {
}, },
}; };
export const Action = {
args: {
variant: "action",
},
};
export const Destructive = { export const Destructive = {
args: { args: {
variant: "destructive", variant: "destructive",

View file

@ -10,12 +10,16 @@
["lodash.debounce" :as debounce] ["lodash.debounce" :as debounce]
[app.common.colors :as c] [app.common.colors :as c]
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.tokens :as dt] [app.main.data.tokens :as dt]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.color-bullet :refer [color-bullet]] [app.main.ui.components.color-bullet :refer [color-bullet]]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.ds.foundations.typography.text :refer [text*]]
[app.main.ui.workspace.colorpicker :as colorpicker] [app.main.ui.workspace.colorpicker :as colorpicker]
[app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]]
[app.main.ui.workspace.tokens.common :as tokens.common] [app.main.ui.workspace.tokens.common :as tokens.common]
@ -25,6 +29,7 @@
[app.main.ui.workspace.tokens.token :as wtt] [app.main.ui.workspace.tokens.token :as wtt]
[app.main.ui.workspace.tokens.update :as wtu] [app.main.ui.workspace.tokens.update :as wtu]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[cuerdas.core :as str] [cuerdas.core :as str]
[malli.core :as m] [malli.core :as m]
[malli.error :as me] [malli.error :as me]
@ -124,7 +129,7 @@ Token names should only contain letters and digits separated by . characters.")}
[name-ref token tokens callback & {:keys [timeout] :or {timeout 160}}] [name-ref token tokens callback & {:keys [timeout] :or {timeout 160}}]
(let [timeout-id-ref (mf/use-ref nil) (let [timeout-id-ref (mf/use-ref nil)
debounced-resolver-callback debounced-resolver-callback
(mf/use-callback (mf/use-fn
(mf/deps token callback tokens) (mf/deps token callback tokens)
(fn [value] (fn [value]
(let [timeout-id (js/Symbol) (let [timeout-id (js/Symbol)
@ -178,19 +183,22 @@ Token names should only contain letters and digits separated by . characters.")}
[{:keys [result-or-errors]}] [{:keys [result-or-errors]}]
(let [{:keys [errors]} result-or-errors (let [{:keys [errors]} result-or-errors
empty-message? (or (nil? result-or-errors) empty-message? (or (nil? result-or-errors)
(wte/has-error-code? :error/empty-input errors))] (wte/has-error-code? :error/empty-input errors))
[:div {:class (stl/css-case :resolved-value true message (cond
:resolved-value-placeholder empty-message? empty-message? (dm/str (tr "workspace.token.resolved-value") "-")
:resolved-value-error (seq errors))}
(cond
empty-message? "Enter token value"
errors (->> (wte/humanize-errors errors) errors (->> (wte/humanize-errors errors)
(str/join "\n")) (str/join "\n"))
:else [:p result-or-errors])])) :else (dm/str (tr "workspace.token.resolved-value") result-or-errors))]
[:> text* {:as "p"
:typography "body-small"
:class (stl/css-case :resolved-value true
:resolved-value-placeholder empty-message?
:resolved-value-error (seq errors))}
message]))
(mf/defc form (mf/defc form
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [token token-type]}] [{:keys [token token-type action selected-token-set-id]}]
(let [validate-name? (mf/use-state (not (:id token))) (let [validate-name? (mf/use-state (not (:id token)))
token (or token {:type token-type}) token (or token {:type token-type})
color? (wtt/color-token? token) color? (wtt/color-token? token)
@ -212,13 +220,16 @@ Token names should only contain letters and digits separated by . characters.")}
;; Name ;; Name
name-ref (mf/use-var (:name token)) name-ref (mf/use-var (:name token))
name-errors (mf/use-state nil) name-errors (mf/use-state nil)
validate-name (mf/use-callback validate-name
(mf/use-fn
(mf/deps selected-set-tokens-tree) (mf/deps selected-set-tokens-tree)
(fn [value] (fn [value]
(let [schema (token-name-schema {:token token (let [schema (token-name-schema {:token token
:tokens-tree selected-set-tokens-tree})] :tokens-tree selected-set-tokens-tree})]
(m/explain schema (finalize-name value))))) (m/explain schema (finalize-name value)))))
on-update-name-debounced (mf/use-callback
on-update-name-debounced
(mf/use-fn
(debounce (fn [e] (debounce (fn [e]
(let [value (dom/get-target-val e) (let [value (dom/get-target-val e)
errors (validate-name value)] errors (validate-name value)]
@ -226,11 +237,14 @@ Token names should only contain letters and digits separated by . characters.")}
(when-not (and validate-name? (str/empty? value)) (when-not (and validate-name? (str/empty? value))
(reset! validate-name? false) (reset! validate-name? false)
(reset! name-errors errors)))))) (reset! name-errors errors))))))
on-update-name (mf/use-callback
on-update-name
(mf/use-fn
(mf/deps on-update-name-debounced) (mf/deps on-update-name-debounced)
(fn [e] (fn [e]
(reset! name-ref (dom/get-target-val e)) (reset! name-ref (dom/get-target-val e))
(on-update-name-debounced e))) (on-update-name-debounced e)))
valid-name-field? (and valid-name-field? (and
(not @name-errors) (not @name-errors)
(valid-name? @name-ref)) (valid-name? @name-ref))
@ -241,7 +255,8 @@ Token names should only contain letters and digits separated by . characters.")}
value-input-ref (mf/use-ref nil) value-input-ref (mf/use-ref nil)
value-ref (mf/use-var (:value token)) value-ref (mf/use-var (:value token))
token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])) token-resolve-result (mf/use-state (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value]))
set-resolve-value (mf/use-callback set-resolve-value
(mf/use-fn
(fn [token-or-err] (fn [token-or-err]
(let [error? (:errors token-or-err) (let [error? (:errors token-or-err)
v (if error? v (if error?
@ -250,18 +265,19 @@ Token names should only contain letters and digits separated by . characters.")}
(when color? (reset! color (if error? nil v))) (when color? (reset! color (if error? nil v)))
(reset! token-resolve-result v)))) (reset! token-resolve-result v))))
on-update-value-debounced (use-debonced-resolve-callback name-ref token active-theme-tokens set-resolve-value) on-update-value-debounced (use-debonced-resolve-callback name-ref token active-theme-tokens set-resolve-value)
on-update-value (mf/use-callback on-update-value (mf/use-fn
(mf/deps on-update-value-debounced) (mf/deps on-update-value-debounced)
(fn [e] (fn [e]
(let [value (dom/get-target-val e)] (let [value (dom/get-target-val e)]
(reset! value-ref value) (reset! value-ref value)
(on-update-value-debounced value)))) (on-update-value-debounced value))))
on-update-color (mf/use-callback on-update-color (mf/use-fn
(mf/deps on-update-value-debounced) (mf/deps on-update-value-debounced)
(fn [hex-value] (fn [hex-value]
(reset! value-ref hex-value) (reset! value-ref hex-value)
(set! (.-value (mf/ref-val value-input-ref)) hex-value) (set! (.-value (mf/ref-val value-input-ref)) hex-value)
(on-update-value-debounced hex-value))) (on-update-value-debounced hex-value)))
value-error? (seq (:errors @token-resolve-result)) value-error? (seq (:errors @token-resolve-result))
valid-value-field? (and valid-value-field? (and
(not value-error?) (not value-error?)
@ -270,13 +286,14 @@ Token names should only contain letters and digits separated by . characters.")}
;; Description ;; Description
description-ref (mf/use-var (:description token)) description-ref (mf/use-var (:description token))
description-errors (mf/use-state nil) description-errors (mf/use-state nil)
validate-descripion (mf/use-callback #(m/explain token-description-schema %)) validate-descripion (mf/use-fn #(m/explain token-description-schema %))
on-update-description-debounced (mf/use-callback on-update-description-debounced (mf/use-fn
(debounce (fn [e] (debounce (fn [e]
(let [value (dom/get-target-val e) (let [value (dom/get-target-val e)
errors (validate-descripion value)] errors (validate-descripion value)]
(reset! description-errors errors))))) (reset! description-errors errors)))))
on-update-description (mf/use-callback on-update-description
(mf/use-fn
(mf/deps on-update-description-debounced) (mf/deps on-update-description-debounced)
(fn [e] (fn [e]
(reset! description-ref (dom/get-target-val e)) (reset! description-ref (dom/get-target-val e))
@ -288,7 +305,8 @@ Token names should only contain letters and digits separated by . characters.")}
(not valid-value-field?) (not valid-value-field?)
(not valid-description-field?)) (not valid-description-field?))
on-submit (mf/use-callback on-submit
(mf/use-fn
(mf/deps validate-name validate-descripion token resolved-tokens) (mf/deps validate-name validate-descripion token resolved-tokens)
(fn [e] (fn [e]
(dom/prevent-default e) (dom/prevent-default e)
@ -317,12 +335,32 @@ Token names should only contain letters and digits separated by . characters.")}
:description final-description) :description final-description)
:prev-token-name (:name token)})) :prev-token-name (:name token)}))
(st/emit! (wtu/update-workspace-tokens)) (st/emit! (wtu/update-workspace-tokens))
(modal/hide!))))))))] (modal/hide!))))))))
[:form on-delete-token
{:class (stl/css :form-wrapper) (mf/use-fn
(mf/deps selected-token-set-id)
(fn [e]
(dom/prevent-default e)
(modal/hide!)
(st/emit! (dt/delete-token selected-token-set-id (:name token)))))
on-cancel
(mf/use-fn
(fn [e]
(dom/prevent-default e)
(modal/hide!)))]
[:form {:class (stl/css :form-wrapper)
:on-submit on-submit} :on-submit on-submit}
[:div {:class (stl/css :token-rows)} [:div {:class (stl/css :token-rows)}
[:div [:> text* {:as "span" :typography "headline-medium"}
(if (= action "edit")
(tr "workspace.token.edit-token")
(tr "workspace.token.create-token" token-type))]
[:div {:class (stl/css :input-row)}
;; This should be remove when labeled-imput is modified
[:span "Name"]
[:& tokens.common/labeled-input {:label "Name" [:& tokens.common/labeled-input {:label "Name"
:error? @name-errors :error? @name-errors
:input-props {:default-value @name-ref :input-props {:default-value @name-ref
@ -332,9 +370,15 @@ Token names should only contain letters and digits separated by . characters.")}
(for [error (->> (:errors @name-errors) (for [error (->> (:errors @name-errors)
(map #(-> (assoc @name-errors :errors [%]) (map #(-> (assoc @name-errors :errors [%])
(me/humanize))))] (me/humanize))))]
[:p {:key error [:> text* {:as "p"
:key error
:typography "body-small"
:class (stl/css :error)} :class (stl/css :error)}
error])] error])]
[:div {:class (stl/css :input-row)}
;; This should be remove when labeled-imput is modified
[:span "value"]
[:& tokens.common/labeled-input {:label "Value" [:& tokens.common/labeled-input {:label "Value"
:input-props {:default-value @value-ref :input-props {:default-value @value-ref
:on-blur on-update-value :on-blur on-update-value
@ -352,17 +396,33 @@ Token names should only contain letters and digits separated by . characters.")}
[:& ramp {:color (some-> (or @token-resolve-result (:value token)) [:& ramp {:color (some-> (or @token-resolve-result (:value token))
(tinycolor/valid-color)) (tinycolor/valid-color))
:on-change on-update-color}]) :on-change on-update-color}])
[:& token-value-or-errors {:result-or-errors @token-resolve-result}] [:& token-value-or-errors {:result-or-errors @token-resolve-result}]]
[:div
[:div {:class (stl/css :input-row)}
;; This should be remove when labeled-imput is modified
[:span "Description"]
[:& tokens.common/labeled-input {:label "Description" [:& tokens.common/labeled-input {:label "Description"
:input-props {:default-value @description-ref :input-props {:default-value @description-ref
:on-change on-update-description}}] :on-change on-update-description}}]
(when @description-errors (when @description-errors
[:p {:class (stl/css :error)} [:> text* {:as "p"
:typography "body-small"
:class (stl/css :error)}
(me/humanize @description-errors)])] (me/humanize @description-errors)])]
[:div {:class (stl/css :button-row)}
[:button {:class (stl/css :button) [:div {:class (stl/css-case :button-row true
:type "submit" :with-delete (= action "edit"))}
(when (= action "edit")
[:> button* {:on-click on-delete-token
:class (stl/css :delete-btn)
:icon i/delete
:variant "secondary"}
(tr "labels.delete")])
[:> button* {:on-click on-cancel
:variant "secondary"}
(tr "labels.cancel")]
[:> button* {:type "submit"
:variant "primary"
:disabled disabled?} :disabled disabled?}
"Save"]]]])) (tr "labels.save")]]]]))

View file

@ -8,49 +8,56 @@
@import "./common.scss"; @import "./common.scss";
.form-wrapper { .form-wrapper {
width: $s-260; width: $s-384;
} }
.button-row { .button-row {
display: flex; display: grid;
flex-direction: column; grid-template-columns: auto auto;
margin-top: $s-16; justify-content: end;
gap: $s-12;
padding-block-start: $s-8;
}
.with-delete {
grid-template-columns: 1fr auto auto;
}
.delete-btn {
justify-self: start;
} }
.token-rows { .token-rows {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: $s-8; gap: $s-16;
}
.input-row {
display: flex;
flex-direction: column;
gap: $s-4;
} }
.error { .error {
@include bodySmallTypography; padding: $s-4 $s-6;
margin-top: $s-6;
margin-bottom: 0; margin-bottom: 0;
color: var(--status-color-error-500); color: var(--status-color-error-500);
} }
.resolved-value { .resolved-value {
@include bodySmallTypography; --input-hint-color: var(--color-foreground-primary);
margin-bottom: 0;
padding: $s-4 $s-6; padding: $s-4 $s-6;
font-weight: medium; color: var(--input-hint-color);
min-height: 1lh;
color: var(--color-foreground-primary);
border: 1px solid color-mix(in hsl, var(--color-foreground-secondary) 30%, transparent);
p {
font-size: $fs-12;
margin: 0;
}
} }
.resolved-value-placeholder { .resolved-value-placeholder {
color: var(--color-foreground-secondary); --input-hint-color: var(--color-foreground-secondary);
} }
.resolved-value-error { .resolved-value-error {
color: var(--status-color-error-500); --input-hint-color: var(--status-color-error-500);
} }
.color-bullet { .color-bullet {

View file

@ -8,9 +8,12 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.ui.workspace.tokens.modals.themes :as wtmt]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.workspace.tokens.form :refer [form]] [app.main.ui.workspace.tokens.form :refer [form]]
[app.main.ui.workspace.tokens.modals.themes :as wtmt]
[app.util.i18n :refer [tr]]
[okulary.core :as l] [okulary.core :as l]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -40,12 +43,21 @@
(mf/defc token-update-create-modal (mf/defc token-update-create-modal
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [x y position token token-type] :as _args}] [{:keys [x y position token token-type action selected-token-set-id] :as _args}]
(let [wrapper-style (use-viewport-position-style x y position)] (let [wrapper-style (use-viewport-position-style x y position)
[:div close-modal (mf/use-fn
{:class (stl/css :shadow) (fn []
(modal/hide!)))]
[:div {:class (stl/css :token-modal-wrapper)
:style wrapper-style} :style wrapper-style}
[:> icon-button* {:on-click close-modal
:class (stl/css :close-btn)
:icon i/close
:variant "action"
:aria-label (tr "labels.close")}]
[:& form {:token token [:& form {:token token
:action action
:selected-token-set-id selected-token-set-id
:token-type token-type}]])) :token-type token-type}]]))
(mf/defc token-themes-modal (mf/defc token-themes-modal

View file

@ -6,14 +6,19 @@
@import "refactor/common-refactor.scss"; @import "refactor/common-refactor.scss";
.shadow { .token-modal-wrapper {
@extend .modal-container-base; @extend .modal-container-base;
width: auto;
max-width: auto;
min-width: auto;
@include menuShadow; @include menuShadow;
position: absolute; position: absolute;
width: auto;
min-width: auto;
z-index: 11; z-index: 11;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
} }
.close-btn {
position: absolute;
top: $s-6;
right: $s-6;
}

View file

@ -10,8 +10,8 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.transit :as t] [app.common.transit :as t]
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]
[app.main.data.notifications :as ntf]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.notifications :as ntf]
[app.main.data.tokens :as dt] [app.main.data.tokens :as dt]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
@ -33,6 +33,7 @@
[app.main.ui.workspace.tokens.token :as wtt] [app.main.ui.workspace.tokens.token :as wtt]
[app.main.ui.workspace.tokens.token-types :as wtty] [app.main.ui.workspace.tokens.token-types :as wtty]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[app.util.webapi :as wapi] [app.util.webapi :as wapi]
[beicon.v2.core :as rx] [beicon.v2.core :as rx]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -60,8 +61,8 @@
:title (cond :title (cond
errors? (sd/humanize-errors token) errors? (sd/humanize-errors token)
:else (->> [(str "Token: " name) :else (->> [(str "Token: " name)
(str "Original value: " value) (str (tr "workspace.token.original-value") value)
(str "Resolved value: " resolved-value)] (str (tr "workspace.token.resolved-value") resolved-value)]
(str/join "\n"))) (str/join "\n")))
:on-click on-click :on-click on-click
:on-context-menu on-context-menu :on-context-menu on-context-menu
@ -111,6 +112,7 @@
#(st/emit! (dt/set-token-type-section-open type (not open?)))) #(st/emit! (dt/set-token-type-section-open type (not open?))))
on-popover-open-click (mf/use-fn on-popover-open-click (mf/use-fn
(fn [event] (fn [event]
(mf/deps type title)
(let [{:keys [key fields]} modal] (let [{:keys [key fields]} modal]
(dom/stop-propagation event) (dom/stop-propagation event)
(st/emit! (dt/set-token-type-section-open type true)) (st/emit! (dt/set-token-type-section-open type true))
@ -118,6 +120,8 @@
:y (.-clientY ^js event) :y (.-clientY ^js event)
:position :right :position :right
:fields fields :fields fields
:title title
:action "create"
:token-type type})))) :token-type type}))))
on-token-pill-click (mf/use-fn on-token-pill-click (mf/use-fn
@ -175,13 +179,13 @@
:on-click (fn [e] :on-click (fn [e]
(dom/stop-propagation e) (dom/stop-propagation e)
(modal/show! :tokens/themes {}))} (modal/show! :tokens/themes {}))}
(if create? "Create" "Edit")]) (if create? (tr "labels.create") (tr "labels.edit"))])
(mf/defc themes-header (mf/defc themes-header
[_props] [_props]
(let [ordered-themes (mf/deref refs/workspace-token-themes-no-hidden)] (let [ordered-themes (mf/deref refs/workspace-token-themes-no-hidden)]
[:div {:class (stl/css :themes-wrapper)} [:div {:class (stl/css :themes-wrapper)}
[:span {:class (stl/css :themes-header)} "Themes"] [:span {:class (stl/css :themes-header)} (tr "labels.themes")]
[:div {:class (stl/css :theme-select-wrapper)} [:div {:class (stl/css :theme-select-wrapper)}
[:& theme-select] [:& theme-select]
[:& edit-button {:create? (empty? ordered-themes)}]]])) [:& edit-button {:create? (empty? ordered-themes)}]]]))
@ -207,7 +211,7 @@
[:& title-bar {:collapsable true [:& title-bar {:collapsable true
:collapsed (not @open?) :collapsed (not @open?)
:all-clickable true :all-clickable true
:title "SETS" :title (tr "labels.sets")
:on-collapsed #(swap! open? not)} :on-collapsed #(swap! open? not)}
[:& add-set-button {:on-open on-open}]]] [:& add-set-button {:on-open on-open}]]]
(when @open? (when @open?

View file

@ -1993,6 +1993,14 @@ msgstr "Team Leader"
msgid "labels.team-member" msgid "labels.team-member"
msgstr "Team member" msgstr "Team member"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "labels.themes"
msgstr "Themes"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "labels.sets"
msgstr "Sets"
#: src/app/main/ui/dashboard/sidebar.cljs:992, src/app/main/ui/workspace/main_menu.cljs:118 #: src/app/main/ui/dashboard/sidebar.cljs:992, src/app/main/ui/workspace/main_menu.cljs:118
msgid "labels.tutorials" msgid "labels.tutorials"
msgstr "Tutorials" msgstr "Tutorials"
@ -6139,3 +6147,20 @@ msgstr "Update"
#, unused #, unused
msgid "workspace.viewport.click-to-close-path" msgid "workspace.viewport.click-to-close-path"
msgstr "Click to close the path" msgstr "Click to close the path"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.create-token"
msgstr "Create new %s token"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.edit-token"
msgstr "Edit token"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.resolved-value"
msgstr "Resolved value: "
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.original-value"
msgstr "Original value: "

View file

@ -1991,6 +1991,14 @@ msgstr "Líder de equipo"
msgid "labels.team-member" msgid "labels.team-member"
msgstr "Miembro de equipo" msgstr "Miembro de equipo"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "labels.themes"
msgstr "Temas"
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "labels.sets"
msgstr "Sets"
#: src/app/main/ui/dashboard/sidebar.cljs:992, src/app/main/ui/workspace/main_menu.cljs:118 #: src/app/main/ui/dashboard/sidebar.cljs:992, src/app/main/ui/workspace/main_menu.cljs:118
msgid "labels.tutorials" msgid "labels.tutorials"
msgstr "Tutoriales" msgstr "Tutoriales"
@ -6126,3 +6134,20 @@ msgstr "Pulsar para cerrar la ruta"
msgid "errors.maximum-invitations-by-request-reached" msgid "errors.maximum-invitations-by-request-reached"
msgstr "Se ha alcanzado el número máximo (%s) de correos electrónicos que se pueden invitar en una sola solicitud" msgstr "Se ha alcanzado el número máximo (%s) de correos electrónicos que se pueden invitar en una sola solicitud"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.create-token"
msgstr "Crear un token de %s"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.edit-token"
msgstr "Editar token"
#: src/app/main/ui/workspace/tokens/form.cljs
msgid "workspace.token.resolved-value"
msgstr "Valor resuelto: "
#: src/app/main/ui/workspace/tokens/sidebar.cljs
msgid "workspace.token.original-value"
msgstr "Valor original: "