🐛 Fix problem with error detail in toast (#6259)

This commit is contained in:
Alonso Torres 2025-04-09 16:36:11 +02:00 committed by GitHub
parent 82cf474863
commit 28a6797595
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 118 additions and 20 deletions

View file

@ -8,7 +8,10 @@
(:require-macros
[app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf]))
(defn icons-by-level
@ -26,12 +29,14 @@
[:level [:enum :default :info :warning :error :success]]
[:type [:enum :toast :context]]
[:appearance {:optional true} [:enum :neutral :ghost]]
[:is-html {:optional true} :boolean]])
[:is-html {:optional true} :boolean]
[:show-detail {:optional true} [:maybe :boolean]]
[:on-toggle-detail {:optional true} [:maybe fn?]]])
(mf/defc notification-pill*
{::mf/props :obj
::mf/schema schema:notification-pill}
[{:keys [level type is-html appearance children]}]
[{:keys [level type is-html appearance detail children show-detail on-toggle-detail]}]
(let [class (stl/css-case :notification-pill true
:appearance-neutral (= appearance :neutral)
:appearance-ghost (= appearance :ghost)
@ -44,12 +49,27 @@
:level-info (= level :info))
is-html (or is-html false)
icon-id (icons-by-level level)]
[:div {:class class}
[:> i/icon* {:icon-id icon-id :class (stl/css :icon)}]
[:div {:class (dm/str class " " (stl/css :notification-pill))}
[:div {:class (stl/css :error-message)}
[:> i/icon* {:icon-id icon-id :class (stl/css :icon)}]
;; The content can arrive in markdown format, in these cases
;; we will use the prop is-html to true to indicate it and
;; that the html injection is performed and the necessary css classes are applied.
(if is-html
[:div {:class (stl/css :context-text)
:dangerouslySetInnerHTML #js {:__html children}}]
children)]))
;; we will use the prop is-html to true to indicate it and
;; that the html injection is performed and the necessary css classes are applied.
(if is-html
[:div {:class (stl/css :context-text)
:dangerouslySetInnerHTML #js {:__html children}}]
children)]
(when detail
[:div {:class (stl/css :error-detail)}
[:div {:class (stl/css :error-detail-title)}
[:> icon-button*
{:icon (if show-detail "arrow-down" "arrow")
:aria-label (tr "workspace.notification-pill.detail")
:icon-class (stl/css :expand-icon)
:variant "action"
:on-click on-toggle-detail}]
[:div {:on-click on-toggle-detail}
(tr "workspace.notification-pill.detail")]]
(when show-detail
[:div {:class (stl/css :error-detail-content)} detail])])]))

View file

@ -83,3 +83,34 @@
color: var(--notification-icon-color);
margin-block-start: var(--notification-icon-margin);
}
.notification-pill {
display: grid;
max-height: 92vh;
overflow: hidden;
grid-template-rows: auto 1fr;
}
.error-message {
display: flex;
gap: var(--sp-s);
}
.error-detail {
overflow: auto;
}
.error-detail-title {
display: flex;
align-items: center;
cursor: pointer;
}
.expand-icon {
--icon-fill-color: var(--color-foreground-primary);
--icon-stroke-color: var(--color-foreground-primary);
}
.error-detail-content {
padding-left: var(--sp-xxxl);
}

View file

@ -21,12 +21,14 @@
[:level {:optional true} [:maybe [:enum :default :info :warning :error :success]]]
[:appearance {:optional true} [:enum :neutral :ghost]]
[:is-html {:optional true} :boolean]
[:on-close {:optional true} fn?]])
[:show-detail {:optional true} [:maybe :boolean]]
[:on-close {:optional true} fn?]
[:on-toggle-detail {:optional true} [:maybe fn?]]])
(mf/defc toast*
{::mf/props :obj
::mf/schema schema:toast}
[{:keys [class level appearance type is-html children on-close] :rest props}]
[{:keys [class level appearance type is-html children detail show-detail on-close on-toggle-detail] :rest props}]
(let [class (dm/str class " " (stl/css :toast))
level (if (string? level)
(keyword level)
@ -45,9 +47,14 @@
[:> notification-pill* {:level level
:type type
:is-html is-html
:appearance appearance} children]
;; TODO: this should be a buttom from the DS, but this variant is not designed yet.
;; https://tree.taiga.io/project/penpot/task/8492
:appearance appearance
:detail detail
:show-detail show-detail
:on-toggle-detail on-toggle-detail} children]
;; TODO: this should be a buttom from the DS, but this variant is not designed yet.
;; https://tree.taiga.io/project/penpot/task/8492
[:> "button" {:on-click on-close
:aria-label "Close"
:class (stl/css-case :close-button true

View file

@ -17,6 +17,12 @@ export default {
children: {
control: { type: "text" },
},
detail: {
control: { type: "text" },
},
showDetail: {
control: { type: "boolean" },
},
},
args: {
children: "Lorem ipsum",
@ -40,6 +46,14 @@ export const WithLongerText = {
},
};
export const WithDetail = {
args: {
detail:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent lorem ante, bibendum sed ex.",
showDetail: true,
},
};
export const WithHTML = {
args: {
children:

View file

@ -27,7 +27,14 @@
(= :floating (:position notification)))
toast? (or (= :toast (:type notification))
(some? (:timeout notification)))
content (or (:content notification) "")]
content (or (:content notification) "")
show-detail* (mf/use-state false)
handle-toggle-detail
(mf/use-fn
(fn []
(swap! show-detail* not)))]
(when notification
(cond
@ -35,7 +42,10 @@
[:> toast*
{:level (or (:level notification) :info)
:type (:type notification)
:on-close on-close} content]
:detail (:detail notification)
:on-close on-close
:show-detail @show-detail*
:on-toggle-detail handle-toggle-detail} content]
inline?
[:& inline-notification
@ -55,4 +65,5 @@
[:> toast*
{:level (or (:level notification) :info)
:type (:type notification)
:detail (:detail notification)
:on-close on-close} content]))))

View file

@ -14,7 +14,8 @@
:error.import/style-dictionary-reference-errors
{:error/code :error.import/style-dictionary-reference-errors
:error/fn #(str (tr "workspace.token.import-error") "\n\n" (str/join "\n\n" %))}
:error/fn #(str (tr "workspace.token.import-error") "\n\n" (first %))
:error/detail #(str/join "\n\n" (rest %))}
:error.import/style-dictionary-unknown-error
{:error/code :error.import/style-dictionary-reference-errors
@ -74,3 +75,9 @@
(:error/fn err) ((:error/fn err) (:error/value err))
(:error/message err) (:error/message err)
:else err)))))
(defn detail-errors [errors]
(->> errors
(map (fn [err]
(when (:error/detail err)
((:error/detail err) (:error/value err)))))))

View file

@ -16,8 +16,7 @@
[app.main.data.tokens :as dt]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.dropdown-menu :refer [dropdown-menu
dropdown-menu-item*]]
[app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]]
[app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.context :as ctx]
[app.main.ui.ds.buttons.button :refer [button*]]
@ -378,6 +377,7 @@
(fn [err]
(js/console.error err)
(st/emit! (ntf/show {:content (wte/humanize-errors [(ex-data err)])
:detail (wte/detail-errors [(ex-data err)])
:type :toast
:level :error})))))
(-> (mf/ref-val input-ref)

View file

@ -7272,3 +7272,7 @@ msgstr "Autosaved versions will be kept for %s days."
#, unused
msgid "workspace.viewport.click-to-close-path"
msgstr "Click to close the path"
msgid "workspace.notification-pill.detail"
msgstr "Details"

View file

@ -7248,3 +7248,6 @@ msgstr "Los autoguardados duran %s días."
#, unused
msgid "workspace.viewport.click-to-close-path"
msgstr "Pulsar para cerrar la ruta"
msgid "workspace.notification-pill.detail"
msgstr "Detalles"