mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 14:42:56 +00:00
🐛 Fix broken attribute on numeric input (#8250)
* 🐛 Fix broken attribute on numeric input * 🐛 Fix tooltip position
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
(def ^:private schema:icon-button
|
||||
[:map
|
||||
[:class {:optional true} :string]
|
||||
[:tooltip-class {:optional true} [:maybe :string]]
|
||||
[:icon-class {:optional true} :string]
|
||||
[:icon
|
||||
[:and :string [:fn #(contains? icon-list %)]]]
|
||||
@@ -28,7 +29,7 @@
|
||||
(mf/defc icon-button*
|
||||
{::mf/schema schema:icon-button
|
||||
::mf/memo true}
|
||||
[{:keys [class icon icon-class variant aria-label children tooltip-placement] :rest props}]
|
||||
[{:keys [class icon icon-class variant aria-label children tooltip-placement tooltip-class] :rest props}]
|
||||
(let [variant
|
||||
(d/nilv variant "primary")
|
||||
|
||||
@@ -49,6 +50,7 @@
|
||||
:aria-labelledby tooltip-id})]
|
||||
|
||||
[:> tooltip* {:content aria-label
|
||||
:class tooltip-class
|
||||
:placement tooltip-placement
|
||||
:id tooltip-id}
|
||||
[:> :button props
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
[app.main.ui.ds.controls.utilities.input-field :refer [input-field*]]
|
||||
[app.main.ui.ds.controls.utilities.token-field :refer [token-field*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list] :as i]
|
||||
[app.main.ui.ds.tooltip :refer [tooltip*]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
@@ -638,27 +637,17 @@
|
||||
:on-change store-raw-value
|
||||
:variant "comfortable"
|
||||
:disabled disabled
|
||||
:slot-start (when (or icon text-icon)
|
||||
:icon icon
|
||||
:aria-label property
|
||||
:slot-start (when text-icon
|
||||
(mf/html
|
||||
[:> tooltip*
|
||||
{:content property
|
||||
:id property}
|
||||
(cond
|
||||
icon
|
||||
[:> icon*
|
||||
{:icon-id icon
|
||||
:size "s"
|
||||
:aria-labelledby property
|
||||
:class (stl/css :icon)}]
|
||||
|
||||
text-icon
|
||||
[:div {:class (stl/css :text-icon)
|
||||
:aria-labelledby property}
|
||||
text-icon])]))
|
||||
[:div {:class (stl/css :text-icon)}
|
||||
text-icon]))
|
||||
:slot-end (when-not disabled
|
||||
(when (some? tokens)
|
||||
(mf/html [:> icon-button* {:variant "ghost"
|
||||
:icon i/tokens
|
||||
:tooltip-class (stl/css :button-tooltip)
|
||||
:class (stl/css :invisible-button)
|
||||
:aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown")
|
||||
:ref open-dropdown-ref
|
||||
@@ -686,23 +675,19 @@
|
||||
:disabled disabled
|
||||
:on-blur on-blur
|
||||
:class inner-class
|
||||
:property property
|
||||
:slot-start (when (or icon text-icon)
|
||||
(mf/html
|
||||
[:> tooltip*
|
||||
{:content property
|
||||
:id property}
|
||||
(cond
|
||||
icon
|
||||
[:> icon*
|
||||
{:icon-id icon
|
||||
:size "s"
|
||||
:aria-labelledby property
|
||||
:class (stl/css :icon)}]
|
||||
(cond
|
||||
icon
|
||||
[:> icon*
|
||||
{:icon-id icon
|
||||
:size "s"
|
||||
:class (stl/css :icon)}]
|
||||
|
||||
text-icon
|
||||
[:div {:class (stl/css :text-icon)
|
||||
:aria-labelledby property}
|
||||
text-icon])]))
|
||||
text-icon
|
||||
[:div {:class (stl/css :text-icon)}
|
||||
text-icon])))
|
||||
:token-wrapper-ref token-wrapper-ref
|
||||
:token-detach-btn-ref token-detach-btn-ref
|
||||
:detach-token detach-token})))]
|
||||
@@ -737,40 +722,21 @@
|
||||
(mf/with-effect [dropdown-options]
|
||||
(mf/set-ref-val! options-ref dropdown-options))
|
||||
|
||||
(if (some? icon)
|
||||
[:div {:class [class (stl/css :input-wrapper)]
|
||||
:ref wrapper-ref}
|
||||
[:div {:class [class (stl/css :input-wrapper)]
|
||||
:ref wrapper-ref}
|
||||
|
||||
(if (and (some? token-applied)
|
||||
(not= :multiple token-applied))
|
||||
[:> token-field* token-props]
|
||||
[:> input-field* input-props])
|
||||
(if (and (some? token-applied)
|
||||
(not= :multiple token-applied))
|
||||
[:> token-field* token-props]
|
||||
[:> input-field* input-props])
|
||||
|
||||
(when ^boolean is-open
|
||||
(let [options (if (delay? dropdown-options) @dropdown-options dropdown-options)]
|
||||
[:> options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options options
|
||||
:selected selected-id
|
||||
:focused focused-id
|
||||
:align align
|
||||
:empty-to-end empty-to-end
|
||||
:ref set-option-ref}]))]
|
||||
[:div {:class [class (stl/css :input-wrapper)]
|
||||
:ref wrapper-ref}
|
||||
|
||||
(if (and (some? token-applied)
|
||||
(not= :multiple token-applied))
|
||||
[:> token-field* token-props]
|
||||
[:> input-field* input-props])
|
||||
|
||||
(when ^boolean is-open
|
||||
(let [options (if (delay? dropdown-options) @dropdown-options dropdown-options)]
|
||||
[:> options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options options
|
||||
:selected selected-id
|
||||
:focused focused-id
|
||||
:align align
|
||||
:empty-to-end empty-to-end
|
||||
:ref set-option-ref}]))])))
|
||||
(when ^boolean is-open
|
||||
(let [options (if (delay? dropdown-options) @dropdown-options dropdown-options)]
|
||||
[:> options-dropdown* {:on-click on-option-click
|
||||
:id listbox-id
|
||||
:options options
|
||||
:selected selected-id
|
||||
:focused focused-id
|
||||
:align align
|
||||
:empty-to-end empty-to-end
|
||||
:ref set-option-ref}]))]))
|
||||
|
||||
@@ -55,3 +55,8 @@
|
||||
--opacity-button: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.button-tooltip {
|
||||
inline-size: var($sz-28);
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
type (d/nilv type "text")
|
||||
variant (d/nilv variant "dense")
|
||||
tooltip-id (mf/use-id)
|
||||
|
||||
props (mf/spread-props props
|
||||
{:class [class
|
||||
(stl/css-case
|
||||
@@ -54,15 +53,11 @@
|
||||
"true")
|
||||
:aria-describedby (when has-hint
|
||||
(str id "-hint"))
|
||||
:aria-labelledby tooltip-id
|
||||
:type (d/nilv type "text")
|
||||
:id id
|
||||
:max-length (d/nilv max-length max-input-length)})
|
||||
|
||||
props (if (and aria-label (not (some? icon)))
|
||||
(mf/spread-props props
|
||||
{:aria-label aria-label})
|
||||
(mf/spread-props props
|
||||
{:aria-labelledby tooltip-id}))
|
||||
inside-class (stl/css-case :input-wrapper true
|
||||
:has-hint has-hint
|
||||
:hint-type-hint (= hint-type "hint")
|
||||
@@ -83,11 +78,14 @@
|
||||
(when (some? slot-start)
|
||||
slot-start)
|
||||
(when (some? icon)
|
||||
(if aria-label
|
||||
[:> tooltip* {:content aria-label
|
||||
:id tooltip-id}
|
||||
[:> icon* {:icon-id icon :class (stl/css :icon) :on-click on-icon-click}]]
|
||||
[:> icon* {:icon-id icon :class (stl/css :icon) :on-click on-icon-click}]))
|
||||
[:> "input" props]
|
||||
[:> icon* {:icon-id icon
|
||||
:class (stl/css :icon)
|
||||
:size "s"
|
||||
:on-click on-icon-click}])
|
||||
(if aria-label
|
||||
[:> tooltip* {:content aria-label
|
||||
:id tooltip-id}
|
||||
[:> "input" props]]
|
||||
[:> "input" props])
|
||||
(when (some? slot-end)
|
||||
slot-end)]))
|
||||
|
||||
@@ -118,4 +118,5 @@
|
||||
|
||||
.icon {
|
||||
color: var(--color-foreground-secondary);
|
||||
min-inline-size: var(--sp-l);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
[:class {:optional true} [:maybe :string]]
|
||||
[:id {:optional true} [:maybe :string]]
|
||||
[:label {:optional true} [:maybe :string]]
|
||||
[:property {:optional true} [:maybe :string]]
|
||||
[:value :any]
|
||||
[:disabled {:optional true} :boolean]
|
||||
[:slot-start {:optional true} [:maybe some?]]
|
||||
@@ -35,7 +36,7 @@
|
||||
{::mf/schema schema:token-field}
|
||||
[{:keys [id label value slot-start disabled class
|
||||
on-click on-token-key-down on-blur detach-token
|
||||
token-wrapper-ref token-detach-btn-ref on-focus]}]
|
||||
token-wrapper-ref token-detach-btn-ref on-focus property]}]
|
||||
(let [set-active? (some? id)
|
||||
content (if set-active?
|
||||
label
|
||||
@@ -50,37 +51,42 @@
|
||||
(when-not ^boolean disabled
|
||||
(dom/prevent-default event)
|
||||
(dom/focus! (mf/ref-val token-wrapper-ref)))))]
|
||||
[:> tooltip* {:content property
|
||||
:class (stl/css :token-field-wrapper)
|
||||
:id (dm/str default-id "-input")}
|
||||
[:div {:class [class (stl/css-case :token-field true
|
||||
:with-icon (some? slot-start)
|
||||
:token-field-disabled disabled)]
|
||||
:on-click focus-wrapper
|
||||
:disabled disabled
|
||||
:on-key-down on-token-key-down
|
||||
:ref token-wrapper-ref
|
||||
:on-blur on-blur
|
||||
:on-focus on-focus
|
||||
:aria-labelledby (dm/str default-id "-input")
|
||||
:tab-index (if disabled -1 0)}
|
||||
|
||||
[:div {:class [class (stl/css-case :token-field true
|
||||
:with-icon (some? slot-start)
|
||||
:token-field-disabled disabled)]
|
||||
:on-click focus-wrapper
|
||||
:disabled disabled
|
||||
:on-key-down on-token-key-down
|
||||
:ref token-wrapper-ref
|
||||
:on-blur on-blur
|
||||
:on-focus on-focus
|
||||
:tab-index (if disabled -1 0)}
|
||||
(when (some? slot-start) slot-start)
|
||||
|
||||
(when (some? slot-start) slot-start)
|
||||
[:div {:class (stl/css :content-wrapper)}
|
||||
[:> tooltip* {:content content
|
||||
:id (dm/str id "-pill")}
|
||||
[:button {:on-click on-click
|
||||
:class (stl/css-case :pill true
|
||||
:no-set-pill (not set-active?)
|
||||
:pill-disabled disabled)
|
||||
:disabled disabled
|
||||
:aria-labelledby (dm/str id "-pill")
|
||||
:on-key-down on-token-key-down}
|
||||
value
|
||||
(when-not set-active?
|
||||
[:div {:class (stl/css :pill-dot)}])]]]
|
||||
|
||||
[:> tooltip* {:content content
|
||||
:id (dm/str id "-pill")}
|
||||
[:button {:on-click on-click
|
||||
:class (stl/css-case :pill true
|
||||
:no-set-pill (not set-active?)
|
||||
:pill-disabled disabled)
|
||||
:disabled disabled
|
||||
:aria-labelledby (dm/str id "-pill")
|
||||
:on-key-down on-token-key-down}
|
||||
value
|
||||
(when-not set-active?
|
||||
[:div {:class (stl/css :pill-dot)}])]]
|
||||
|
||||
(when-not ^boolean disabled
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:class (stl/css :invisible-button)
|
||||
:icon i/broken-link
|
||||
:ref token-detach-btn-ref
|
||||
:aria-label (tr "ds.inputs.token-field.detach-token")
|
||||
:on-click detach-token}])]))
|
||||
(when-not ^boolean disabled
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:class (stl/css :invisible-button)
|
||||
:tooltip-class (stl/css :button-tooltip)
|
||||
:icon i/broken-link
|
||||
:ref token-detach-btn-ref
|
||||
:aria-label (tr "ds.inputs.token-field.detach-token")
|
||||
:on-click detach-token}])]]))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
@use "ds/typography.scss" as t;
|
||||
@use "ds/colors.scss" as *;
|
||||
@use "ds/mixins.scss" as *;
|
||||
@use "ds/_utils.scss" as *;
|
||||
|
||||
.token-field {
|
||||
--token-field-bg-color: var(--color-background-tertiary);
|
||||
@@ -37,6 +38,9 @@
|
||||
--token-field-outline-color: var(--color-accent-primary);
|
||||
}
|
||||
}
|
||||
.token-field-wrapper {
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
.with-icon {
|
||||
grid-template-columns: auto 1fr;
|
||||
@@ -132,3 +136,12 @@
|
||||
--opacity-button: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
.button-tooltip {
|
||||
inline-size: px2rem(28);
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
|
||||
(def ^:private schema:tooltip
|
||||
[:map
|
||||
[:class {:optional true} :string]
|
||||
[:class {:optional true} [:maybe :string]]
|
||||
[:id {:optional true} :string]
|
||||
[:offset {:optional true} :int]
|
||||
[:delay {:optional true} :int]
|
||||
@@ -184,6 +184,7 @@
|
||||
[{:keys [class id children content placement offset delay] :rest props}]
|
||||
(let [internal-id
|
||||
(mf/use-id)
|
||||
trigger-ref (mf/use-ref nil)
|
||||
|
||||
id
|
||||
(d/nilv id internal-id)
|
||||
@@ -204,19 +205,23 @@
|
||||
(mf/use-fn
|
||||
(mf/deps id placement offset)
|
||||
(fn [event]
|
||||
(clear-schedule schedule-ref)
|
||||
(when-let [tooltip (dom/get-element id)]
|
||||
(let [origin-brect
|
||||
(->> (dom/get-target event)
|
||||
(dom/get-bounding-rect))
|
||||
|
||||
update-position
|
||||
(fn []
|
||||
(let [new-placement (update-tooltip-position tooltip placement origin-brect offset)]
|
||||
(when (not= new-placement placement)
|
||||
(reset! placement* new-placement))))]
|
||||
(let [current (dom/get-current-target event)
|
||||
related (dom/get-related-target event)
|
||||
is-node? (fn [node] (and node (.-nodeType node)))]
|
||||
(when-not (and related (is-node? related) (.contains current related))
|
||||
(clear-schedule schedule-ref)
|
||||
(when-let [tooltip (dom/get-element id)]
|
||||
(let [origin-brect
|
||||
(dom/get-bounding-rect (mf/ref-val trigger-ref))
|
||||
|
||||
(add-schedule schedule-ref delay update-position)))))
|
||||
update-position
|
||||
(fn []
|
||||
(let [new-placement (update-tooltip-position tooltip placement origin-brect offset)]
|
||||
(when (not= new-placement placement)
|
||||
(reset! placement* new-placement))))]
|
||||
|
||||
(add-schedule schedule-ref delay update-position)))))))
|
||||
|
||||
on-hide
|
||||
(mf/use-fn
|
||||
@@ -252,6 +257,7 @@
|
||||
:on-focus on-show
|
||||
:on-blur on-hide
|
||||
:on-key-down handle-key-down
|
||||
:ref trigger-ref
|
||||
:class [class (stl/css :tooltip-trigger)]
|
||||
:aria-describedby id})
|
||||
content
|
||||
|
||||
Reference in New Issue
Block a user