🐛 Fix color wrapper choppiness (#5655)

* ♻️ Remove unused state om tokens colorpicker ramp component

* 🐛 Fix color wrapper choppiness

*  Add performance related changes for colorpicker ramp selector

*  Add performance oriented changes to tokens ramp component

---------

Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
This commit is contained in:
Andrey Antukh 2025-01-24 09:37:11 +01:00 committed by GitHub
parent cf25614afb
commit 32f0da7514
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 105 additions and 57 deletions

View file

@ -250,6 +250,7 @@
[brightness brightness brightness] [brightness brightness brightness]
(let [sextant (int (mth/floor (/ h 60))) (let [sextant (int (mth/floor (/ h 60)))
remainder (- (/ h 60) sextant) remainder (- (/ h 60) sextant)
brightness (d/nilv brightness 0)
val1 (int (* brightness (- 1 s))) val1 (int (* brightness (- 1 s)))
val2 (int (* brightness (- 1 (* s remainder)))) val2 (int (* brightness (- 1 (* s remainder))))
val3 (int (* brightness (- 1 (* s (- 1 remainder)))))] val3 (int (* brightness (- 1 (* s (- 1 remainder)))))]

View file

@ -33,7 +33,7 @@
[app.main.ui.workspace.colorpicker.harmony :refer [harmony-selector]] [app.main.ui.workspace.colorpicker.harmony :refer [harmony-selector]]
[app.main.ui.workspace.colorpicker.hsva :refer [hsva-selector]] [app.main.ui.workspace.colorpicker.hsva :refer [hsva-selector]]
[app.main.ui.workspace.colorpicker.libraries :refer [libraries]] [app.main.ui.workspace.colorpicker.libraries :refer [libraries]]
[app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector*]]
[app.main.ui.workspace.colorpicker.shortcuts :as sc] [app.main.ui.workspace.colorpicker.shortcuts :as sc]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -346,7 +346,7 @@
[:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :picker-detail-wrapper)}
[:div {:class (stl/css :center-circle)}] [:div {:class (stl/css :center-circle)}]
[:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]] [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
[:& ramp-selector [:> ramp-selector*
{:color current-color {:color current-color
:disable-opacity disable-opacity :disable-opacity disable-opacity
:on-change handle-change-color :on-change handle-change-color

View file

@ -8,6 +8,7 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.colors :as cc] [app.common.colors :as cc]
[app.common.data :as d]
[app.common.math :as mth] [app.common.math :as mth]
[app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-bullet :as cb]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]] [app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
@ -51,48 +52,82 @@
:top (str (* 100 (- 1 (/ value 255))) "%")}}]])) :top (str (* 100 (- 1 (/ value 255))) "%")}}]]))
(mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}] (defn- enrich-color-map
(let [{hex :hex [{:keys [h s v] :as color}]
hue :h saturation :s value :v alpha :alpha} color (let [h (d/nilv h 0)
s (d/nilv s 0)
v (d/nilv v 0)
hsv [h s v]
[r g b] (cc/hsv->rgb hsv)]
(assoc color
:hex (cc/hsv->hex hsv)
:h h :s s :v v
:r r :g g :b b)))
(mf/defc ramp-selector*
[{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
(let [internal-color*
(mf/use-state #(enrich-color-map color))
internal-color
(deref internal-color*)
h (get internal-color :h)
s (get internal-color :s)
v (get internal-color :v)
hex (get internal-color :hex)
alpha (get internal-color :alpha)
bullet-color
(mf/with-memo [hex alpha]
{:color hex :opacity alpha})
on-change-value-saturation on-change-value-saturation
(fn [new-saturation new-value] (mf/use-fn
(let [hex (cc/hsv->hex [hue new-saturation new-value]) (mf/deps internal-color on-change)
[r g b] (cc/hex->rgb hex)] (fn [saturation value]
(on-change {:hex hex (let [color (-> internal-color
:r r :g g :b b (assoc :s saturation)
:s new-saturation (assoc :v value)
:v new-value}))) (enrich-color-map))]
(reset! internal-color* color)
(on-change color))))
on-change-hue on-change-hue
(fn [new-hue] (mf/use-fn
(let [hex (cc/hsv->hex [new-hue saturation value]) (mf/deps internal-color on-change)
[r g b] (cc/hex->rgb hex)] (fn [hue]
(on-change {:hex hex (let [color (-> internal-color
:r r :g g :b b (assoc :h hue)
:h new-hue}))) enrich-color-map)]
(reset! internal-color* color)
(on-change color))))
on-change-opacity on-change-opacity
(fn [new-opacity] (mf/use-fn
(on-change {:alpha new-opacity}))] (mf/deps internal-color on-change)
(fn [opacity]
(let [color (assoc internal-color :alpha opacity)]
(reset! internal-color* color)
(on-change color))))]
[:* [:*
[:& value-saturation-selector [:& value-saturation-selector
{:hue hue {:hue h
:saturation saturation :saturation s
:value value :value v
:on-change on-change-value-saturation :on-change on-change-value-saturation
:on-start-drag on-start-drag :on-start-drag on-start-drag
:on-finish-drag on-finish-drag}] :on-finish-drag on-finish-drag}]
[:div {:class (stl/css :shade-selector) [:div {:class (stl/css :shade-selector)
:style #js {"--bullet-size" "52px"}} :style {:--bullet-size "52px"}}
[:& cb/color-bullet {:color {:color hex [:& cb/color-bullet {:color bullet-color
:opacity alpha}
:area true}] :area true}]
[:div {:class (stl/css :sliders-wrapper)} [:div {:class (stl/css :sliders-wrapper)}
[:& slider-selector {:type :hue [:& slider-selector {:type :hue
:max-value 360 :max-value 360
:value hue :value h
:on-change on-change-hue :on-change on-change-hue
:on-start-drag on-start-drag :on-start-drag on-start-drag
:on-finish-drag on-finish-drag}] :on-finish-drag on-finish-drag}]

View file

@ -19,7 +19,7 @@
[app.main.ui.ds.foundations.typography.heading :refer [heading*]] [app.main.ui.ds.foundations.typography.heading :refer [heading*]]
[app.main.ui.ds.foundations.typography.text :refer [text*]] [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.components.controls.input-token-color-bullet :refer [input-token-color-bullet*]] [app.main.ui.workspace.tokens.components.controls.input-token-color-bullet :refer [input-token-color-bullet*]]
[app.main.ui.workspace.tokens.components.controls.input-tokens :refer [input-tokens*]] [app.main.ui.workspace.tokens.components.controls.input-tokens :refer [input-tokens*]]
[app.main.ui.workspace.tokens.errors :as wte] [app.main.ui.workspace.tokens.errors :as wte]
@ -156,11 +156,8 @@
(defonce form-token-cache-atom (atom nil)) (defonce form-token-cache-atom (atom nil))
(mf/defc ramp (defn hex->value
[{:keys [color on-change]}] [hex]
(let [wrapper-node-ref (mf/use-ref nil)
dragging? (mf/use-state)
hex->value (fn [hex]
(when-let [tc (tinycolor/valid-color hex)] (when-let [tc (tinycolor/valid-color hex)]
(let [hex (str "#" (tinycolor/->hex tc)) (let [hex (str "#" (tinycolor/->hex tc))
[r g b] (c/hex->rgb hex) [r g b] (c/hex->rgb hex)
@ -169,18 +166,33 @@
:r r :g g :b b :r r :g g :b b
:h h :s s :v v :h h :s s :v v
:alpha 1}))) :alpha 1})))
value (mf/use-state (hex->value color))
on-change' (fn [{:keys [hex]}] (mf/defc ramp*
(reset! value (hex->value hex)) [{:keys [color on-change]}]
(when-not (and @dragging? hex) (let [wrapper-node-ref (mf/use-ref nil)
(on-change hex)))] dragging-ref (mf/use-ref false)
(colorpicker/use-color-picker-css-variables! wrapper-node-ref @value)
on-start-drag
(mf/use-fn #(mf/set-ref-val! dragging-ref true))
on-finish-drag
(mf/use-fn #(mf/set-ref-val! dragging-ref false))
on-change'
(mf/use-fn
(mf/deps on-change)
(fn [{:keys [hex]}]
(let [dragging? (mf/ref-val dragging-ref)]
(when-not (and dragging? hex)
(on-change hex)))))]
(colorpicker/use-color-picker-css-variables! wrapper-node-ref (hex->value color))
[:div {:ref wrapper-node-ref} [:div {:ref wrapper-node-ref}
[:& ramp-selector [:> ramp-selector*
{:color @value {:color (hex->value color)
:disable-opacity true :disable-opacity true
:on-start-drag #(reset! dragging? true) :on-start-drag on-start-drag
:on-finish-drag #(reset! dragging? false) :on-finish-drag on-finish-drag
:on-change on-change'}]])) :on-change on-change'}]]))
(mf/defc token-value-or-errors (mf/defc token-value-or-errors
@ -419,7 +431,7 @@
[:> input-token-color-bullet* [:> input-token-color-bullet*
{:color @color :on-click on-display-colorpicker}])] {:color @color :on-click on-display-colorpicker}])]
(when @color-ramp-open? (when @color-ramp-open?
[:& 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}]]